Tutorial ‘Digger’

In this article I will give you basic introduction to the MightyEditor and development process that surrounds it. Tutorial will show how to actually prototype a mini-game within an hour.

Requirements

Newest Google Chrome browser. You can try other browsers, but we don’t test them yet.

What is MightyEditor?

MightyEditor is open-source cloud based solution for creating and hosting HTML5 games. It is compatible with Phaser game development framework, but you can also use it with other tools. Main features of the editor are: asset management, map editing, code editor, data export.

How does MightyEditor work?

Design process of using editor works by following steps:

  1. Create a project
  2. Upload assets
  3. Drag and drop assets to the map
  4. Group assets in layers e.g. background, blocks…
  5. Add collisions and functionality in code editor
  6. Open game and export data

Why should I use MightyEditor?

Having a browser based tool with all of the basic functionality of map and code editor allows you to focus on fast prototyping of games. Open a link in browser and you are good to go. There is no hassle with installing and configuring various software solutions thus saving your precious time.

Cooperation with designer, another team member or a client has been made as easy as sharing link to the project. You can really work as a team, assign an illustrator to dealing with assets while game designer creates different levels in map editor and developer adds functionality with JavaScript code.

MightyEditor does not require your project to depend on it. All assets and code can be exported at any time. Whats even better – the editor is open-source and data can be moved to your local machine with local version of editor. The source code can be found on github  https://github.com/TheMightyFingers/mightyeditor.

Idea of mini-game

In this tutorial we will create a simple mini-game called Digger. The game is about a little miner who digs dirt block for gold and sells various minerals at the store. Arrow keys will be used for navigation and a simple physics and collision will be added to miner object.

Creating a project

Open the link http://mightyeditor.mightyfingers.com. Enter project title – in this case it will be Digger.

On the bottom right panel enter game dimensions: worldWidth, worldHeight 640 x 640. For sake of simplicity we will set view-port sizes the same 640 x 640.

 Upload game assets

In the following part of tutorial we will use assets that you can download here. On the top right panel from select list use upload file option and add files. Alternatively you can drag and drop files on to the panel and the assets will upload automatically.

Create a map

Click stamp icon on the left tool panel and then select background_sky.png in assets panel and then click on map thus creating background (hold Ctrl button for snapping to grid). You can change position of background by selecting arrow from the left tool panel. For more accurate positioning change x, y position in the settings panel.

Then repeat this step with following assets: background_city.png, background_hill1.png, background_hill2.png, background_grass.png. At the end everything should look like it’s shown in the following image

Create group

Let’s create group for newly created background objects. On right panel Objects section from select list choose Add Group. Rename group to bg and drag objects to this group. To drag multiple objects hold Shift key.

Add rest of graphics

Let’s create 5 rows of blocks under background. There are four different types of them: rock, ground, grass, gold. Gold blocks are collectible and you can’t dig rocks. Objects have to be added in blocks group.

Finally we need to add character and shop objects. As for the character asset – the image contains multiple frames. We need to define frame width and height in bottom right panel Settings panel. The size is 90 x 90. Separated frames can be viewed at bottom assetPreview panel. Also edit anchorX and anchorY. Set them both to 0.5

You can also define your own variables for object. Open userData tab in the same panel and add gold parameter with 0 value;

Select text icon on left tools panel and put a text object on top right corner of map. Write “0” as text will represent points. Rename text object in Objects panel on the right side.

Now we are ready to add objects and finish working with map editing. Character and shop objects are added like in image below

We have finished graphical part of tutorial. Next we’ll go in to coding and adding functionality like character controls, collisions, etc.

Source editor

Switch to source editor on top left side.

On the left side menu with game files are displayed. You will have to code mostly in state/play.js file. You can find key shortcodes for the editor here.

Game states

For coding we are going to use Phaser development framework. The states in Phaser are a separate parts of the game logic. By default editor gives you a template with four states boot, load, menu, play. For each state there are some predefined methods: preload, create, update, render. For demo purposes you should know that create method is called right after all assets are loaded and update method is called by game loop 60 times a second. You can learn more in documentation.

By default template calls load state. We need to redirect to play state. For this edit menu.js file under create method.

window.Digger.state.load = {
    preload: function(){
        ...
    },

    create: function() {
        this.game.state.start("play");
    }
}

Open game

First open game from top panel Open game button. At the moment there is only black screen. To display just made objects we have to initialize them in play.js file create method.

create: function() {
    this.bg = mt.create("bg");
    this.blocks = mt.create("blocks");
    this.shop = mt.create("shop");
    this.character = mt.create("character");
    this.points = mt.create("points");
}

Initializing is done with mt.create function. “bg” and “blocks” represent group names in object panel on the right side. “shop” and “character” represent sprite names in the same panel and finally “points” represent text. As you see all objects group, sprite and text are initialized with the same method.

Open the game now and initialized objects will be visible on the screen.

Adding physics

By default physics are disabled in Phaser for better performance reasons. We will enable the lightest and fastest physics from all available – Arcade physics. Open physics tab in bottom right corner. Change parameter enable to 1 and rest of parameters will appear below. Set character body size width: 60 and height 60. Enable gravity and set y to 1000. At last set collideWorldBounds parameter to 1.

Opening game you will see character falling down to the bottom of the screen.

Character controls

Initialize cursor keys in create method.

this.cursors = this.game.input.keyboard.createCursorKeys();

This  function give us an object with the four arrow keys to play with: up, down, left and right. In update method we will track when left/right/up arrow key is pressed and give a velocity to character or stop it keys are not inactive.

update: function() {
    if (this.cursors.left.isDown) {
        this.character.body.velocity.x = -200;
    } else if (this.cursors.right.isDown) {
        this.character.body.velocity.x = 200;
    } else {
        this.character.body.velocity.x = 0;
    } if (this.cursors.up.isDown) {
        this.character.body.velocity.y = -300;
    }
}

Open game and try arrow keys to control character.

Collision between character and blocks

Enable physics for blocks and set them immovable in the Map editor bottom right physics panel.

Next add collision detection in update method. First two arguments declare that we will check collision between sprite object and group of object. Third argument is a 2 argument function which is called on collision.

this.game.physics.arcade.collide(this.character, this.blocks, function(character, block) {
    console.log('Collision between', character, block);
}, null, this);

Opening game you will see character won’t fall to the end of screen, but will land on top of the blocks.

Character animations

First we need to define frames in spritesheet for different types of animations. Add these lines in create method.

this.character.animations.add('stand', [0, 1, 2, 3], 10, true);
this.character.animations.add('fly', [4, 5, 6, 7], 10, true);
this.character.animations.add('run', [8, 9, 10], 10, true);
this.character.animations.add('fall', [12, 13, 14, 15], 10, true);
this.character.animations.add('dig', [16, 17, 18], 10, false);
this.character.animations.add('dig_down', [20, 21, 22], 10, false);
this.character.animations.play('stand');

Last line of code starts play default animation stand.

For rest of animations we have to change update method and add play specific animation for each key press. Note that we have the same animation for left and right run. In order to flip horizontally sprite we are using scale -1.

if (this.cursors.left.isDown) {
    this.character.body.velocity.x = -200;
    this.character.animations.play('run');
    this.character.scale.x = -1;
} else if (this.cursors.right.isDown) {
    this.character.body.velocity.x = 200;
    this.character.animations.play('run');
    this.character.scale.x = 1;
} else {
    this.character.body.velocity.x = 0;
    this.character.animations.play('stand');
} if (this.cursors.up.isDown) {
    this.character.body.velocity.y = -300;
    this.character.animations.play('fly');
}

Destroying blocks

In order to dig blocks we need to add functionality to our collide function:

this.game.physics.arcade.collide(this.character, this.blocks, function(character, block) {
    if (this.cursors.left.isDown) {
        if (block.body.touching.right) {
            this.destroyBlock(block);
        }
    }
    else if (this.cursors.right.isDown) {
        if (block.body.touching.left) {
            this.destroyBlock(block);
        }
    }
    else if (this.cursors.down.isDown) {
        if (block.body.touching.up) {
            this.destroyBlock(block);
        }
    }
}, null, this);

Various blocks need to be handled differently. Grass and ground blocks are simply destroyed, rocks are indestructible and we can collect gold and save it in character gold parameter. Add destroyBlock method under play state.

destroyBlock: function(block) {
    switch (block.key) {
        case '/rock.png':
            break;
        case '/grass.png':
        case '/ground.png':
            block.destroy();
            break;
        case '/gold.png':
            this.character.getData().userData.gold++;
            block.destroy();
            break;
    }
},

Overlapping and selling gold

In the next step we need to sell collected gold at the shop. At first you need to go back to map editor and set physics for shop object similar how it was done with character. Set parameters enable: 1, gravity->allow: 0, immovable: 1. After that go to source editor and change update method with following lines:

this.game.physics.arcade.overlap(this.character, this.shop,
    function(character, shop) {
        if (character.getData().userData.gold > 0) {
            var newPoints = parseInt(this.points._text) + character.getData().userData.gold;
            this.points.setText(newPoints);
            character.getData().userData.gold = 0;
        }
    }, null, this
);

Refactoring and adding final animations

We will add digging animations as final step of this tutorial and re-factor update method to meet our needs of good looking game. Given previous samples the code below should be self explaining.

"use strict";
window.Digger.state.play = {	
	create: function(){
		this.cursors = this.game.input.keyboard.createCursorKeys();
		
		this.bg = mt.create("bg");
		this.blocks = mt.create("blocks");
		this.shop = mt.create("shop");
		this.character = mt.create("character");
		this.points = mt.create("points");
		
		this.character.animations.add('stand', [0, 1, 2, 3], 10, true);
		this.character.animations.add('fly', [4, 5, 6, 7], 10, true);
		this.character.animations.add('run', [8, 9, 10], 10, true);
		this.character.animations.add('fall', [12, 13, 14, 15], 10, true);
		this.character.animations.add('dig', [16, 17, 18], 10, false);
		this.character.animations.add('dig_down', [20, 21, 22], 10, false);
		this.character.animations.play('stand');
	},
	
	update: function(){
		var collideDown = false;
		this.game.physics.arcade.collide(this.character, this.blocks,
		  function(character, block){
			
			if(this.dig) return;	
				
			if(this.cursors.left.isDown){		
				if(block.body.touching.right){
					this.dig = this.character.animations.play('dig');
					this.dig.onComplete.addOnce(function(){
      					this.destroyBlock(block);
					}, this);							
				} else {
					this.character.animations.play('run');
				}					
			}

			else if(this.cursors.right.isDown){					
				if(block.body.touching.left){
					this.dig = this.character.animations.play('dig');
					this.dig.onComplete.addOnce(function(){
      					this.destroyBlock(block);
					}, this);					
				} else {
					this.character.animations.play('run');
				}

			}

			else if(this.cursors.down.isDown){					
				if(block.body.touching.up){
					this.dig = this.character.animations.play('dig_down');
					this.dig.onComplete.addOnce(function(){
      					this.destroyBlock(block);
					}, this);

				} else {
					this.character.animations.play('stand');
				}
			}		
			
			if(block.body.touching.up){
				collideDown = true;
			}
				
			
			
		}, null, this);
										 
		
		if(this.dig){
			return;	
		}
		

		if(this.cursors.left.isDown){
			this.character.scale.x = -1;
			this.character.body.velocity.x = -200;
		}
		else if(this.cursors.right.isDown){
			this.character.scale.x = 1;
			this.character.body.velocity.x = 200;
		}
		else {
			this.character.body.velocity.x = 0;	
		}
		
		
		if(this.cursors.up.isDown){
			this.character.body.velocity.y = -300;
			this.character.animations.play('fly');
		} else {
			if(!collideDown){
				this.character.animations.play('fall');
			}
			else if(this.character.body.velocity.x === 0){
				this.character.animations.play('stand');
			}
		}
		
		this.game.physics.arcade.overlap(this.character, this.shop,
		 	function(character, shop){
				if(character.getData().userData.gold > 0){
					var newPoints = parseInt(this.points._text) + character.getData().userData.gold;
					this.points.setText(newPoints);
					character.getData().userData.gold = 0;
				}
			}, null, this
		);
	},
	
	destroyBlock: function(block){
		this.dig = false;
		switch(block.key){
			case '/rock.png':
				break;
			case '/grass.png':
			case '/ground.png':
				block.destroy();
				break;
			case '/gold.png':
				this.character.getData().userData.gold++;
				block.destroy();
				break;
		}
	},
	
	stopDig: function(){
		this.dig = false;	
	}
};

Full game project is available here: http://mightyeditor.mightyfingers.com/#pde5-copy
Final game here: http://mightyeditor.mightyfingers.com/data/projects/pde5/phaser/index.html
iframe:

59 comments on “Tutorial ‘Digger’

  1. Hi, I’m looking for MightyEditor, you’ve done a good job from my last visit! I’ve just a question: in the loadProject, I’ve some random projects that I’ve never created, instead of the Tmp project that I’ve just created. Are the projects data stored locally?

  2. Hi,
    at the moment – projects are stored in the local storage at browser side.

    In the earlier versions every time you opened mightyeditor.mightyfingers.com – you got automatically blank project with custom id something like: pd7s
    Now id is added to the project only after you create new project.

    In the loadProject menu – script checks local storage entries and displays all projects that are stored there. For older projects it shows pd7s (pd7s) and for newer – ProjectTitle (pd7s).
    Your only link with your project is project_id – it is recommended to save it ( or bookmark it).

    Theoretically it’s impossible that loadProject menu would show some random projects – it just shows all that can be found on browsers local storage.

    Also if you will enter http://mightyeditor.mightyfingers.com/#pd7s – next time it will show also pd7s project at Recent Projects menu

    And finally if you have open project and then goto Project -> clone – editor will copy current project and assign new id to the copied project.

    You can clear all projects by hitting ctrl+shift+delete and checking: “Cookies and other site and plug-in data”
    This is temporary solution as it isn’t very useful an you can clear that list accidentally.
    This functionality will change with user account feature.

  3. Hi Slila,
    Open SourceEditor and click top icon from left tool panel thus creating a new file. Name it “character.js” and drag in whatever folder you want. Finally include script in index.html head section. Basically workflow is the same as any other code editor.

  4. Hi,

    really cool … the tool and the description of the tutorial.

    But I have a problem with the sourcecode editor. I can’t click on a special position to write there some code. Every time I click the lines are jumping, or adding a new clear line I’m not shure.
    Maybe there is something to do bevor using the editor?

    Kind regards.

  5. Hey, so I am using the digger example thing but this line of code is not working with me

    for( i = 0; i<this.blocks.length; i++)
    {this.blocks.getAt(i).destory();
    if(this.blocks.getAt(i).key=='/basic_tile_-_undug.png'){
    this.blocks.getAt(i).destory();
    }

    }

    why??

  6. Hi Ahmad,
    we have made an abstraction on top of phaser group. You can get to the group itself this.blocks.self and destroy this.blocks.self.getAt(i).destory();
    The abstraction helps to get more easily to group children by name like this.blocks.gold1
    In your case maybe you can use instead of loop construction removeAll method. Like this.blocks.self.removeAll(true);

  7. Hi,
    no there is no official documentation yet,
    but you can check out mt.helper.js – this is where mt object is defined and used for phaser object creation

    just don’t edit this file directly as it will be overwritten – if you need to modify it – just make copy of it like: mt.helper.mod.js and replace in index.html

  8. The problem is in negative y parameter “-60″
    this.b.self.create(64,-60,”/grass.png”);
    It creates sprite out of game world and you don’t see it. I’ve updated the parameter to “60” and grass tiles has been added

  9. This is a great tutorial and I’ve followed it all the way through and plan to use it with some children at my school to teach them MightyEditor.

    However, I want to expand the basic game to include more features. One of these is making the map bigger. Due to this I want the camera to follow the character around, but can’t work it out for the life of me!

    Looking at Phaser docs and examples, it looks like I should be using this command:

    game.camera.follow(character);

    But as I say, I can’t get it working. Any ideas, please?!

  10. Finally figured it out!

    Added:

    this.game.camera.follow(this.character);

    At the end of create: function() and altered the world size accordingly and it works!

    Loving MightyEditor, by the way!

  11. Great that you’ve figured it out. We didn’t wanted to duplicate Phaser examples, but probably you are right and we should add an example on camera in tutorial section :)

  12. Hi – I’ve followed the tutorial above (and the youtube clip) but I can’t get the character to respond to the cursor key input? It responds to gravity when I open the game from the editor but won’t move thereafter.

  13. Thanks a lot. I did the programming errors . Now it’s all right . If I were to have other problems I will contact you .
    Thanks again for this software . It ‘s wonderful . I will try to study it thoroughly . I have to create an interactive map in a website and must appear as a video game with a character that moves within it . Mighty Editor is perfect for this need.

    I’ll give you another question .
    Can I add a second player or more ( multiplayer ) ?

    Thanks in advance.

    1. Thanks for good words.

      Currently there is no multiplayer option in editor. One thing you can do is to create a client side game in editor, export the game and add server side (multiplayer) code on your PC.

  14. Thank you. Tomorrow , I will return to study the tutorials . Now I’m tired . I go to sleep . Thanks again. Good Night.

  15. Heya i’m for the first time here. I found this board and I too find It really
    useful & it helped me ouut much. I’m hoping to provide something basck and aid others such as you helped me.

  16. Hi I am working on a small project and found this really helpful but I have a question. I need to set up a 3×3 tile map. I also need the tiles to for example disappear when clicked. Could you show me an example piece of code on how to do that?

  17. HI there. Fantastic editor and tut! I did notice that for some reason, the amount of gold only updates upon colliding with the shop. How could we fix that?

  18. 10/11/2012OK My favorite game is cresis 2, All i know is the character i chose was an injured solder that was given the suite to fight off the aliens. Some how the suit is keeping him alive. I love the way they designed the suite and keep you up to date by explain how the suite works.

  19. Hi ! Thanks for this editor, this is wonderful! Just i write a comment today for a little problem. I follow this tutorial but when I launch my game (with the editor or in my local PC), and I have just a picture of a white horizontal bar….
    Firstly, I think this is because I am in Mozilla Firefox but no, that is the same on the last version of Google Chrome… I follow the video tutorial too, and i’ve picked up your project for test, so I have change NOTHING…. Don’t know why there is this problem… Need help, thanks in advance ! And thanks for this editor !

  20. It’s great to hear that you’ve finally “found your voice”, Michael. More posts about you as a person wo#u1n&l82d7;t be unwelcome — it’s a good reminder that the most knowledgeable people in any field are still learning and striving to improve.

  21. Imponente Ordesa y su entorno. Lo que si te aseguro que con mis vértigos no podría ni asomarme a ese Puente Arripas. Mucha presión de agua como para no sentirte atraido por la corriente cuando atravieses esa pasarela que por su escasa apariencia no transmite mucha seguridad, que di0&mosa#823g; Feliz estancia.

  22. he had another one with the bayonet an ask me if I wanted to do another trade. I was able to get the other one for 300 rounds of Chinese SKS ammo. I had a bent bolt and scope put on the first one, but bought a second bolt to be cut off because I did not want to cut the bolt with the oriaingl serial number on it. I have been using it for deer hunting and have gotten at least one deer for the last three years. I love the fact thats it is very cheap to shoot and been having lots of fun with it.

  23. Jerry –I think Gonzo worried too much about chemistry(i.e making Harvey happy). Willard should just play the guys that deserve the playing time — The competetion should be good for the team.As for RU, before making them the favorites for the Big East in 2011, lets make sure the kids all get into to schoool and are as good as the experts say. I hope Rice does not turn out to be like Gonzo, good with lesser players but unable to rise to the next level with the big boys.P.S. How is fatherhood? Is the kid toilet trained yet?

  24. of similar projects. People truly dedicated to providing library services and promoting education. I’ve read about a Colombian who provides library services with a donkey, and a project where camel…. These stories made me want to leave the comfort of the academic library I work at, and join these

  25. Hi we have the same camera, though i bought mine dec2011 10k pa sya nuon. Nainsprise ako sa mga shots mo ang ganda. I haven’t tried using mine in manual mode palaging auto. Gusto ko na tuloy matuto ng photog i love my GE x500 though! Super sulit:) the only thing i dont like is the battery though on the positive side you can easily buy kahit saan double a’s then slap into your camera in case madead bat ka na walang charger na dala

  26. LENNY IRMAWATY mengatakan:YTH. tim HPEQ Project, saya mohon info yang kontinyu tentang penelitian dosen kebidanan…, karena banyak proposal yang sudah saya susun, namun tidak paham untuk merealisasikannya. termasuk untuk uji kompetensi lulusan prodi kebidanan yang menurut informasi akan dilakukan uji coba tahun 2012. apakah tidak semua institusi ya?mohon maaf, home base saya ada di prodi kebidanan stikes medistra indonesia

  27. Hallo Chirstiane,danke für den Hinweis. Wollen wir doch mal sehen, ob sich ein Qualitätsjournalist seine Sporen verdient. Seltsam, dass die Weapons of Massdesinformation darüber noch nichts gebracht haben oder habe ich das nicht mitbekommen, ich schaue ja fast nie fern.

  28. Erstmal von mir “Viel Glück” für den Neuanfang! Mich würde es besonders freuen wenn es in Solingen und Burscheid bezugsquellen geben würde. Immer nach Wuppertal ist ein wenig weit

  29. Amazing indeed. Someone should ask the Eminent Senator from Nevada if he has an iPhone – and remind him that it is assembled in China (and many parts made in China). This, of course after a bonfire of clothes in his wardrobe that were made in China – or of items in his home, office that have components, systems made or assembled in China.

  30. caro autor,só quem não quer ver é que teima em ignorar os novos partidos. não me atrevo a fazer prognósticos mas, sempre lhe posso dizer que se os resultados finais derem 1 deputado para um dos novos partidos então o primeiro passo para mudar o sistema está dado. se tal não acontecer então nas legislativas far-se-á História.cordialmente,um leitor assíduo

Leave a Reply

Your email address will not be published. Required fields are marked *