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 :