6 min read

Building Mobile Games with Crafty.js and PhoneGap – Part 2

Let’s continue making a simple turn-based RPG-like game based on Pascal Rettig’s Crafty Workshop presentation with PhoneGap. In the second part of this two-part series, you will learn how to add sprites to a game, control them, and work with mouse/touch events.

Adding sprites

OK, let’s add some sprites to the mix using open source sprite sheets from RLTiles. All of the resources at RLTiles are in public domain, but the ones we will need are the dungeon tiles, which you can find here, and the monsters, which you can find here. To use them, first create a new folder under your www root directory in your PhoneGap project called assets. Then, click on the Dungeon link and right-click on the dungeon  sprite sheet and select Save as. Save it as dungeon.png to your assets directory. Do the same with monsters, but call it characters.png.

 Now, edit index.html to look like listing 1.

Listing 1: Loading sprites in Crafty

<!DOCTYPE html>
   <html>
   <head></head>
   <body>
   <div id="game"></div>
		 <script type="text/javascript" src="lib/crafty.js"></script>
	<script>
	         var WIDTH = 500, HEIGHT = 320;
	         Crafty.init(WIDTH, HEIGHT);
	         // Background
         Crafty.background("black");
            //let’s loads some assets for the game
         // This will create entities called floor, wall1, and stairs
         Crafty.sprite(32,"assets/dungeon.png", {
         floor: [0,0], wall1: [2,1], stairs: [3,1]
         });
                     // This will create entities called hero1 and blob1
                  Crafty.sprite(32,"assets/characters.png", {
                  hero: [11,4],goblin1: [8,14]
                  });
            Crafty.scene("loading", function() {
	         Crafty.load(["assets/dungeon.png","assets/characters.png"], function() {
	         Crafty.scene("main"); // Run the main scene
         console.log("Done loading");
                 },
            function(e) { //progress
	              },
			         function(e) { //somethig is wrong, error loading
		                  console.log("Error,failed to load", e)
				            });
				         });
				         Crafty.scene("loading");
				         // Let's draw us a Hero and a Goblin
		         Crafty.scene("main",function() {
			         Crafty.background("#FFF");
			         var player = Crafty.e("2D, Canvas, hero")
			                  .attr({x:0, y:0});
			         var goblin = Crafty.e("2D, Canvas, goblin1")
			                  .attr({x:50, y:50});
			         });
				</script>
				</body>
				</html>

There are a couple of things to note in this code. Firstly, we are using Crafty.sprite to load sprites from a sprite file. The first attribute in the sprite(), 32, references the size of the sprite. The second is the location of the sprite sheet. Next, we set the name of each sprite we want to load and its location. For example, floor(0,0) means grab the very first sprite on the sprite sheet, assign it the label floor, and load it into memory.

Next is a very important Crafty function; Crafty.scene(). In Crafty, scenes are a way to organize your game objects and easily transition between levels or screens. In our case, we first use Crafty.scene() to load a bunch of assets, our sprite sheets, and when done, we tell it to call the main() scene.

Next, we actually call loading, which loads our assets and then calls the main() scene. In the main() scene, we create the player and goblin entities. Try saving the file and loading it in your browser. You should see something like figure 1.

 

Figure 1: Loading the hero and goblin sprites in Chrome

Movement

Now that we have figured out how to load the sprites, let’s figure out how to move them. First, we want to move and control our hero. To do this, we want to make a component, which is an abstracted set of data or behaviors we can then assign to an entity. To do that, open your index.html file again and edit it to look like listing 2.

Listing 2: Controlling the hero

<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="game"></div>
<script type="text/javascript" src="lib/crafty.js"></script>
<script>
      var WIDTH = 500, HEIGHT = 320;
      Crafty.init(WIDTH, HEIGHT);
      Crafty.sprite(32,"assets/dungeon.png", {
           floor: [0,0], wall1: [2,1], stairs: [3,1]
           });
      Crafty.sprite(32,"assets/characters.png", {
           hero: [11,4], goblin1: [8,14]
           });
           // create a simple object that describes player movement
           Crafty.c("PlayerControls", {
      init: function() {
              //let’s now make the hero move wherever we touch    
            Crafty.addEvent(this, Crafty.stage.elem, 'mousedown', function(e) {
               // let’s simulate an 8-way controller or old school joystick
                 console.log("the values are; x= " + e.clientX );
            if (e.clientX<player.x&& (e.clientX - player.x)< 32)
                   {player.x= player.x - 32;}
                 else if (e.clientX>player.x&& (e.clientX - player.x) > 32){
                  player.x = player.x + 32;
                 }
                 else {player.x = player.x}
 
                 if (e.clientY<player.y&& (e.clientY - player.y)< 32)
                   {player.y= player.y - 32;}
                 else if (e.clientY>player.y&& (e.clientY - player.y) > 32){
                  player.y = player.y + 32;
                 }
                 else {player.y = player.y}
          
                 Crafty.trigger('Turn');
                  console.log('mousedown at (' + e.clientX + ', ' + e.clientY + ')');
                 });
         }
           });
 
           Crafty.scene("loading", function() {
      Crafty.load(["assets/dungeon.png","assets/characters.png"], function() {
           Crafty.scene("main"); // Run the main scene
           console.log("Done loading");
                },
           function(e) { //progress
                },
           function(e) { //somethig is wrong, error loading
      console.log("Error,failed to load", e)
 
              });
           });
           Crafty.scene("loading");
           // Let's draw us a Hero and a mean Goblin
           Crafty.scene("main",function() {
           Crafty.background("#FFF");
           player = Crafty.e("2D, Canvas,Fourway, PlayerControls, hero")
                    .attr({x:0, y:0})
           goblin = Crafty.e("2D, Canvas, goblin1")
                    .attr({x:50, y:50});
          
           });
</script>
</body>
</html>

In listing 2, the main thing to focus on is the PlayerControls component defined by Crafty.c(). In the component, we are going to simulate a typical 8-way controller. For our PlayerControls component, we want the player to only be able to move one tile, which is 32 pixels, each time they select a direction they want to move. We do this by using Crafty.addEvent and having it update the player’s location based on the direction of where the user touched, which is derived by getting the relative location of the user’s touch from client.x, client.y in relation to the hero’s position, which is player.x, player.y.

Save the file and view it. View the file using the inspect element option, and you should see something like figure 2.

 

Figure 2: Controlling the hero

You can now control the movement of the hero in the game.

Summary

In this two-part series, you learned about working with Crafty.js. Specifically, you learned how to work with the Crafty API, create entities, work with sprites, create components, and control entities via mouse/touch.

About the author

Robi Sen, CSO at Department 13, is an experienced inventor, serial entrepreneur, and futurist whose dynamic twenty-plus-year career in technology, engineering, and research has led him to work on cutting edge projects for DARPA, TSWG, SOCOM, RRTO, NASA, DOE, and the DOD. Robi also has extensive experience in the commercial space, including the co-creation of several successful start-up companies. He has worked with companies such as UnderArmour, Sony, CISCO, IBM, and many others to help build new products and services. Robi specializes in bringing his unique vision and thought process to difficult and complex problems, allowing companies and organizations to find innovative solutions that they can rapidly operationalize or go to market with.

LEAVE A REPLY

Please enter your comment!
Please enter your name here