xikka

A collection of things I have made and things I find interesting.


Some game engines

Friday, 17th July 2020 ◆ Clumsy alibi errs in staying silent here (9)

I thoroughly enjoy trying out new game development engines, and as a consequence have tinkered with many of them.

The most important features for an engine for me are:

All of the engines I mention satisfy these criteria, and are the engines I consider to be the major players:

LibGDX

LibGDX in IntelliJ

LibGDX is a Java-based game framework which can deploy to iOS, Android, HTML5 and Desktop. The HTML5 export is quite slow to produce and requires special effort when coding for all platforms, but once exported, it is reliable and fast.

Deploying to iOS and HTML5 is not always plain sailing. I have had plenty of obscure error messages for which I’ve had to employ heavy use of Google, but once it works, it works smoothly. There’s also a sizable community of LibGDX developers, so the rare problems do get spotted and fixed quickly. I’ve had to make local changes to the LibGDX source too.

There is no inbuilt WYSIWYG editor and everything is done with code. If that turns you off, LibGDX is not the engine for you. I find it easy to create organised and extensible code with LibGDX, and that probably stems from my liking of Java.

One of the biggest reasons I like LibGDX so much is the Scene2D API. It gives you a hierarchy of Actors. If you rotate, scale or translate one Actor, all of its children will also be subjected to the same transformations. Scene2D also includes the concept of Actions which let you chain multiple animations or translations in a really elegant way. Want to move a sprite across the screen whilst changing its colour to green. Then, once it gets to the end, fade it out and then remove it from its parent? No problem:

sprite.addAction(Actions.sequence(
    Actions.parallel(Actions.moveBy(500, 0, 0.5f), Actions.color(Color.GREEN, 0.5f)),
    Actions.fadeOut(0.5f),
    Actions.removeActor()
));

Another point is that you don’t get direct access to memory. There is a garbage collector, even when run on iOS. In most cases, you won’t notice, but if you are creating a lot of garbage every frame, you may notice stutters on iOS and should be aware of the why. These are things which won’t be a problem if you are aware of them and understand them, but for a beginner, it may be confusing.

Code snippet

private ScorePanel addScorePanel() {
    ScorePanel sp = new ScorePanel(mode);
    sp.setSize(scorePanelHolder.getWidth(), scorePanelHolder.getHeight());
    scorePanelHolder.addActor(sp);
    sp.getColor().a = 0;
    sp.addAction(Actions.fadeIn(0.3f, Interpolation.pow2Out));
    return sp;
}

Godot

Godot

Godot offers a complete editor with many premade components which can be dragged and dropped onto the stage. There is also a specific anchoring system for responsive layout of GUI elements, allowing development for multiple screen resolutions at once.

Personally, I didn’t like the dynamic typing of GDScript. There is the option is available to use C# or C++ instead, but this does require the use of an external editor.

Compiling to other platforms is a complete breeze, and of all the engines I will talk about, is the fastest and easiest to do this with. The HTML5 export takes mere seconds, and running the game from the editor takes even less. Whilst you are running the game in the editor, you can make changes to the game code, and they will be loaded live.

I found Godot simultaneously made some things trivial, and other things really difficult. There is no easy-to-use Actions system like in LibGDX. Non-GUI actors do not have a size, so determining when the user clicks on them is not straightforward. Singletons feel quite shoehorned in, and the API has changed quite a lot during it's brief lifetime meaning online examples are often dated.

The documentation is adequate, but often doesn't go into enough depth. If you want a GUI, I would recommend Godot.

Code snippet

func load_session():
    var http_request = HTTPRequest.new()
    http_request.connect("request_completed", self, "_load_session_request_completed", [http_request])
    add_child(http_request)
    var error = http_request.request(session_url(), headers(), false, HTTPClient.METHOD_GET)
    if error != OK:
        push_error("An error occurred in the session HTTP request.")
        emit_signal("error", "Could not make session request.")

Cocos2d-x

Cocos2d-x in Xcode

Cocos2d-x has an easy-to-use API. From my perspective, its biggest advantage is that your project simply contains the Cocos2d-x source code, and when you build, you compile it with your game. It means you can code in Xcode for iOS, and all the standard Apple build tools apply. There are no special tricks for adding things like app icons.

However, there is no compilation to HTML5. There is a JS version of Cocos2d which does also compile to web, but I prefer to avoid Javascript when I can.

Cocos2d-x is nice to use, and I would recommend it if you are familiar with C++, want to target Android and iOS and have no plans for Web. The building process is easier than LibGDX in my opinion, but the API is not as elegant.

Code snippet

Attack *Monster::getAttack() {
    // pick a random int up to the sum
    int pivot = rand() % total_attack_ratio;
    int current = 0;
    for (Attack *attack : attacks) {
        current += attack->ratio;
        if (pivot < current) {
            return attack;
        }
    }
    // should never happen!
    return attacks[0];
}

PixiJS

PixiJS in Atom

PixiJS is a javascript based engine. It has a simple hierarchical API which I found quite easy to use, and reminiscent of Flash. It’s possible to deploy it to mobile using something like Cordova, and I found it will run without problem directly in phone browsers too.

I wouldn’t choose to use it again for a big project, due to my aversion to Javascript. However, for a little browser game I would definitely recommend it.

Code snippet

function Particle(name) {
  let texture = name;
  PIXI.Sprite.call(this, PIXI.loader.resources[texture].texture);
  this.dx = 0;
  this.dy = 0;
  this.dr = 0;
}
Particle.prototype.tick = function(delta) {
    this.rotation += this.dr;
    this.position.x += this.dx;
    this.position.y += this.dy;
};

Comments

There are no comments yet.