You are previewing Building HTML5 Games with ImpactJS.

Building HTML5 Games with ImpactJS

Cover of Building HTML5 Games with ImpactJS by Jesse Freeman Published by O'Reilly Media, Inc.
  1. Introducing HTML5 Game Development
  2. SPECIAL OFFER: Upgrade this ebook with O’Reilly
  3. A Note Regarding Supplemental Files
  4. Preface
    1. About This Book
    2. Who This Book Is For
    3. Who This Book Is Not For
    4. Conventions Used in This Book
    5. This Book’s Example Files
    6. Using Code Examples
    7. How To Use This Book
    8. Safari® Books Online
    9. How to Contact Us
    10. Acknowledgments
  5. 1. Introduction To Impact
    1. Why Use Impact?
    2. Setting Up a Local Environment
    3. Install WebStorm/PHPStorm
    4. Install Apache/PHP/MySQL
    5. Other Hosting Options
    6. Setting Up a New Impact Project
    7. Modules
    8. How Classes Work
    9. Core Classes
    10. How Inner Classes Work
    11. Level Editor
  6. 2. Working With Sprites
    1. Sprites and Sprite Sheets
    2. Scripting in Photoshop
    3. Working with Sprites in Photoshop
    4. Optimizing Sprites
  7. 3. Introduction To Game Design
    1. What is Game Design?
    2. Sample Game Design Document
      1. Gameplay
      2. Exploring a Map
      3. Combat
      4. Completing a Map
      5. Death
      6. Main Character
      7. Monsters
      8. Bosses
      9. Equipment
      10. Inventory
      11. Equipping Items
      12. Weapons and Armor
      13. Leveling Up
      14. Winning the Game
    3. Coming Up With Ideas
    4. Books to Read
  8. 4. Building A Game
    1. Creating Our First Level
    2. Saving/Loading Maps in Weltmeister
    3. CollisionMaps
    4. The Main Class
    5. Customizing the Main Class
    6. Key Binding
    7. Creating the Player Class
      1. Using Your Sprite Sheet
      2. Adding Simple Physics
      3. Defining Animation Sequences
    8. Creating a Monster Class
    9. Collision Detection
    10. type Property
    11. checkAgainst Property
    12. collides Property
    13. Health
    14. Weapons
    15. Firing the Weapon
    16. Add Multiple Weapons
    17. Killing Entities
    18. Respawning the Player
    19. Create Death Animations
    20. Adding Grenade Explosions
    21. Customizing the Camera
    22. Loading New Levels
  9. 5. Working With Text
    1. Creating Font Sprite Sheets
    2. Adding Text to Your Game
  10. 6. Working With Sound
    1. Adding Sounds
    2. Adding Music
    3. Mobile Browser Sound Compatibility Issues
  11. 7. Creating Game Screens and HUDs
    1. Extending Impact’s Game Class
    2. Creating a Start Screen
    3. Player Stats Screen
    4. Creating the Game Over Screen
    5. Adding In-Game HUD
    6. Game Rewards
    7. In-Game Analytics
  12. 8. Debugging Your Game
    1. Impact’s Debugger
    2. Publishing Your Game
    3. Baking Your Game
    4. Mobile Web Support
    5. Compiling for Native iOS
  13. 9. Wrapping Up
    1. References and Links
  14. About the Author
  15. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Creating the Player Class

The player will be the first entity we build for our game. Entities are anything that exist in the level that are not part of the map. Monsters, bullets, doors, triggers, etc., are all considered entities. Our player class will extend the core entity.js class so it can inherit some basic behavior to get us started. Let’s begin by creating a new player.js file in the lib/game/entities directory.

Our player class goes in the entities directory.

Figure 4-11. Our player class goes in the entities directory.

Now, add the following code to our file:

1    ig.module(
2        'game.entities.player'
3    )
4    .requires(
5        'impact.entity'
6    )
7    .defines(function(){
8        EntityPlayer = ig.Entity.extend({
9
10        });
11    });

This is the basic structure for creating entities in Impact. As discussed previously, we define the module name and reference any required classes, then define the class itself, extending ig.Entity. At this point, however, nothing will happen if you refresh your game. We still need to set up the player and add it to the level. To do that, let’s add some properties to this class.

Using Your Sprite Sheet

Start by setting up an animation sheet. Add the following to the EntityPlayer code block:

EntityPlayer = ig.Entity.extend({
    animSheet: new ig.AnimationSheet( 'media/player.png', 16, 16 ),
});

This tells our player that it will use player.png in the media folder and that its tiles are 16×16. We are also going to need to define some values for the size and offset of the player. We’ll add the following underneath where we set up our animation sheet:

size: {x: 8, y:14},
offset: {x: 4, y: 2},
flip: false,

The size property represents the actual size of the player. The offset property describes any change in the player size needed to make collisions more accurate. In this case, we’re offsetting the bounding box used for collisions by 4 pixels on the left and right, and 2 pixels on top and bottom. By making the collision area smaller than the sprite, we can better account for the transparent space around the graphic. Finally, we don’t flip the player, so it remains oriented in its original direction.

Adding Simple Physics

Next let’s set up some physics properties, such as velocity, friction, rate of acceleration in the ground and air, and jump strength.

maxVel: {x: 100, y: 150},
friction: {x: 600, y: 0},
accelGround: 400,
accelAir: 200,
jump: 200,

These properties define how our player can move in the environment. Impact handles all of the physics calculations for us. Once we get the player up and running, you should feel free to tweak these values to see how they affect your game.

Defining Animation Sequences

With the player’s core values out of the way, we can look into setting up animation sequences. Create an init() method underneath where we defined the properties 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] );
},

This function passes the x,y and settings values up to the parent’s init() method. 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 also pass in additional values through the level editor, which get attached to the settings object during the construction of the entities.

As discussed earlier, it’s easy to set up animations. Use the entity class’s addAnim() method and pass it an ID (or name) 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:

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

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 dorm1.js level. If it’s not there, simply load it up manually. When you load the level, the entities layer should automatically be highlighted. This layer works just like the other layers we created, so move over to the Canvas area and press the space bar to see the list of entities you can add to the level. Right now, you should see the player from the drop-down menu.

Select the player from the pop-up entity menu.

Figure 4-12. Select the player from the pop-up entity menu.

Select the player and add him to the level. You can place him anywhere for now; I put mine on the far left of the level. Also, make sure you hit Save once you are happy with your player’s start position.

A preview of the player in the level editor.

Figure 4-13. A preview of the player in the level editor.

It’s also important to note that as of version 1.19 of Impact, you no longer need to add each entity to your game’s requires block; it is now automatically handled for you when the level is loaded. Now you are ready to test out your game. Go to your browser and hit refresh.

The player is now in our game’s level.

Figure 4-14. The player is now in our game’s level.

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 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

As you continue adding code to your game, always make sure there is a comma to separate new functions, or you may get an error when you try to preview your code.

Now, you are ready to refresh the game and test out moving the player. As you can see, we can move our player, but he doesn’t animate or fall off ledges. We are going to need to set the gravity of the game. We can do this in main.js. Add the following property to that class:

MyGame = ig.Game.extend({
    gravity: 300,
    init: function() {

Now, if you go back to your game, you will be able to jump and fall off ledges. When you test it out, though, you 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. This should go below our jump code 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 corresponding 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. We can do this by adding 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—so let’s add a few monsters to the game.

The best content for your career. Discover unlimited learning on demand for around $1/day.