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!

ZEEF HTML5 Game Development


Check this ZEEF curated directory with several resources for develop games using HTML5, Javascript and WebGL. Some resources can be used for general game development.


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!

Implementing Particles with melonJS


With the popularity of games on smartphones and browsers, 2D gaming is back on the scene, recalling the classic age of the late '80s and early '90s. At that time, most games used animation techniques with images (sprite sheets) to display special effects such as explosions, fire, or magic. In current games we can use particle systems, generating random and interesting visual effects in them. In this post I will briefly describe what a particle system is and how to implement models using the HTML5 engine melonJS.

Note: Although the examples are specific to the melonJS game engine using JavaScript as a programming language, the concepts and ideas can be adapted for other languages ​​or game engines as well.


Packt Publishing mission is to help the world put software to work in new ways, through the delivery of effective learning and information services to IT professionals.

Upgrading to melonJS 1.1


With the release of melonJS 1.1, is time to conduct a upgrade to this new version of the engine, packed with really nice features, as:

- New blazing-fast inheritance pattern (Jay Inheritance)
- New SAT (Separate Axis Theorem) based collision algorithm
- Super fast collision detection across a spatial partitioning algorithm (QuadTree)
- Added collision filtering support
- Entity object redesign with a full polygon shape based physic body implementation
- Several objects renamed  for a cleaner  and standardized API
- 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 0.9.11, you need to update first to 1.0.2 version (check the post Upgrading to melonJS 1.0) and after to 1.1.0 version.

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


Before the Upgrade


The melonJS 1.1 is a major release and include several breaking changes which forces you to make several 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 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
me.ObjectEntity -> me.Entity
me.SpriteObject -> me.Sprite
me.ObjectContainer -> me.Container
me.video.getWidth -> me.video.renderer.getWidth
me.video.getHeight -> me.video.renderer.getHeight
me.video.getSystemCanvas -> me.video.renderer.getCanvas
me.video.getSystemContext -> me.video.renderer.getContext
me.video.getScreenCanvas -> me.video.renderer.getScreenCanvas
me.video.getScreenContext -> me.video.renderer.getScreenContext
me.video.applyRGBFilter -> me.video.renderer.applyRGBFilter
me.video.getContext2d -> me.CanvasRenderer.getContext2d
If you used the onDestroyEvent callback from me.Renderable, the same should be renamed to onDeactivateEvent. Note that the function onDestroyEvent remains only to me.ScreenObject.

In preparation to WebGL support (probably available in version 1.2.0), the call to me.video.init has a new parameter informing the type of renderer (currently accepts only me.video.CANVAS):

// Before melonJS 1.1
me.video.init("game", 400, 300, true, "auto");

// After melonJS 1.1
me.video.init("game", me.video.CANVAS, 400, 300, true, "auto");

Let's Rock


The inheritance pattern has changed significantly, moving from John Resig Simple Inheritance to the new and fast Jay Inheritance, forcing various adjustments in the code. In the melonJS 1.0 and previous, you have something like:

// Before melonJS 1.1
var sprite = me.SpriteObject.extend({
  // Property
  active: yes,
  
  // Constructor
  init : function(x, y, sprite) {
    this.parent(x, y, sprite);
  },
 
  // Draw
  draw: function(context) {
    // Draw only if is active
    if (this.active)
       this.parent(context);
  }
});
To make performance improvements and enforce better rules you need to invoke a _super method (instead of parent), passing the base class itself, a string representing the method name, and an array of the arguments:

// After melonJS 1.1
var sprite = me.Sprite.extend({
  // Constructor
  init : function(x, y, sprite) {
    this._super(me.Sprite, "init", [x, y, sprite]);

    // Properties must be set in the init method only!
    this.active = yes;
  },
 
  // Draw
  draw: function(renderer) {
    // Draw only if is active
    if (this.active)
       this._super(me.Sprite, "draw", [renderer]);
  }
});
At first this change can scare, but the benefits with increased performance and reduced memory consumption compensate. For a more detailed explanation of the great new inheritance pattern, see the post about Jay Inheritance.

For better performance, the me.Renderable, me.Rect, me.PolyShape and me.Ellipse now requires (x,y) integer values over a me.Vector2d instance:

// Before melonJS 1.1
var myRenderable = new me.Renderable(new me.Vector2d(20, 50), 200, 300);
var myRect = new me.Rect(new me.Vector2d(30, 60), 150, 50);

// After melonJS 1.1
var myRenderable = new me.Renderable(20, 50, 200, 300);
var myRect = new me.Rect(30, 60, 150, 50);
The me.AnimationSheet now requires x, y and a settings hash to its constructor:

// Before melonJS 1.1
var animation = new me.AnimationSheet(10, 20, me.loader.getImage("sprite"), 64, 32);

// After melonJS 1.1
var animation = new me.AnimationSheet(10, 20, {
    image: me.loader.getImage("sprite"),
    spritewidth: 64,
    spriteheight: 32
});

Come Get Some


For a faster execution time, the me.Entity (me.ObjectEntity in the previous version) has been redesigned using a composition approach (lowering the amount of object properties), instead of inheritance based design used in the previous version. In this way, the me.Entity has a new me.Body child object that will hold all physic and collision properties and functions.

// Before melonJS 1.1
var entity = me.ObjectEntity.extend({
  // Constructor
  init: function(x, y, settings) {
    this.parent(x, y, settings);

    // Set the gravity
    this.gravity = 2;

    // Set the velocity
    this.setVelocity(5, 8);
  },

  // Update logic
  update: function(dt) {
      // Apply gravity
      this.vel.y += this.gravity;      

      // Update entity Position
      this.updateMovement();

      this.parent(dt);
      return true;
  }
});

// After melonJS 1.1
var entity = me.Entity.extend({
  // Constructor
  init: function(x, y, settings) {
    this._super(me.Entity, "init", [x, y, settings]);

    // Set the gravity
    this.body.gravity = 2;

    // Set the velocity
    this.body.setVelocity(5, 8);
  },

  // Update logic
  update: function(dt) {
      // Apply gravity
      this.body.vel.y += this.body.gravity;     

      // Update entity Position
      this.body.update();

      this._super(me.Entity, "update", [dt])
      return true;;
  }
});
Thus, the following functions have been renamed or assigned through the me.Body child object:

// Physics Old Code -> Physics New Code
this.accel -> this.body.accel
this.canBreakTile -> this.body.canBreakTile
this.disableTopLadderCollision -> this.body.disableTopLadderCollision
this.falling -> this.body.falling
this.gravity -> this.body.gravity
this.jumping -> this.body.jumping
this.maxVel -> this.body.maxVel
this.onladder -> this.body.onladder
this.onslope -> this.body.onslope
this.shapes -> this.body.shapes
this.vel -> this.body.vel
this.addShape -> this.body.addShape
this.getShape -> this.body.getShape
this.setShape -> this.body.setShape
this.setFriction -> this.body.setFriction
this.setMaxVelocity -> this.body.setMaxVelocity
this.setVelocity -> this.body.setVelocity
this.collisionMap -> this.body.collisionMap

// Collision Old Code -> Collision New Code
this.updateMovement() -> this.body.update()
me.game.world.collide(this) -> me.collision.check(this, true, this.collideHandler.bind(this), true)
The melonJS 1.1 has now a full SAT collision algorithm, for polygon collision detection and more accurate collision response. The previous collision check function has therefore been deprecated and replaced by a new me.collision.check function. Refined collision filtering is now possible through the use of me.body.setCollisionMask function (that defines what should collide with what).

// Before melonJS 1.1
var entity = me.ObjectEntity.extend({ 
    init: function(x, y, settings) {
        // Call the constructor
        this.parent(x, y , settings);

        // Default velocity
        this.setVelocity(3, 15);
    },
 
    // Update logic
    update: function(dt) {
        // Change velocity
        this.vel.x -= this.accel.x * me.timer.tick;
    
        // Check for collision with environment
        this.updateMovement();
  
        // Check for collision with enemies or objects
        var res = me.game.world.collide(this);

        if (res) {
            // Change velocity
            this.vel.y -= this.maxVel.y * me.timer.tick;

            // Change position
            this.pos.x -= 20;
        }
  
        this.parent(dt);
        return true;
    },
 
    // Collision callback
    onCollision: function() {
        // Disable collision
        this.collidable = false;
  
        // Remove from game
        me.game.world.removeChild(this);
    }
});

// After melonJS 1.1
var entity = me.Entity.extend({   
    init: function(x, y, settings) {
        // Call the constructor
        this._super(me.Entity, 'init', [x, y , settings]);
       
        // 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;
            
        // Check for collision with environment
        this.body.update();
       
        // Check for collision with enemies or objects
        me.collision.check(this, true, this.collideHandler.bind(this), true);
           
        this._super(me.Entity, "update", [dt]);
        return true;       
    },
   
    // Collision handler
    collideHandler: function(response) { 
        // 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 preparation to support WebGL, the me.video is now agnostic of rendering target, by adding the me.CanvasRenderer object,  passing it to the draw calls of all the objects added to the world container and other subsequent containers.

// Before melonJS 1.1
draw: function(context) {
    // Set the context color
    context.fillStyle = "#FFFFFF";

    // Draw a simple rectangle
    context.fillRect(this.pos.x, this.pos.y, this.width, this.height);
}

// After melonJS 1.1 - Getting directly the context
draw: function(renderer) {
    // Get the renderer context
    var context = renderer.getContext();
   
    // Set the context color
    context.fillStyle = "#FFFFFF";
   
    // Draw a simple rectangle
    context.fillRect(this.pos.x, this.pos.y, this.width, this.height);
}

// After melonJS 1.1 - Using me.CanvasRenderer methods (recommended)
draw: function(renderer) {
    // Draw a simple rectangle, using the integrated function
    renderer.fillRect(this.pos.x, this.pos.y, this.width, this.height, "#FFFFFF");
}

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 collision detection, fast inheritance, bug fixes and performance enhancements, in addition to being better prepared for the next melonJS version (in development), with the replacement of the current limited tile collision layer by a shape based collision layer and the probable addition of WebGL support! 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.