Ch015 - Game Mechanic: Player Health Meter

Ch015 - Game Mechanic: Player Health Meter

Game Mechanic: Player Health Meter

The game mechanic of having a health meter which is depleted when you come into contact with enemies and their projectiles can be very welcome if you have a challenging layout of levels. This can stop your game from being too hard.

What we need to know and what we will do

Our health mechanic is going to build on the code we are using when our player collides with a hazard. As such you may need to know about.

You can use the following stages as a checklist;

  • create a graphical health bar
  • reduce the level of this health bar as our player gets hit
  • move our player to the side of the enemy and stop their health from draining too much all the time the player is overlapping with the enemy
  • restart the game when the health bar reaches zero

Going over the code:

The code for a minimal example of the Player Health Bar game mechanic is shown here - https://jamm-labs.github.io/ggcp/player-health-meter/game.js

In our create function , after we have added our player to the game, we can set the health of our player to be a value of 100;

  player.health = 100;

Health is actually a built in property of Phaser and when that reaches zero our player will disappear automatically. But let’s add some code anywhere in our update function to check when health is down to zero and restart the game.

  if (player.health === 0) {
    restart();
  }

Next we need to build and display the graphical health bar and this is done by calling the following function one at the end of the create function.

var createHealthBar = function () {
     meters = game.add.group();

    // create a plain black rectangle to use as the background of a health meter
    var meterBackgroundBitmap = game.add.bitmapData(20, 100);
    meterBackgroundBitmap.ctx.beginPath();
    meterBackgroundBitmap.ctx.rect(0, 0, meterBackgroundBitmap.width, meterBackgroundBitmap.height);
    meterBackgroundBitmap.ctx.fillStyle = '#000000';
    meterBackgroundBitmap.ctx.fill();

    // create a Sprite using the background bitmap data
    var healthMeterBG = game.add.sprite(10, 10, meterBackgroundBitmap);
    healthMeterBG.fixedToCamera = true;
    meters.add(healthMeterBG);

    // create a red rectangle to use as the health meter itself
    var healthBitmap = game.add.bitmapData(12, 92);
    healthBitmap.ctx.beginPath();
    healthBitmap.ctx.rect(0, 0, healthBitmap.width, healthBitmap.height);
    healthBitmap.ctx.fillStyle = '#FF0000';
    healthBitmap.ctx.fill();

    // create the health Sprite using the red rectangle bitmap data
    health = game.add.sprite(14, 14, healthBitmap);
    meters.add(health);
    health.fixedToCamera = true;
};

The code above creates a black box to act as the background and then a red box to act as the health meter. Now have a look at the updated hitHazard part of our code (if you don’t have one you should add one);

var hitHazard = function (player, hazard) {

    if (!player.immune) {
      player.damage(10);
      updateHealthBar();
      player.immune = true;
      game.time.events.add(200, function () {player.immune = false;}, this);
    }

    if (player.body.position.x < enemy1.body.position.x) {
      player.body.velocity.x = -200;
    }
    else {
      player.body.velocity.x = 200;
    }
};

What’s to stop our player from being drained of all health points in one go, when the player is zapped by overlapping with a hazard we need to set a quick time limit where they can’t get zapped again. Let’s called this time when the player is immune from harm. In the code above if the player isn’t immune - if (!player.immune) - then we zap the players' health by 10 points and make a call to a function to update the health bar, to reduce the value a bit. We also add code to say that the player is now immune and will stay that way for 200 miliseconds (0.2 of a second).

This time is enough to prevent this section of code running again until we can run the next code which moves the player out of the way of the enemy. It checks to see if the player is more to the right or to the left of the enemy using the player.body.position property, and then changes their velocity value to bump them out of the way of the enemy. Doing this then stops the hitHazard function from being called as the player and the enemy are no longer overlapping.

There is also another thing we need to add to the update function in our code. We need to stop the game player from controlling our player character when it is immune. Have a look at the extra conditions which makes this happen. One example is show below. Be sure to update all of them!

  if (!player.immune && game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
    player.body.velocity.x = -300
  } 

That’s it. We hope you enjoy adding this game dynamic to your game

Follow up Resources: If you want find out more about the code for doing the maths and the process to update the health meter then there is a more in depth look at this dynamic at the website where the code was originally found - https://thoughts.amphibian.com/2015/12/putting-health-meter-in-my-phaser-game.html