Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / HTML5, CSS3, and JavaScript /

Developing HTML5 games with Impact JavaScript game engine and Dreamweaver CS5.5

by Jesse Freeman

Jesse Freeman
  • jessefreeman.com

Content

  • Setting up a local environment and creating a new Impact project
  • Working with sprite sheets
  • Creating the first level of the game
  • Using Weltmeister to save and load maps
  • Creating the collision layer
  • Examining and customizing the main class
  • Binding key press events with the input class
  • Creating the player class
  • Creating the monster class
  • Understanding collision detection, health, and weapons
  • Customizing the player's weapon
  • Adding the code to fire the weapon
  • Customizing the camera
  • Publishing the game
  • Where to go from here

Created

29 November 2011

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
animation application Dreamweaver gaming HTML5 JavaScript

Requirements

Prerequisite knowledge

Previous experience working with Dreamweaver and setting up a local host server is recommended. Prior knowledge of HTML5 and JavaScript code is also required.

 

Additional required products

 

  • Impact JavaScript game engine
  • XAMPP (Windows)
  • MAMP (Mac OSX)

User level

All

Required products

  • Dreamweaver CS5.5 (Download trial)

In this article, you'll learn how to work with Impact and Dreamweaver CS5.5 to build HTML5 games. ImpactJS is a JavaScript game framework created by Dominic Szablewski. It takes advantage of the modern browser’s Canvas element in order to create high-performance 2D games on the web and even mobile platforms. Impact is very easy to pick up, comes with very good code examples, has an active community, and includes a very robust level editor called Weltmeister. The only barrier of entry is the licensing fee for the software because it is not open source. After purchasing a license you recieve the full source code, the Weltmeister editor, and free updates. While there are many other open source and free JavaScript game frameworks out there, Impact has an extra level of polish I haven’t encountered in the other HTML5 game frameworks I've tested.

Perhaps one of the most appealing factors of buying Impact is the inclusion of a sample Objective-C project that allows you to compile your Web game into a native iOS app, which takes advantage of OpenGL for graphics and OpenCL for sound. This solution gives your game native performance on iOS, and it can be packaged up and sold in the Apple App Store just like a native app.

Note: Impact works very well running on WebKit browsers, especially Chrome, but any modern browser with support for Canvas will also work.

Setting up a local environment and creating a new Impact project

Before building an HTML5 game with Impact, you'll need to prepare the web development environment, so that you can take full advantage of the features included in Impact and its level editor. Let’s take a look at configuring Apache, install the necessary tools, and create a new project in Impact.

Installing Apache, PHP, and MySQL

There are many resources out there for installing Apache and PHP on your operating system of choice. Here are some simple one-click solutions to help get you up and running as quickly as possible.

Mac OSX users can use an all-in-one solution such as MAMP. MAMP is a one-click solution for setting up Apache, PHP, and MySQL on your Mac. Likewise, you can also use the built-in version of PHP that comes with OS X, but you will need to do some manual configuration of Apache to get it working. Simply do a search for Enabling PHP in Mac OS X to find instructions on how to do it.

Just like on Mac, XAMPP, there are some excellent one-click solutions for setting up Apache, PHP and MySQL. I have used XAMPP in the past and have had excellent success with it.

Setting up a new Impact project

Impact is a self-contained project. Each game you create will require you to copy the default Impact project file (which you get once you buy a license) into a new location on your Apache server and start from scratch. For your first project, you could easily do all your work from your local host, but when it comes to building multiple games at the same time or organizing your web projects, it is best if you set up a VirtualHost in Apache. To keep things simple, we are going to use a local host. For the purposes of this sample project, I've set up a local host called html5gameworkshop.local.

To get started, copy the Impact project folder into your local host. You will see the following files (see Figure 1):

Figure 1. Review the contents of the Impact project folder.
Figure 1. Review the contents of the Impact project folder.

Here is a quick breakdown of the files in the Impact folder:

  • index.html - The main HTML file that runs your game.
  • lib - The core code for Impact and the folder where you will store your own game-specific code. This folder also contains the source code for Weltmeister.
  • media - The assets directory where the game art will go.
  • tools - The PHP directory that contains PHP scripts to compress and obscure your game. This is part of the license and ensures that you don’t accidentally distribute the source code.
  • weltmeister.html - The level editor HTML file.

You should now have everything you need to run your first game. Open a browser and navigate to your localhost to see the following page (see Figure 2):

Figure 2. The confirmation screen indicates that the environment is configured correctly.
Figure 2. The confirmation screen indicates that the environment is configured correctly.

Working with sprite sheets

Sprite sheets are going to be the primary way that we display and animate artwork in Impact games. A sprite is a single bitmap image that is drawn to the display (in this case, our Canvas element). To help organize them better, sprites are grouped together into a single image called a sprite sheet. The following is an example of a sprite sheet from the game we are going to build (see Figure 3).

Figure 3. This sprite sheet contains all of the animation for the main character.
Figure 3. This sprite sheet contains all of the animation for the main character.

Sprite sheets are usually set up in an easily dividable way. So, in this case, each sprite is 16 x 16 pixels. This spacing allows us to simply divide the sprite sheet by 16 and automatically figure out that there are 10 sprites. Generally, when doing animation from a sprite sheet, we would tell the animation engine which sprite is part of each animation set. Here is an example of how that works in Impact:

this.addAnim( 'idle', 1, [0] ); this.addAnim( 'run', 0.07, [0,1,2,3,4,5] ); this.addAnim( 'jump', 1, [9] ); this.addAnim( 'fall', 0.4, [6,7] );

We will explore this a little later on when we begin setting up our game. As you can see, sprite 0 is our idle animation, while 0-5 represent our run animations. It is important to note that JavaScript’s Arrays are zero-based; we must take this into account when it comes to registering sprite sheet animation. So, the first sprite is always 0.

Sprite sheets are also good for non-animated graphics, such as tiles for a level. The following sprites are tiles that will make up the background of our game (see Figure 4).

Figure 4. The bitmap images used to display the game's background graphics.
Figure 4. The bitmap images used to display the game's background graphics.

So, instead of registering animations manually, we can tell the game engine which sprites represent walls, decorations or any other art you would need for your level’s design. Here is an image from Impact’s level editor that illustrates how these tiles will look in the game (see Figure 5):

Figure 5. Screenshot of the game's background that is displayed with a sprite sheet.
Figure 5. Screenshot of the game's background that is displayed with a sprite sheet.

Creating the first level of the game

Now that we have a basic understanding of sprite sheets, let’s look at how to actually use them in our game.

Let’s open up Weltmeister, Impact’s level editor and create a level. Follow these steps:

  1. Navigate to the weltmeister.html page in the root of your project. When you open up Weltmeister for the first time, you will see that an untitled.js file has been created for you but that the level is empty.
  2. Before we can even start creating the first level, we need to add the map tile sprite sheet. Copy the tiles.png file into your media directory.
  3. Create a new layer and name it main. This is where we will start drawing our level. You can create this new layer by clicking the plus icon on the top right of the screen, next to the Layers label (see Figure 6).
Figure 6. Create a new layer named main.
Figure 6. Create a new layer named main.

When a new layer is created, its bounding box shows the borders of the layer. This is based on the layer’s dimensions. You can’t draw tiles outside of this box. We will also have to configure the layer’s properties. Here is a summary of what each property represents:

  • Name - The name of the layer. Name it anything you desire—with the exception of collision, which is a reserved name. I'll describe collison layers in the next section.
  • Tileset - The path to the Tileset image file for this layer. When you click this property, you are presented with a list of directories in your project file.
  • Tilesize - The size of each tile in your sprite sheet. By default, the size is set to 8.
  • Dimensions - The width and height of the layer. By default, it is set to 30 x 30 tiles. Since tiles are set to 8 pixels by default, this layer's dimensions are 240 x 160 pixels.
  • Distance - The distance from the camera, similar to setting the Z index in HTML. This is useful for creating background layers that you want to scroll at a different speed than the foreground layers to create a parallax scrolling effect.
  • Repeat - This is also a background layer property that allows you to repeat your layer when it scrolls by in the background. Think of this more as a texture that is applied to your layer.

So, now we are ready to make our first level. Follow these steps:

  1. Click the Tileset field and select the map tiles.
  2. The root directory of your project is available in the drop-down menu. Select media and then select tiles.png.
  3. Make sure to apply the changes to save your selection (see Figure 7).
Figure 7. Select the media directory in the Tileset field.
Figure 7. Select the media directory in the Tileset field.
  1. Return to the map editor and press the Spacebar. Choose from the series of tiles that appear to paint the level (see Figure 8).
Figure 8. Select the tiles to add to the background for the first level of the game.
Figure 8. Select the tiles to add to the background for the first level of the game.

Using the tile painter, you can select the tile you want to use. Once you make your selection, you can start drawing down tiles.

Notice the empty yellow box at the beginning of your sprite sheet. Select the yellow box when you want to erase tiles you have painted. Weltmeister automatically creates the empty tile for you, so you don’t need to add it to your sprite sheet.

  1. Select tiles in the tile painter to draw the following basic level (see Figure 9):
Figure 9. Click here and insert your figure caption.
Figure 9. Click here and insert your figure caption.

I know this level doesn’t look very exciting yet, but don’t worry, we will get into more complex level creation later on.

Using Weltmeister to save and load maps

In this section, we save maps and then load them in Weltmeister. Since we just created a level in the previous section, it's important to save the recent changes. We should save our map really fast by hitting Save at the top. You will notice that, by default, Weltmeister automatically puts levels in the lib/game/levels/ directory .

Figure 10. Levels are always saved in the levels folder in the project's structure.
Figure 10. Levels are always saved in the levels folder in the project's structure.

This location is very important because it is the folder where Impact will automatically look for your game’s levels. Later on, we will be able to simply tell Impact to load your level by its name, instead of being required to pass it the full directory path.

Let’s name our the first level test.js in the Save Level field and click Save.

Note: You must add the .js file extension as you name the level. The file is actually a JSON file. The Weltmeister editor will display an error if you forget to add the correct file extension.

When saving, you may get the following error (see Figure 11):

Figure 11. The Couldn't write to file error message may appear when saving levels.
Figure 11. The Couldn't write to file error message may appear when saving levels.

This is easy to fix; it’s just a permissions error. Navigate to the lib/game/levels directory on your computer and fix the read/write permissions. (see Figure 12).

Figure 12. Update the Privilege setting for the levels folder to Read & Write.
Figure 12. Update the Privilege setting for the levels folder to Read & Write.

It’s also important to note that you must have PHP set up in order to save levels. The editor itself is a JavaScript application, but the save scripts use PHP to function.

You can also easily load any level you have created by selecting Load in the top menu (see Figure 13).

Figure 13. Click Load and then select the level from the directory structure that appears.
Figure 13. Click Load and then select the level from the directory structure that appears.

You will see a list of all the maps you have created. By default, Weltmeister automatically attempts to load the last level you were working in.

Creating the collision layer

There is one thing we have to do, though, before we can start building our game and that is set up the collision layer. This tells Impact what tiles are passible and impassible to the player and other game objects. To set this up, we need to create a new level called collision and load the collision Tileset: media/collisiontiles-8x8.png. This comes in the default Impact project. Once you have the collision layer in place, let’s start painting.

Figure 14. After saving the collision layer, you can begin updating the tiles.
Figure 14. After saving the collision layer, you can begin updating the tiles.

As you can see, there are several collision types set up for us. We are going to focus on solid, which is the pink S tile. The other collision tiles represent slime, and water. You can also add your own tiles. Use the tiles to paint on top of the main level’s walls (see Figure 15).

Figure 15. Lay out the background of the main level with tiles.
Figure 15. Lay out the background of the main level with tiles.

Usually, I put the CollisionMap underneath the main layer. You can reorder layers at any time by simply dragging them around. Now, when we create our player, Impact game enginewill make sure they don’t fall through the floor.

It looks like we are finally ready to start building our game!

Examining and customizing the main class

When setting up a new Impact project from the template project, you will see a main.js file in your game directory. The main class is the entry point to your application and will contain some of the core logic such as binding keyboard events and logic for making the camera follow the player. Most importantly, the main file also defines and loads any required files or global functions in your game. Here is the default main.js class you will start with:

ig.module( 'game.main' ) .requires( 'impact.game', 'impact.font' ) .defines(function(){ MyGame = ig.Game.extend({ // Load a font font: new ig.Font( 'media/04b03.font.png' ), init: function() { // Initialize your game here; bind keys etc. }, update: function() { // Update all entities and backgroundMaps this.parent(); // Add your own, additional update code here }, draw: function() { // Draw all entities and backgroundMaps this.parent(); // Add your own drawing code here var x = ig.system.width/2, y = ig.system.height/2; this.font.draw( 'It Works!', x, y, ig.Font.ALIGN.CENTER ); } }); // Start the Game with 60fps, a resolution of 320x240, scaled // up by a factor of 2 ig.main( '#canvas', MyGame, 60, 320, 240, 2 ); });

Let’s take a moment to go through some of the high-level code. Begin by reviewing the first function:

ig.module( 'game.main' )

This represents the namespace of your game. As you can see, this also defines the name of your main class.

.requires( 'impact.game', 'impact.font' )

This block of code tells the module what JS classes are needed by the game. These classes will automatically load when your game is run for the first time. First, you’ll see that impact.game is the class your game extends from; I’ll talk about this next. After impact.game comes impact.font,which is the font class. By default, the main class of a new project displays some text that says “It Works!” In order to display text, you will need the font class.

Finally, everything in the .defines(function(){ ... }) block of code is your game logic. As you can see, we set up a local variable for the font we use.

// Load a font font: new ig.Font( 'media/04b03.font.png' ),

Then, we define some scaffolding code for init(), update() and draw(). The draw method is the only one with executable code in it. We need to re-render the font on each draw call, so this simply gets the x,y position of where the text field should go so the engine knows where to draw the font graphic.

Before moving on, there is one more thing that is important to highlight. Scroll down to the last few lines in the main.js file:

// Start the Game with 60fps, a resolution of 320x240, scaled // up by a factor of 2 ig.main( '#canvas', MyGame, 60, 320, 240, 2 ); });

This is the code that initializes your game. As you can see, we pass a reference to the Canvas, a name for our game instance, the frame rate and size into the ig.main constructor. The last value of two represents the scale of your game. This will upscale all of your game’s graphics by two. Upscaling is an important technique in order to get better performance out of games. This is especially important when running in software render mode in the browser, which is done by default. You can turn off upscaling but be weary of the possible performance issue you may run into down the line when using larger sprites.

Customizing the main class

To get started, delete the font code, but make sure you leave this.parent(). We can also now delete the font variable from the beginning of the class.

The first thing we want to do is load the level we created and change the .requires(...) block to load the level, like this:

.requires( 'impact.game', 'game.levels.test' )

Unfortunately, if you refresh your game now, nothing is going to display. We will need to tell the game to load our level. Add the following code to your init function:

init: function() { this.loadLevel( LevelTest ); },

Now, refresh the game and see that the test level has loaded (see Figure 16).

Figure 16. Verify that the level loads successfully by refreshing the game.
Figure 16. Verify that the level loads successfully by refreshing the game.

Binding key press events with the input class

Impact includes an easy-to-use input class, which can be found in the ig.input namespace. In order to capture keyboard events, you'll bind the key press event to the desired key in the input class. Place the following code at the beginning of the main.js init() function just above the load level code:

// Bind keys ig.input.bind( ig.KEY.LEFT_ARROW, 'left' ); ig.input.bind( ig.KEY.RIGHT_ARROW, 'right' ); ig.input.bind( ig.KEY.X, 'jump' ); ig.input.bind( ig.KEY.C, 'shoot' );

For our game, we are going to track the left and right arrows along with the X and C keys. This code is all you need to add in order to set up controls for your game. There is a list of constants, which contains all the keys Impact can use in the ig.KEY class. You simply apply a custom label to that key so when the script polls for input in its update loop, it returns the corresponding value when the keys are pressed.

Creating the player class

The first entity you'll build for the sample game is the player. Entities are any objects that exist in the level that are not part of the map. Monsters, bullets, doors, and triggers are all considered entities. The player class extends the main entity.js class, which allows it to run correctly within the Impact game engine. Begin by setting up a simple entity class, like this:

  1. In Dreamweaver, create a new player.js file in the lib/game/entities directory (see Figure 17).
Figure 17. Save the player.js file in the entities subfolder of the game directory.
Figure 17. Save the player.js file in the entities subfolder of the game directory.
  1. Add the following code to the JavaScript file:
ig.module( 'game.entities.player' ) .requires( 'impact.entity' ) .defines(function(){ EntityPlayer = ig.Entity.extend({ }); });

This is the basic structure for creating entities in Impact. We set up the module name and any required classes and define the class and that it extends, such as Entity.

Unfortunately, nothing is actually going to happen if you refresh your game. We still need to configure the player, add them to the level and import them into our main.js class. Before we do all that, let’s finish adding some properties to this class.

  1. Start by setting up an animation sheet. Add the following to the EntityPlayer code block:
animSheet: new ig.AnimationSheet( 'media/player.png', 16, 16 ),

The line of code above instructs the player class to use the player.png file located in the media folder. It also specifies that its tiles are 16 x 16 pixels.

  1. Copy the player.png file to the media folder, so that it's available for the script to access.

You'll also need to define values for the size and offset of the player.

  1. Add the following code below the code you just added to set up the animation sheet:
size: {x: 8, y:14}, offset: {x: 4, y: 2}, flip: false,

The size represents the actual size of the player and the offset tells the animation engine where to render the player sprite inside the bounding box. I’ll cover how this works a little bit later when we talk about the debugger. We just want to make sure that the collision size is smaller than the actual animation frame so we simply move the collision box over just a few pixels.

While we are adding values to the player, let’s set up some physics such as velocity, friction and jump properties.

  1. Copy and paste the following code into the player class file:
maxVel: {x: 100, y: 200}, friction: {x: 600, y: 0}, accelGround: 400, accelAir: 200, jump: 200,

Now we have defined the physics of how our player can move in the environment. Impact handles all of this for us; we simply need to override a few base properties to make it work correctly in our game. Once we get the player up and running in the game, you should feel free to mess around with these values to see how they affect your game play.

With all the player’s core values out of the way, we can look into setting up animation.

  1. Create an init() method in the player class and add the following code to it:
init: function( x, y, settings ) { this.parent( x, y, settings ); this.addAnim( 'idle', 1, [0] ); this.addAnim( 'run', 0.07, [0,1,2,3,4,5] ); this.addAnim( 'jump', 1, [9] ); this.addAnim( 'fall', 0.4, [6,7] ); },

As you can see, we first need to pass up the parent’s init() methods. This is very important since entities need to know their starting x,y positions and any settings assigned to them when being created in the level. You can actually pass in additional values through the level editor, which becomes attached to the settings object during the construction of the entities.

Impact makes it very easy to set up animations. Simply use the entity class’s addAnim() method and pass an ID for the animation, along with the duration and an array for the frames from the sprite sheet.

Before we move on, let’s make sure your player class looks like this:

ig.module( 'game.entities.player' ) .requires( 'impact.entity' ) .defines(function(){ EntityPlayer = ig.Entity.extend({ animSheet: new ig.AnimationSheet( 'media/player.png', 16, 16 ), size: {x: 8, y:14}, offset: {x: 4, y: 2}, flip: false, maxVel: {x: 100, y: 200}, friction: {x: 600, y: 0}, accelGround: 400, accelAir: 200, jump: 200, init: function( x, y, settings ) { this.parent( x, y, settings ); // Add the animations this.addAnim( 'idle', 1, [0] ); this.addAnim( 'run', 0.07, [0,1,2,3,4,5] ); this.addAnim( 'jump', 1, [9] ); this.addAnim( 'fall', 0.4, [6,7] ); } }); });

At this point, we are ready to switch back over to Weltmeister and add our player. When you load the editor back up, you should see our test.js level. If it’s not there, simply re-load. When you load the level, the entities layer should automatically be highlighted. This layer works just like the other layers we created.

  1. In the Canvas area, press spacebar to see the list of entities you can add to the level. Right now, you should see the player listed in the drop-down menu (see Figure 18):
Figure 18. Choose the player option in the menu.
Figure 18. Choose the player option in the menu.
  1. Select the player and add it to the level. You can place the player in any location as a starting place; I placed mine on the right-side platform.
  2. Click Save when you are happy with your player’s start position (see Figure 19).
Figure 19. Position the player at its starting location and then save the project.
Figure 19. Position the player at its starting location and then save the project.

Now, before you can see the player displayed in the game, it's necessary to add the player class to the main.js code.

  1. Add the following to the main.js requires code block:
'game.entities.player'

Take care to add this line of code to the end of the list of required classes that you add, because if you place it in other locations, Impact will present an error.

  1. Save the main.js file. Visit the game in the browser and refresh it to see the player displayed (see Figure 20).
Figure 20. Test the game by running it in a browser.
Figure 20. Test the game by running it in a browser.
  1. You should now see your player in the game, but you will not be able to move him. Let’s fix that. Go back into the player.js class and let’s add the following update() function:
update: function() { // move left or right var accel = this.standing ? this.accelGround : this.accelAir; if( ig.input.state('left') ) { this.accel.x = -accel; this.flip = true; } else if( ig.input.state('right') ) { this.accel.x = accel; this.flip = false; } else { this.accel.x = 0; } // jump if( this.standing && ig.input.pressed('jump') ) { this.vel.y = -this.jump; } // move! this.parent(); }

Note: Make sure to add a comma after the init() method because each method must be separated by commas in the class file.

Now, you are ready to refresh out of the game and test out moving the player (see Figure 21).

Figure 21. After adding the update function, you can press keys to move the player.
Figure 21. After adding the update function, you can press keys to move the player.

As you can see from testing the game, we can move our player but he doesn’t animate or fall off the ledges. We are going to need to set the gravity of the game.

  1. Return to Dreamweaver. Open the main.js file and add the following property to the main class:
gravity: 300

Now, if you go back to your game, you will be able to jump and fall off ledges. When you test it out, though, we will not have a clean-looking fall animation. Let’s add in some additional code to keep track of the player’s velocity in order to show the correct animation such as jump, fall, idle and run.

  1. In Dreamweaver, copy and paste the following code below the existing update function in the player.js class:
// set the current animation, based on the player's speed if( this.vel.y < 0 ) { this.currentAnim = this.anims.jump; } else if( this.vel.y > 0 ) { this.currentAnim = this.anims.fall; } else if( this.vel.x != 0 ) { this.currentAnim = this.anims.run; } else { this.currentAnim = this.anims.idle; }

Now, we should be able to jump and run with animation, but there is one thing missing. We need a way to tell the player to flip his animation based on the direction he is running.

  1. Add the following code just before the this.parent() call in the player.js update function:
this.currentAnim.flip.x = this.flip;

Now we have a fully functional player. Let’s give it one more test and make sure everything works. At this point, our level is kind of boring. In the next part we are going to add a few monsters to the game.

Creating the monster class

  1. Creating a monster is similar to how we created the player. In fact, we are going to use the same basic class code but change its name and namespace. Create a new file called spike.js in the entities folder.
  2. Now copy the following code into the monster class:
ig.module( 'game.entities.spike' ) .requires( 'impact.entity' ) .defines(function(){ EntitySpike = ig.Entity.extend({ }); });

As you can see, we simply changed the entity name and class name but everything else is the same as the code we used to build the player class. Now we are ready to add our monster’s animation and set its size and maximum velocity.

  1. Add the following code to the monster class:
animSheet: new ig.AnimationSheet( 'media/spike.png', 16, 9 ), size: {x: 16, y: 9}, maxVel: {x: 100, y: 100}, flip: false,
  1. Save a copy of the spike.png file to the media folder.

Now we need to set up the animations just like we did for the player. This is a simple monster, so there are only a few sprites representing its animation.

  1. Let’s create a new init method with the following code:
init: function( x, y, settings ) { this.parent( x, y, settings ); this.addAnim( 'crawl', 0.08, [0,1,2] ); }

Now that the monster's default animation is in place, we can start adding instances of the monster to the level to test it.

  1. Switch over to Weltmeister and go to the entity layer then select the sprite monster (see Figure 22).
Figure 22. Choose Spike from the menu to select the monster.
Figure 22. Choose Spike from the menu to select the monster.

Feel free to add a few of them to the map on different platforms (see Figure 23).

Figure 23. Place several instances of monsters on the platforms in the level.
Figure 23. Place several instances of monsters on the platforms in the level.

Before we can test the game to see the monsters, we need to import the spike entity into the main.js file.

  1. In Dreamweaver, add the following code to the requires code block in the main.js file:
'game.entities.spike'

Save the file and refresh the game in your browser. The instances of the monsters are displayed in the game. Unfortunately, they don’t do much right now.

Let’s add in some logic to make them walk back and forth but be smart enough to not fall off their platforms.

  1. We’ll need to create an update function to the monster class that handles the basic AI for our monster by adding the following code:
update: function() { // near an edge? return! if( !ig.game.collisionMap.getTile( this.pos.x + (this.flip ? +4 : this.size.x -4), this.pos.y + this.size.y+1 ) ) { this.flip = !this.flip; } var xdir = this.flip ? -1 : 1; this.vel.x = this.speed * xdir; this.parent(); },

The function shown above checks if the monster hits anything in the CollisionMap. If it does, we toggle the this.flip value.

As you test the game, notice that the direction and velocity are updated before parent is called. We will also need to define the monster’s friction and speed.

  1. Add the following code towards the top of the class, just where we define the flip property.
friction: {x: 150, y: 0}, speed: 14,
  1. Refresh the game in the browser. Try playing the game to see how the player and the monsters behave as the game is played.

You will see the monster instances moving around, and when they hit the edge of a platform, they flip and go the other way (see Figure 24).

Figure 24. Test the game to see the monsters move back and forth on their platforms.
Figure 24. Test the game to see the monsters move back and forth on their platforms.
  1. We just need to add a few more lines of code to clean this up. Add the following block of code:
handleMovementTrace: function( res ) { this.parent( res ); // collision with a wall? return! if( res.collision.x ) { this.flip = !this.flip; } },

This helps make sure that if the monster runs into a wall they also turn around. Collisions with walls and the CollisionMap are handled through the handleMovementTrace function. Now we have covered all our bases and made sure our monster will not fall off a platform, but we still have one issue. There is no collision detection between the monster and the player (see Figure 25).

Figure 25. When a monster collides with the player, the game doesn't respond to the collision.
Figure 25. When a monster collides with the player, the game doesn't respond to the collision.

Before we get into adding more code to the monster, we need to talk a little bit collision detection in Impact JS.

Understanding collision detection, health, and weapons

Since the Impact Game Engine has built-in collision detection, we can focus on setting up collision relationships instead of having to create all the necessary code from scratch. Impact’s collision detection is based on bounding boxes, which look at an entity’s rectangle vs. pixel perfect collision. This is why we have had to tweak the size and offset values of our entities to help make our collision look as clean as possible. This kind of collision detection is super fast and covers a good portion of the use cases you will probably need. To  learn more about Impact’s collision detection, visit the Impact documentation.

Let’s take a look at how to add collision detection to entities in the sample game.

  1. Open the player.js class in Dreamweaver. Add the following code to the properties listed near the top of the class:

As you can see here, we are setting up all three collision properties for the player. We assign the player to TYPE.A, which will represent our friendly group. Next, we set .checkAgainst to NONE since we don’t want the player to apply damage to the monsters he runs into.

Note: If you were building a Mario-type game, you would set this to group B and do a check if the player lands on top of the monster verses running into it from the side.

Finally, we set .collides to COLLIDES.PASSIVE since we will not be moving the player or colliding entity back when there is a collision with the player.

Now it’s time to set up the collision properties for the monster class.

  1. Open the spike.js class and add the following code:
type: ig.Entity.TYPE.B, checkAgainst: ig.Entity.TYPE.A, collides: ig.Entity.COLLIDES.PASSIVE,

So we are setting our monster to the enemy group, which is TYPE.B. Since the player belongs to group A, we will check against that group for collisions. And finally, we also set the enemy .collides property to passive. If we run the game now, you will see that the player and monster appear to be ignoring the collision properties we just set up. We need to add some more code in the monster class in order to handle the collision when it is detected. Add the following method to the spike.js class:

check: function( other ) { other.receiveDamage( 10, this ); }

Remembering back to our introduction about the .checkAgainst property you will remember that I talked about a check method that gets called when a valid collision of the correct type is detected. Here, we are simply overriding the .check() function, which gets called when this collision is detected and now applies damage to the entity it collides with. In this case, the player will lose 10 points of health.

Now, if you re-run the game when the player hits a monster he should be immediately killed. Basically, the player just disappears since we don’t have any death animations.

  Figure 26. When the player and a monster collide, the player disappears.
Figure 26. When the player and a monster collide, the player disappears.

Setting the health property

Each entity in the game has a health property. By default, the health property is set to 0. This value is incredibly useful if you are leveraging the built-in receiveDamage() method to subtract an entity’s health. Use the following line of code to set the health value in the class:

health: 10,

Right now, if we applied this to our player, the collision with the enemy would happen so quickly, since the monster doesn’t push the player back in any way, that it would appear as if there was no difference from what we had before. As we get into creating weapons for our player, we can tweak this value a little more in the monster class and get a better sense of how it will work.

Adding weapons to the game

Right now, our player is totally defenseless in the game. As soon as he hits a monster he dies and there is no way to kill anything. Well, that is about to change, but before we build our first weapon we will have to talk about setting up a special type of class.

When it comes to things like weapons, we don’t need these to show up in the editor. So, just like in other languages where you would use an inner class to help contain scope and hide it from the rest of the application, we can do the same in Impact JS. In this case, we will use an inner class to hide the player’s weapons from the level editor.

Creating an inner class is very similar to making a regular class with the exception that you will be adding it to the end of another class’s code block. They support inheritance as well. If you look at the player.js file you will see the two closing blocks of code for that class at the end.

Figure 27. Scroll to the bottom of player.js code to see an example of an inner class.
Figure 27. Scroll to the bottom of player.js code to see an example of an inner class.

When viewed in Dreamweaver, these closing blocks are located on lines 69 and 71. On line 70, in between the two closing block tags, is where we will be putting our inner class.

Note: Using Impact, you can add as many inner classes as you need.

  1. Let’s set up the beginning of our weapon class in this space. Add the following code to your player.js class:
EntitySlimeGrenade = ig.Entity.extend({ });

So, now you should have your slime grenade entity just before the end of the player.js class like this (see Figure 28):

Figure 28. Paste the slime grenade code between the two existing closing blocks of code.
Figure 28. Paste the slime grenade code between the two existing closing blocks of code.

Now we are ready to customize our player’s weapon.

Customizing the player's weapon

As you can see, the EntitySlimeGrenade entity is similar to the other entities that you've created. It extends ig.Entity and has all the same properties and methods as the player and the monster. The weapon also requires a graphic, so you'll add that first:

  1. Copy the slime-grande.png file into the media folder.
  2. In Dreamweaver, add the following code to the weapon class:
size: {x: 4, y: 4}, offset: {x: 2, y: 2}, animSheet: new ig.AnimationSheet( 'media/slime-grenade.png', 8, 8 ),
  1. Now that you've specified the grenade’s animation sheet, size, and offset, you can set up its collision detection, like this:
type: ig.Entity.TYPE.NONE, checkAgainst: ig.Entity.TYPE.B, collides: ig.Entity.COLLIDES.PASSIVE,

So, in order for our grenade to move and bounce, we will need to add a few additional physic properties.

  1. Add the following code to the weapon class:
maxVel: {x: 200, y: 200}, bounciness: 0.6, bounceCounter: 0,

Here, we are setting our grenade’s maximum velocity. Also, we are going to keep track of how many times it will bounce before being destroyed as well as its bounciness. You can tweak these values later once we enable the player to actually fire the grenade so you can test what effect the bounciness value will have on it.

  1. Override the init method with the following code:
init: function( x, y, settings ) { this.parent( x, y, settings ); this.vel.x = (settings.flip ? -this.maxVel.x : this.maxVel.x); this.vel.y = -50; this.addAnim( 'idle', 0.2, [0,1] ); },

Here, we are going to determine the beginning x velocity based on a flip parameter that will be passing in via the setting parameter. Each entity accepts an object for additional values outside of the standard x and y position. When the player fires the grenade, we will set the player’s own flip value into a property of the settings object so that we know what direction to fire the grenade. Next, we offset the y velocity by -50, which will help add an arc to the grenade when it gets fired off. After that, we just set the idle animation to display sprite 0 and 1.

We are getting very close to testing out our slime grenade, but before we override the handleMovementTrace() method and write some logic to handle collisions, track the number of bounces and remove the grenade from the display if it bounces too many times.

  1. Copy and paste the following code into the weapon class:
handleMovementTrace: function( res ) { this.parent( res ); if( res.collision.x || res.collision.y ) { // only bounce 3 times this.bounceCounter++; if( this.bounceCounter > 3 ) { this.kill(); } } },

The handleMovementTrace() gets called while an entity is moving. This method is associated with the CollisionMap, so we can detect when an entity hits a wall. As you can see, we check the res object parameter if a collision happens on the x or y values. If we detect a collision, we will increment the .bounceCounter by 1. If the .bounceCounter is greater than three then we kill the grenade. We will talk more about the entity kill() method later.

Now that we can handle tracking bounces, let’s add logic when the grenade collides with an enemy. Like we did before in the slime.js class, we are going to override the check function, which gets called when a .checkAgainst group has been detected.

  1. Add the following function to your grenade class:
check: function( other ) { other.receiveDamage( 10, this ); this.kill(); }

We now have everything we need to create a slime grenade; all we need to do now is add some code to our player class so that the player can fire the weapon.

Adding the code to fire the weapon

Since inner classes are just like any other class we would create in Impact JS, we can simply use the ig.game built-in spawnEnity() method to create a new instance of the grenade when the player presses the fire key.

Up until now, both our player and monster are created during the level parsing process, we have not had to manually instantiate an entity yet. The spawnEnity() function helps ensure that when we create a new entity it gets added to Impact JS’s render list.

  1. Open the player.js class in Dreamweaver and paste the following code under the jump logic in the update method:
// shoot if( ig.input.pressed('shoot') ) { ig.game.spawnEntity( EntitySlimeGrenade, this.pos.x, this.pos.y, {flip:this.flip} ); }

As you can see, the code above listens for the shoot event, which we bound to the C key in our main class. This should be very straightforward; we tell ig.game that we are going to spawn a new entity. The spawnEnity() method needs a reference to the class we want to create, its starting x and y position along with any additional settings we want to pass to the new entity. Notice here that we create a generic object with a property called .flip with the player’s flip value. This is what tells the grenade what direction it should be fired.

  1. Refresh the game in the browser and press the C key to test the grenade and see how it works (see Figure 29).
Figure 29. Fire granades by pressing the C key on your keyboard.
Figure 29. Fire granades by pressing the C key on your keyboard.

So, now you should be able fire your weapon and kill the monsters. Also, check out what happens when you go to a higher level and fire slime grenades. The grenades bounce off the walls and disappear after three bounces (see Figure 30).

Figure 30. Experiment by firing grenades to see how they bounce and disappear.
Figure 30. Experiment by firing grenades to see how they bounce and disappear.

At this point, the monsters will die after a single shot. If you change the monster’s life property to something higher, like 100, it will take 10 shots to kill the monster. This is because on every collision the slime grenade detects with an enemy it calls receivedDamage() and passes in 10 as the value. Likewise, you can make the grenade stronger by changing the amount of damage it applies.

Customizing the camera

Right now, our level is really boring. Impact JS was designed to create side scrolling games, so let’s go back into our map editor and extend out the level so the player has some room to run around. Create an opening in the wall and add another room to the map. Make sure that you also increase the size of the main layer and the collision layer to match (see Figure 31).

Figure 31. Expand the width of the level to add more area for the player to run.
Figure 31. Expand the width of the level to add more area for the player to run.

Once you have extended the level, save and try to play it. You may notice something isn’t quite right (see Figure 32).

Figure 32. Try playing the game after extending the width of the level.
Figure 32. Try playing the game after extending the width of the level.

Did you see that the game’s camera is not following the player? We will need to set this up manually in the main.js class.

  1. Return to Dreamweaver and open the main.js file. Override the update function with the following code:
update: function() { // screen follows the player var player = this.getEntitiesByType( EntityPlayer )[0]; if( player ) { this.screen.x = player.pos.x - ig.system.width/2; this.screen.y = player.pos.y - ig.system.height/2; } // Update all entities and BackgroundMaps this.parent(); },

The code above takes advantage of a method of the game class called getEntitiesByType(). This is a very important API when it comes to finding instances of entities in your game. Because we know that there is only a single instance of our player we can explicitly look for them. There are better ways of getting a reference to the player, but for now, we will just use this technique to keep things simple.

After we see if the player exists, we can get the screen resolution and player position to center the screen’s x,y values. By setting the screen.x and screen.y values the renderer will automatically adjust the camera to that position. You can also do a lot of cool tricks with this like easing the camera movement or limiting it so it doesn’t scroll off-screen.

Save the files and refresh the game in the browser. Test the game again. After making the recent changes, the camera now follows the player's movements through the level (see Figure 33).

Figure 33. Move the player and notice how the camera follows it.
Figure 33. Move the player and notice how the camera follows it.

Publishing the game

After you've finished developing a game with the Impact game engine, the last task involves publishing it. Up until this point, you've been running the game in a local host. If you uploaded the game files as-is, it should work online just fine.

The one thing to keep in mind is that you don’t want people to see your source code, and you don’t want to distribute Impact’s source accidentally. To package up our app, we use a technique called baking.

Baking will combine all your game files into a single file, which helps shorten the download time and compress the game. You can run the bake script by doing the following:

Mac

Open up a terminal window, navigate to the tools/ directory and write ./bake.sh

Windows

For Windows, double-click the bake.bat file in the tools/ directory. Make sure that the bake.bat can find the php.exe file on your system. You can either add the installation path of PHP to your PATH environment variable or edit the bake.bat to point directly to your php.exe.

If you get an error message, make sure all the paths are correct. You can open the bake.bat or bake.sh with a text editor. The only two lines you should ever need to change are these:

SET GAME=lib/game/main.js SET OUTPUT_FILE=game.min.js

The GAME variable should point to your game's main.js file while the OUTPUT_FILE determines where the baked script file will be written.

If the script finishes without errors, you can find the game.min.js file in the Impact directory. You can now load this .js file in your .html instead of the two files you had previously. Open up your index.html file and change the following lines:

<script type="text/javascript" src="lib/impact/impact.js"></script> <script type="text/javascript" src="lib/game/main.js"></script>

to this:

<script type="text/javascript" src="game.min.js"></script>

Now, you are ready to upload or distribute the game.min.js source file along with your media directory.

Where to go from here

We have covered a lot of material to help you build your first game with Impact. Right now, you should have a solid foundation of how Impact JS works and are probably ready to make this simple demo into something more fun to play. I highly suggest going through the example games that come with Impact and take a look at other cool things you can do with the game engine. The is a great source of information if you are stuck or looking for inspiration. At this point it shouldn’t be very difficult to build upon this game and make something you can call your own.

Check out the following links to learn more about Impact and setting up the development environment:

  • Impact site: License for the Impact JavaScript game engine
  • Impact demos: Examples of HTML5 games built with Impact
  • XAMPP: Apache distribution containing MySQL, PHP, and Perl for Windows, Mac, and Linux
  • MAMP: Apache distribution containing MySQL and PHP for Mac OS X
 

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement