Talking about Magick game, Game development, HTML5, Javascript and Phaser.
Some time ago I downloaded an iPad game called Magick.
It’s a retro platformer where a mage called Oz walks and jumps by himself, and you can summon a crate, but only one, to modify the terrain.
The way you control the player, which actually you don’t control, you can just make some changes to the level, is really interesting to build with Phaser.
Since the game is easier to play than to describe, have a look at what you are going to build:
The player walks and climbs on his own, you can only click anywhere on an empty spot to summon a crate, but you can submit only one crate at once. Will you be able to reach the upper platform on the left?
Before I show you the fully commented source code, please note the level has been built with Tiled and exported as JSON. I am telling you this because some of the names used in the game itself are taken from the JSON data in level map.
Here is the Tiled output:
{ "height":10, "layers":[ { "data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "height":10, "name":"myLevel", "opacity":1, "type":"tilelayer", "visible":true, "width":25, "x":0, "y":0 }], "orientation":"orthogonal", "properties": { }, "tileheight":32, "tilesets":[ { "firstgid":1, "image":"rock.png", "imageheight":32, "imagewidth":32, "margin":0, "name":"rock", "properties": { }, "spacing":0, "tileheight":32, "tilewidth":32 }, { "firstgid":2, "image":"block.png", "imageheight":32, "imagewidth":32, "margin":0, "name":"block", "properties": { }, "spacing":0, "tileheight":32, "tilewidth":32 }], "tilewidth":32, "version":1, "width":25 }
And here is the fully commented source code, just a bunch of lines:
window.onload = function() { // the game itself var game = new Phaser.Game(800, 320); // the player! The hero of the game!! var player; // level map, created with Tiled var map; // map layer with level data var levelLayer; // player horizontal speed var playerSpeed = 120; // map tile size, in pixels var tileSize = 32; // tilePoint will be used to save the coordinates of the tile placed by the player var tilePoint = null; // is the player jumping? var playerJumping = false; // playGame function, to be bound to "PlayGame" state var playGame = function(game){} playGame.prototype = { // preloading assets preload: function(){ // map data game.load.tilemap("map", "map.json", null, Phaser.Tilemap.TILED_JSON); // rock image, used to draw walls game.load.image("rock", "rock.png"); // block image, used to let the player add tiles to the map game.load.image("block", "block.png"); // the player game.load.image("player", "player.png"); }, // once the game has been created create: function(){ // starting arcade physics game.physics.startSystem(Phaser.Physics.ARCADE); // adding the map map = game.add.tilemap("map"); // adding "rock" and "block" graphic assets to the map map.addTilesetImage("rock"); map.addTilesetImage("block"); // both "rock" and "block" are solid map.setCollisionBetween(1,2); // we are going to use "myLevel" layer, as created with Tiled levelLayer = map.createLayer("myLevel"); // adding the player player = game.add.sprite(48,226,"player"); // setting player registration point in the center player.anchor.setTo(0.5); // enabling arcade pysics to the player game.physics.enable(player, Phaser.Physics.ARCADE); // setting player gravity player.body.gravity.y = 400; // waiting for input, both touch or mouse click, to call addBlock function game.input.onDown.add(addBlock, this); }, // function to be executed at each frame update:function(){ // setting player x speed to zero player.body.velocity.x = 0; // check for collision between the player and the level, and call "movePlayer" if there's a collision game.physics.arcade.collide(player, levelLayer, movePlayer); } } function movePlayer(){ // is the player blocked down, that is: is the player on the floor? if(player.body.blocked.down){ // set player horizontal velocity player.body.velocity.x = playerSpeed; // the player is definitively not jumping playerJumping = false; } // is player speed greater than zero and the player is blocked right, that is the player is against a wall on the right? if(player.body.blocked.right && playerSpeed>0){ // is the tile on player upper right diagonal empty, as well as the tile immediately above the player, or is the player already jumping? if((!map.getTileWorldXY(player.x+tileSize,player.y-tileSize,tileSize,tileSize,levelLayer)&&!map.getTileWorldXY(player.x,player.y-tileSize,tileSize,tileSize,levelLayer)) || playerJumping){ // jump jump(); } else{ // invert player speed playerSpeed*=-1; } } // the same concept is applied to collisions on the left side of the player if(player.body.blocked.left && playerSpeed<0){ if((!map.getTileWorldXY(player.x-tileSize,player.y-tileSize,tileSize,tileSize,levelLayer)&&!map.getTileWorldXY(player.x,player.y-tileSize,tileSize,tileSize,levelLayer)) || playerJumping){ jump(); } else{ playerSpeed*=-1; } } } function addBlock(e){ // is the tile where we clicked/touched a null tile? if(!map.getTileWorldXY(e.x,e.y,tileSize,tileSize,levelLayer)){ // is there already a tile placed by the player? if(tilePoint){ // remove the tile placed by the player map.removeTileWorldXY(tilePoint.x, tilePoint.y, tileSize, tileSize, levelLayer); } // place the tile on mouse/touch position map.putTileWorldXY(2, e.x, e.y, tileSize, tileSize, levelLayer); // save placed tile position tilePoint = new Phaser.Point(e.x,e.y); } } function jump(){ // setting player vertical velocity player.body.velocity.y = -100; // setting player horizontal velocity player.body.velocity.x = playerSpeed/4; // now the player is jumping playerJumping = true; } // defining "PlayGame" state game.state.add("PlayGame",playGame); // run "PlayGame" state game.state.start("PlayGame") }
I always say the funniest game are built on the simplest concepts, and here’s another one.
Download the source code and suggest some features to add to the game.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.