Godot Engine 2.0 Released



The Godot Game Engine reaches version 2.0 with many new features (check the Godot News for more info):

- Improved scene instancing and scene inheritance.
- Editor with new layout and theme.
- Live scene editing.
- New tools layout with Output Console, better Debugger and Animation Editor.
- New text-based scene format (.tscn).
- Multiple scene editing support.
- Onready keyword and singletons.
- Very improved gamepad support.
- New file dialog and filesystem dock.
- Improved code editor.
- Several bug fixes and minor improvements.



Godot is an advanced, feature packed, multi-platform 2D and 3D open source game engine. It provides a huge set of common tools, so you can just focus on making your game without reinventing the wheel.

Vibrant Recycling 1.1.1 Launched


Vibrant Recycling 1.1.1 launched, with minor tweaks!

Upgrading to melonJS 2.1


With the release of melonJS 2.1, is time to conduct a upgrade to this solid version of the engine, with nice features as:

- New screen independent scaling methods
- Improved collision handling and detection
- Support for Physics Editor tool, to define entities collision shapes
- Added support for pointerenter and pointerleave events
- High-precision color transform with more accurate color effects
- Several improvements in the WebGL renderer (reached a beta quality level)
- Added support for the new Tiled 0.11 object id property
- Fixed various bugs and issues

Check the melonJS Blog for a official announcement and get the lastest version in melonJS Site.

The recommended is to migrate the current version used in the game to one immediately more recent facilitating the upgrade process (some melonJS versions have API breaks). For example, if your game uses melonJS 1.0.2, you need to update first to 1.1.0 version (check the post Upgrading to melonJS 1.1), after to 2.0.2 version (check the post Upgrading to melonJS 2.0) and finally to 2.1.3 version.

Below we will check some of the necessary changes to upgrade from melonJS 2.0.2 (previous version) to melonJS 2.1.4 (current version when writing this post). For a complete list of changes visit the melonJS Upgrade Guide.


Before the Upgrade


The melonJS 2.1 is a major release and include some breaking changes which forces you to make adjustments in your game code.

Before starting the migration, check the Upgrade Guide and the Changelog of engine and decide if the amount of work for the upgrade compensates the new features of this melonJS version!

Don't forget to always have a backup of the last game version before starting the upgrade process!


Piece of Cake


Start renaming the functions, objects and variables changed in this version, which can be easily performed via a Search and Replace (or Refactor) available in your preferred Code Editor (or IDE):

// Old Code -> New Code
spritewidth -> framewidth
spriteheight -> frameheight
me.TextureAtlas -> me.video.renderer.Texture
me.video.shader.gltexture2d() -> me.video.shader.createTexture()
The me.video.init has arguments more flexible and robust requiring three params: width, height and a list of properties for the various options (the pattern function(x, y, {settings}) for constructors signature will be applied to others melonJS functions in future):

// Before melonJS 2.1
me.video.init("screen", me.video.CANVAS, 800, 600, true, "auto", false);

// After melonJS 2.1
me.video.init(800, 600, {
    wrapper: "screen", 
    renderer: me.video.CANVAS,     
    scale: "auto", 
    scaleMethod: "fill-max",
    doubleBuffering: true,
    transparent: true
}); 
The new and functional scaling mode is enabled through the scaleMethod param set in me.video.init and are detailed in the melonJS Blog:

- fit (default): Letterboxed; content is scaled to design aspect ratio.
fill-max: Canvas is resized to fit maximum design resolution; content is scaled to design aspect ratio.
- flex-width: Canvas width is resized to fit; content is scaled to design aspect ratio.
flex-height: Canvas height is resized to fit; content is scaled to design aspect ratio.
- stretch: Canvas is resized to fit; content is scaled to screen aspect ratio.

Check also the addition of the "transparent" parameter to enable support for the new opaque canvas feature and the removal of the old maintainAspectRatio replaced by the new scaling method.

The me.sys.scalingInterpolation setting for enable or disable the anti-aliasing is avaliable now directly in the me.video.init antiAlias params:

// Before melonJS 2.1
me.sys.scalingInterpolation = true;

// After melonJS 2.1
me.video.init(800, 600, {
    wrapper: "screen", 
    renderer: me.video.CANVAS,
    doubleBuffering: true, 
    scale: "auto",      
    antiAlias: true
});


Let's Rock


In order to standardize objects constructor in melonJS, me.Sprite, me.AnimationSheet and me.ImageLayer signature have been update to follow the pattern function(x, y, {settings}):

// Before melonJS 2.1
var sprite = new me.Sprite(20, 80, me.loader.getImage("image"));
var animationSheet = new me.AnimationSheet(30, 50, image: me.loader.getImage("animationsheet"), spritewidth: 32, spriteheight: 32});

// After melonJS 2.1
var sprite = new me.Sprite(20, 80, {
   image: me.loader.getImage("image")
});

var animationSheet = new me.AnimationSheet(30, 50, {
  image: me.loader.getImage("animationsheet"),
  framewidth: 32,
  frameheight: 32
});
Most keywords and name lookups have been made case-sensitive now. This affects file names, pooling, and container child searches and may give more or less work as the patterns used in your project. To perform a case-insensitive search, you can use Javascript RegExp in container child searches:

// Before melonJS 2.1 - Get objects named "Player" or "player"
me.game.world.getChildByProp("name", "PLAYER");

// After melonJS 2.1 - Use the RegExp for Case Insensitive Search
me.game.world.getChildByProp("name", /player/i);
Lastly, remove the references to body.updateBounds() because this function is automatically called by the engine now, providing an extra facility to the developer.


Work Done


After the completion of the steps above, you must run the game performing various tests to detect possible adjustments or fixes to be made. For possible questions, use the melonJS Forum or analyze directly the source code on GitHub Repo.

The practical and functional screen scaling modes, the better support to WebGL and the easy migration proccess (if compared with the whirlwind of changes and new features introduced with melonJS versions 1.1 and 2.0), make the upgrade a good and right choice. And you can enjoy to review some "obscure" or "hackish" code, using the best practices you acquired in recent times or to implement new features in your game.

ZEEF Game Assets

https://game-assets.zeef.com/andre.antonio.schmitz

Check this awesome ZEEF curated directory with several resources and tools for creating assets used in games as graphics, sounds, video, maps and others.


ZEEF is a place where you find and create lists of links about your favourite topics. It's a very powerful way to share information where everybody wins!

Upgrading to melonJS 2.0


With the release of melonJS 2.0, is time to conduct a upgrade to this solid and awesome version of the engine, packed with nice features, as:

- New Shape based collision (replaced the Tile based collision)
- Added support for Tiled 0.10 allowing shape transforms (scaling and rotation) and TMX Tileset Animations
- Automatic collision response handling
- Physics bodies now support multiple shapes
- Many fixes and improvements with collision detection in isometric maps
- Initial WebGL support (alpha quality)
- Fixed various bugs and issues

Check the the melonJS Blog for a official announcement and get the lastest version in melonJS Site.

The recommended is to migrate the current version used in the game to one immediately more recent facilitating the upgrade process (some melonJS versions have API breaks). For example, if your game uses melonJS 1.0.2, you need to update first to 1.1.0 version (check the post Upgrading to melonJS 1.1) and after to 2.0.2 version.

Below we will check some of the necessary changes to upgrade from melonJS 1.1.0 (previous version) to melonJS 2.0.2 (current version when writing this post). For a complete list of changes visit the melonJS Upgrade Guide.


Before the Upgrade


The melonJS 2.0 ends a cycle of major changes started from version 1.0, in order to make the engine most concise, fast, robust, cleaner and future proof, with the replacement of the naive collision mechanism. It's a major release and include some breaking changes so you should do adjustments in your game code. Probably, the most work to be done for this version is the adjustment of all Tiled maps, due the replacement of Tile based collision to Shape based collision, finalizing the implementing of the new collision mechanism!

Before starting the migration, check the Upgrade Guide and the Changelog of engine and decide if the amount of work for the upgrade compensates the incredible new features of this melonJS version!

Don't forget to always have a backup of the last game version before starting the upgrade process!


Piece of Cake


Start renaming the functions, objects and variables changed in this version, which can be easily performed via a Search and Replace (or Refactor) available in your preferred Code Editor (or IDE):

// Old Code -> New Code
debugPanel -> me.debug.Panel
me.Sprite.resize() -> me.Sprite.scale()
me.PolyShape -> me.Polygon
me.game.world.collide -> me.collision.check
The me.Body now supports multiple shapes and the me.Body.getShape() function now needs an index as argument, returning the shape specified at the index:

// Before melonJS 2.0 - Body has only one shape
var bounds = this.body.getShape().bounds;

// After melonJS 2.0 - Body has only one shape, see index = 0
var bounds = this.body.getShape(0).bounds;
The functions flipX and flipY have been removed from me.Entity and me.Body and are available only through the entity renderable component:

// Before melonJS 2.0
game.Entity = me.Entity.extend({
    init: function(x, y, settings){
        // Call the constructor
        this._super(me.Entity, 'init', [x, y , settings]);

        // Set the entity renderable
        this.renderable = game.texture.createSpriteFromName("sign.png");

        // Check for entity renderable flip - passed as constructor param
        this.flipX(settings.flip); 
    }
});

// After melonJS 2.0
game.Entity = me.Entity.extend({
    init: function(x, y, settings){
        // Call the constructor
        this._super(me.Entity, 'init', [x, y , settings]);

        // Set the entity renderable
        this.renderable = game.texture.createSpriteFromName("sign.png");

        // Check for entity renderable flip - passed as constructor param
        this.renderable.flipX(settings.flip); 
    }
});
Update the HUD pattern making it a floating container, because a bug in previous version allowed non-floating containers to always be within the viewport. For this, only add this.floating = true; in the HUD Container init function.


Let's Rock


With the new collision mechanism, the entities now automatically respond to collision, not requiring that me.Body have a explicit onCollision function callback, being necessary directly in me.Entity:

// Before melonJS 2.0
var entity = me.Entity.extend({
    init: function(x, y, settings) {
        // Call the constructor
        this._super(me.Entity, 'init', [x, y , settings]);

        // Set the default velocity
        this.body.setVelocity(3, 15);

        // Set the collision callback function
        this.body.onCollision = this.onCollision.bind(this); 
    },
   
    // Update logic
    update: function(dt) {
        // Change velocity 
        this.body.vel.x -= this.body.accel.x * me.timer.tick;
 
        // Apply physics to the body (this moves the entity)
        this.body.update();

        // Handle collisions against other shapes
        me.collision.check(this, true, this.collideHandler.bind(this), true);

        this._super(me.Entity, "update", [dt]);
        return true; 
    },

    // Collision handler
    collideHandler: function(response) {
        // Check for collision with enemy
        if (response.b.body.collisionType === me.collision.types.ENEMY_OBJECT) { 
            // Change velocity 
            this.body.vel.y -= this.body.maxVel.y * me.timer.tick;

            // Change position
            this.pos.x -= 20;

            // Update the entity bounds since we manually changed the position
            this.updateBounds();
        }
    },

    // Collision callback
    onCollision: function(res, obj) {
        // Disable collision
        this.body.setCollisionMask(me.collision.types.NO_OBJECT);

        // Remove from game
        me.game.world.removeChild(this);
    }
});
In this way, the callbacks used in this.body.onCollision and me.collision.check() are joined into a single callback onCollision defined in me.Entity (check the new signature of me.collision.check() function in the Online Documentation):

// After melonJS 2.0
var entity = me.Entity.extend({
    init: function(x, y, settings) {
        // Call the constructor
        this._super(me.Entity, 'init', [x, y , settings]);

        // Set the default velocity
        this.body.setVelocity(3, 15);       
    },
   
    // Update logic
    update: function(dt) {
        // Change velocity 
        this.body.vel.x -= this.body.accel.x * me.timer.tick;
 
        // Apply physics to the body (this moves the entity)
        this.body.update();

        // Handle collisions against other shapes
        me.collision.check(this);

        this._super(me.Entity, "update", [dt]);
        return true; 
    },    

    // Collision callback
    onCollision: function(response, other) {
        // Check for collision with enemy
        if (other.body.collisionType === me.collision.types.ENEMY_OBJECT) { 
            // Change velocity 
            this.body.vel.y -= this.body.maxVel.y * me.timer.tick;

            // Change position
            this.pos.x -= 20;

            // Update the entity bounds since we manually changed the position
            this.updateBounds();
        }

        // Disable collision
        this.body.setCollisionMask(me.collision.types.NO_OBJECT);

        // Remove from game
        me.game.world.removeChild(this);
    }
});
The Number.prototype.random(min, max) function has changed to match the standard Javascript function Math.random(), using the range [min, max), i.e, from min (inclusive) up to but not including max (exclusive):

// Before melonJS 2.0 - Random Number between 0 and 5
var random = Number.prototype.random(0, 5);

// After melonJS 2.0 - Random Number between 0 and 5 (Normal Syntax)
var random = Number.prototype.random(0, 6);

// After melonJS 2.0 - Random Number between 0 and 5 (Short Syntax)
var random = (0).random(6);


Come Get Some


Completing the new changes to collision system, the legacy Tile based collision mechanism has been replaced with a Shape based collision mechanism, using the same SAT implementation of the entities (added in version 1.1). This change requires adjusting the layer collision of all maps from Tiled, which can be a time consuming work, depending on the complexity and number of maps!

Before melonJS 2.0, you used a Tiled Tile Layer to define the world collision shapes, in accordance with the tiles types supported by engine (using the "metatiles" solid, platform, ladder, slope and breakable):

Tiled Level with Tiles Collision Layer

After melonJS 2.0, you should use a Tiled Object Layer and the world collision shapes can be defined using all standard objects from Tiled, like Polyline, Polygon (only convex with clockwise winding) and Ellipse, giving greater freedom and creativity to define the game collisions, not getting stuck with fixed shapes!

Tiled Level with Shape Collision Layer

Remember that you must use a Tiled Object Layer with name "collision" so the engine detects the collision layer properly. With this change in collision shapes the engine no more support builtin Platforms and Ladders tiles and they must be implemented using the new onCollision response callback:

// melonJS 2.0 - me.Entity onCollision callback
onCollision: function(response, other) {
    if (other.body.collisionType === me.collision.types.WORLD_SHAPE) {
        // Simulate a platform - property defined in Tiled Object
        if (other.type === "platform") {
            if (this.body.falling && !me.input.isKeyPressed('down') &&
               (response.overlapV.y > 0) && 
               (~~this.body.vel.y >= ~~response.overlapV.y)) {
                // Disable collision on the x axis
                response.overlapV.x = 0;

                // Respond to the Platform (it is solid)
                return true;
            }

            // Don't respond to the Platform (pass through)
            return false;
        }
    }

    // Make the object solid
    return true;
}
With the new Shape collision mechanism, some functions related to collisions have been removed from engine:

// Functions removed from Engine
me.Body.onslope
me.Body.onladder
me.Body.disableTopLadderCollision
me.Body.canBreakTile
me.Body.onTileBreak
me.Body.collisionMap
me.game.collisionMap
These functions can now be implemented through smart use of the onCollision callback with a similar logic as previously demonstrated to simulate a platform.


Work Done


After the completion of the steps above, you must run the game performing various tests to detect possible adjustments or fixes to be made. For possible questions, use the melonJS Forum or analyze directly the source code on GitHub Repo.

Even with the extra work, the upgrade compensates for the awesome shape based collisions, bug fixes and performance enhancements. And you can enjoy to review some "obscure" or "hackish" code, using the best practices you acquired in recent times or to implement new features in your game.

The melonJS 2.0 is a solid and stable version, demonstrating the maturity and evolution that the engine achieved during the last three years. Congrats melonJS Team for the job well done!