Upgrading to melonJS 1.0
- Better audio support
- Proper support for all shapes type
- Embedded particle engine
- Better Core/Main Loop logic
- Performance improvements on the object pooling
- Support for HTML5 Fullscreen, Vibrate and VisiblityChange APIs
- Improved Camera management
- Several Tweaks and Fixes
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.7, you need to upgrade to versions 0.9.8 -> 0.9.9 -> 0.9.10 -> 0.9.11 and 1.0.2.
Below we will check some of the necessary changes to upgrade from melonJS 0.9.11 (previous version) to melonJS 1.0.2 (current version when writing this post). For a complete list of changes visit the melonJS Upgrade Guide.
Before the Upgrade
Starting from melonJS 1.0, the following pattern will be used for future releases:
Maintenance Releases (1.0.x): This is for bug fixes and with easy update process without the need for adjustment in your current game code (just replace the current melonJS file to the updated one).
Major Releases (1.x.x): This is for new releases filled with new features and can include multiple breaking changes forcing an upgrade in the game code (you need to make some adjustments in your game).
Before starting the migration, check the Upgrade Guide and the Changelog of engine and decide if the amount of work for the update compensates the incredible new features of each 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 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.game.remove -> me.game.world.removeChild me.game.add -> me.game.world.addChild me.game.collide -> me.game.world.collide me.game.getEntityByProp -> me.game.world.getChildByProp me.save.delete -> to me.save.remove me.entityPool.newInstanceOf -> me.pool.pull me.entityPool.add -> me.pool.register me.Rect.set -> me.Rect.setShape me.Font.set -> me.Font.setFont
In addition to the above changes, the "event type" function param to register and unregister mouse events also changed from mousedown/mousemove to pointerdown/pointermove:
// Before melonJS 1.0
me.input.registerPointerEvent('mousedown', this, this.mouseDown.bind(this));
me.input.registerPointerEvent('mousemove', this, this.mouseMove.bind(this));
me.input.releasePointerEvent('mousedown', this);
me.input.releasePointerEvent('mousemove', this);
// After melonJS 1.0
me.input.registerPointerEvent('pointerdown', this, this.mouseDown.bind(this));
me.input.registerPointerEvent('pointermove', this, this.mouseMove.bind(this));
me.input.releasePointerEvent('pointerdown', this);
me.input.releasePointerEvent('pointermove', this);
Let's Rock
The Object update() function now has a dt (or delta) parameter that provides the elapsed time since the last update in milliseconds (this is a nice feature for timers or for objects sync). If you redefine the update function in your own object, be sure to pass the parameter when calling the parent function. Furthermore, for better standardization, change the update: function() to update: function (dt):
// Before melonJS 1.0
update: function() {
this.updateMovement();
if (this.vel.x != 0 || this.vel.y != 0) {
this.parent();
return true;
}
return false;
}
// After melonJS 1.0
update: function(dt) {
this.updateMovement();
if (this.vel.x != 0 || this.vel.y != 0) {
this.parent(dt);
return true;
}
return false;
}
Other change is the visible property was eliminated from the me.Renderable. To make an object invisible, the recommended way is to remove the object from the game (using me.game.world.removeChild) or make it fully transparent (using setOpacity). Another option is to set a "visible" variable in the object init and use it in the draw function:
game.myRenderable = me.Renderable.extend({
// Constructor
init: function() {
// Set the object screen position
this.parent(new me.Vector2d(80, 80), 200, 100);
// Change renderable visibility
this.visible = true;
},
// Update logic
update: function(dt) {
return true;
},
// Draw canvas
draw: function(context) {
// Check object visibility
if (this.visible) {
// Change the canvas color
context.fillStyle = '#fff';
// Draw a simple rectangle
context.fillRect(this.pos.x, this.pos.y, this.width, this.height);
}
}
});
Come Get Some
To avoid several small bugs difficult to fix, the me.ScreenObject no longer acts as a Renderable, i.e., the init, update and draw functions were removed, disabling the same being added to the world container.
// Before melonJS 1.0
game.TitleScreen = me.ScreenObject.extend({
// Constructor
init: function() {
this.parent(true);
// Load the background image
this.bkg = me.loader.getImage("background");
// Create font
this.font = new me.Font("Arial", "20px", "#000000", "center");
},
// Run every time the screen is displayed
onResetEvent: function() {
// Register input keys
me.input.bindKey(me.input.KEY.ENTER, "play", true);
// Play title track
me.audio.playTrack("title", false);
},
// Run when changing state
onDestroyEvent: function() {
// Unregister input keys
me.input.unbindKey(me.input.KEY.ENTER);
// Stop title track
me.audio.stopTrack("title");
},
// Update logic
update: function() {
if (me.input.isKeyPressed("play")) {
me.state.change(me.state.PLAY);
}
return true;
},
// Draw canvas
draw: function(context) {
// Draw the background
context.drawImage(this.bkg, 0,0);
// Draw text message
this.font.draw(context, "PRESS ENTER TO PLAY", 400, 300);
}
});
This change requires redesigning almost all screens and using a distinct object (me.Renderable with update/draw pattern) for each item on the screen:
// After melonJS 1.0
game.TitleScreen = me.ScreenObject.extend({
// Run every time the screen is displayed
onResetEvent: function() {
// Load the background image
var bkg = new me.SpriteObject(0, 0, me.loader.getImage("background"));
// Added the background image in the game
me.game.world.addChild(bkg, 1);
// Create a static text
var text = new me.Renderable.extend({
init: function() {
this.parent(new me.Vector2d(0, 0), 0, 0);
this.font = new me.Font("Arial", "20px", "#000000", "center");
},
update: function(dt) {
return true;
},
draw: function(context) {
this.font.draw(context, "PRESS ENTER TO PLAY", 400, 300);
}
});
// Added the text in the game
me.game.world.addChild(text, 2);
// Register input keys
me.input.bindKey(me.input.KEY.ENTER, "play", true);
// Check for key press
this.handler = me.event.subscribe(me.event.KEYDOWN, function (action, keyCode, edge) {
if (action === "play") {
me.state.change(me.state.PLAY);
}
});
// Play title track
me.audio.playTrack("title", false);
},
// Run when changing state
onDestroyEvent: function() {
// Unregister input keys
me.input.unbindKey(me.input.KEY.ENTER);
me.event.unsubscribe(this.handler);
// Stop title track
me.audio.stopTrack("title");
}
});
Another big change with melonJS 1.0 was the entity collision properties (collisionBox) replaced by a more "standardized" approach through the use of collision shapes, preparing the engine for the new collision system to be made in version 1.1. The updateColRect and adjustSize functions have been removed and was added the addShape, setShape and getShape functions. For a detailed overview, check the Shapes Entry in the melonJS wiki.
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 new features, bug fixes and performance enhancements, especially on mobile devices. In addition, 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 the game.

0 comentários :