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

Add Multiple Weapons

So, we built a basic gun that fires bullets, but what about adding something a little more exciting? How about a grenade that bounces and explodes when it hits stuff? We can easily add in new types of weapons just like we did with our bullet. Let’s set up the beginning of our grenade class after our EntityBullet. Add the following inner class to your player.js module:

EntityGrenade = ig.Entity.extend({

});

Just like with our bullet, we are ready to customize the grenade’s properties. We will need to give it a graphic and set the size and offset:

size: {x: 4, y: 4},
offset: {x: 2, y: 2},
animSheet: new ig.AnimationSheet( 'media/grenade.png', 8, 8 ),

Now let’s set up our collision detection:

type: ig.Entity.TYPE.NONE,
checkAgainst: ig.Entity.TYPE.BOTH,
collides: ig.Entity.COLLIDES.PASSIVE,

Pay special attention to the fact that we are setting checkAgainst to TYPE.BOTH. What this means is that our grenade can collide with our zombie and our player. You’ll see how this works when we are ready to test our grenade later on. However, in order for our grenade to move and bounce, we will need to add a few additional properties. Add the following to your grenade 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 blowing up, as well as its bounciness value. You can tweak these values once we enable the player to actually fire the grenade, so you can test what effect the bounciness value will have.

Let’s override the init() method with the following code:

init: function( x, y, settings ) {
    this.parent( x + (settings.flip ? −4 : 7), y, settings );
    this.vel.x = (settings.flip ? -this.maxVel.x : this.maxVel.x);
    this.vel.y = -(50 + (Math.random()*100));
    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 passed in via the settings object. Just like with our bullet, 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. It’s also incredibly important that we get the start x,y position offset correct. Since the grenade can collide with the player, we wouldn’t want it to fire the weapon and instantly blow up.

Next, we offset the y velocity by negative 50 plus a random number that ranges from 0 to 100, which will help add an arc to the grenade when it gets fired. The randomness makes sure that the player throws the grenade slightly differently each time. This, along with the fact that the grenade can also kill the player, will help balance the fact that this is a more powerful weapon. After that, we just set the idle animation to display sprites 0 and 1, which will loop through images of the grenade rotating as it flies through the air.

We are getting very close to testing out our grenade, but before we do, we’ll have to 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:

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();
          }
    }
},

This works exactly like our bullet, except that when a collision is detected, we increment the .bounceCounter by 1. If the .bounceCounter is greater than 3, we kill the grenade. We will talk more about the entity’s 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 EntityBullet class, we are going to override the check function, which gets called when a .checkAgainst group has been detected. Add the following function to your grenade class:

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

Finally, we have increased the damage of the grenade so that it kills anything in a single hit. Now, all we need to do in order to have the player toggle between weapons is bind a new key to toggle between the weapons and then have the player swap between the correct one. Let’s add the following bind logic into our main.js init() function:

ig.input.bind( ig.KEY.TAB, 'switch' );

Now, if we go back into our player class, we will need a way to keep track of the current weapon. Add the following property to the beginning of our EntityPlayer class in the player.js file:

weapon: 0,
totalWeapons: 2,

From there, we can add a simple test to see when the player presses the weapon toggle button, so we can toggle the weapon property. Add the following code below where we test if the shoot button was pressed in the PlayerEntity update() method:

if( ig.input.pressed('switch') ) {
    this.weapon ++;
    if(this.weapon >= this.totalWeapons)
          this.weapon = 0;
    switch(this.weapon){          case(0):
               this.activeWeapon = "EntityBullet";
               break;
          case(1):
               this.activeWeapon = "EntityGrenade";
          break;
    }
}

Now, when we go to spawn our weapon instance, we can simply check to see which weapon is set in the weapon property and spawn the correct instance.

We will also need to add a new property called this.activeWeapon to the top of our class:

activeWeapon: "EntityBullet",

Notice how we have to set the value to a string instead of a reference to the class itself? This will be evaluated correctly when the player class gets created. If we don’t make the default value a string, it will break the player class when it tries to load.

The last thing we need to do is update our shoot code in the player class with the following:

if( ig.input.pressed('shoot') ) {
    ig.game.spawnEntity( this.activeWeapon, this.pos.x, this.pos.y, {flip:this.flip} );
}

This simply spawns a new instance of any class you have set as the this.activeWeapon value. Now you are ready to test out your new grenade and switch between the two weapons.

The player can now throw grenades.

Figure 4-22. The player can now throw grenades.

You may have noticed that the player still looks like he has a gun in his hand and that there really aren’t any visual changes when you switch weapons. We can quickly fix this by modifying how we set up our player’s animations in the init() method. Go ahead and delete the four lines of code where we set up the idle, run, jump, and fall animations. Then add the following in its place:

this.setupAnimation(this.weapon);

Now we will create a new method called setupAnimation(), which takes our current weapon ID as an offset. Here is the code to add below the init() method:

setupAnimation: function(offset){
    offset = offset * 10;
    this.addAnim('idle', 1, [0+offset]);
    this.addAnim('run', .07, [0+offset,1+offset,2+offset,3+offset,4+offset,5+offset]);
    this.addAnim('jump', 1, [9+offset]);
    this.addAnim('fall', 0.4, [6+offset,7+offset]);
},

This is just like our original animation setup, except we now take the weapon ID (which becomes an offset), multiply it by the total number of player frames with a weapon, and add it to each animation. Let’s look at the player sprite sheet so you can see what’s going on.

The player sprites with a gun and without one.

Figure 4-23. The player sprites with a gun and without one.

As you can see, we have 10 sprites holding a gun and 10 sprites without the gun. By offsetting the animation by 10 frames, we can easily switch between the different sets of sprites. This is a common trick, and one we will use later on when we add death animations. For now, we just need to add one last line of code to help update the player graphics when we switch weapons. Add a call to this.setupAnimation() at the end of where we test for the weapon switch key press:

switch(this.weapon){
    case(0):
          this.activeWeapon = "EntityBullet";
          break;
    case(1):
          this.activeWeapon = "EntityGrenade";
    break;
}
this.setupAnimation(this.weapon);

Now when you test and hit the Tab key, you should see the player’s animation change based on the weapon he is using (Figure 4-24).

Now you can see the player’s sprite update when switching between weapons.

Figure 4-24. Now you can see the player’s sprite update when switching between weapons.

From here, you should be able to add even more weapons to your game by simply using the above pattern and building upon it.

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