Game states: start menu, game over menu, etc.

Game and object states: start menu, game-over menu, etc.

Object states

With our game framework handling the basics, we can make things more exciting by causing something to happen when a collision occurs – maybe the player ‘dies’, balls are removed, or we should add to your score? Usually, we add extra properties to the player and enemy objects. For example, a boolean dead property that will record if an object is dead or alive: if a ball is marked “dead”, do not draw it! If all balls are dead: go to the next level with more balls, faster balls, etc…

Let’s try adding a dead property to balls and consult it before drawing them. We could also test to see if all the balls are dead, in which case we recreate them and add one more ball. Let’s update the score whenever the monster eats a ball. And finally, we should add a test in the createBalls function to ensure that no balls are created on top of the monster.

Try this jsBin!

Eat the ball game

Source code extract:

  1. function updateBalls(delta) {
  2.    // for each ball in the array
  3.    var allBallDead = true;
  4.    for(var i=0; i < ballArray.length; i++) {
  5.      var ball = ballArray[i];
  6.      if(ball.dead) continue; // do nothing if the ball is dead
  7.      // if we are here: the ball is not dead
  8.      allBallDead = false;
  9.      // 1) move the ball
  10.      ball.move();
  11.      // 2) test if the ball collides with a wall
  12.      testCollisionWithWalls(ball);
  13.      // Test if the monster collides
  14.      if(circRectsOverlap(monster.x, monster.y,
  15.                          monster.width, monster.height,
  16.                          ball.x, ball.y, ball.radius)) {
  17.         //change the color of the ball
  18.         ball.color = ‘red’;
  19.         ball.dead = true;
  20.         // Here, a sound effect would greatly improve
  21.         // the experience!
  22.         currentScore+= 1;
  23.      }
  24.      // 3) draw the ball
  25.      ball.draw();
  26.   }
  27.   if(allBallDead) {
  28.      // reset all balls, create more balls each time
  29.      // as a way of increasing the difficulty
  30.      // in a real game: change the level, play nice music!
  31.      nbBalls++;
  32.      createBalls(nbBalls);
  33.    }
  34. }

Game states: menus, high score tables etc…

In this example, we will make use of a global gameState variable for managing the life-cycle of the game. Usually, there is a main menu with a “start new game” option, then we play the game, and if we ‘die’ we suffer a game-over screen, etc…

Ah!… you think that the game has been too easy? Let’s reverse the game: now you must survive without being touched by a ball!!!

Also, every five seconds a next level will start: the set of balls is re-created, and each level has two more than before. How long can you survive?

Try this JsBin, then look at the source code. Start from the mainloop!

currentGameState = gameStates.gameOver:

Game Over Screen, asking to press space to start again

currentGameState = gameStates.gamerunning:

game running, showing score, time, level

Game state management in the JavaScript code:

  1. // game states
  2. var gameStates = {
  3.    mainMenu: 0,
  4.    gameRunning: 1,
  5.    gameOver: 2
  6. };
  7. var currentGameState = gameStates.gameRunning;
  8. var currentLevel = 1;
  9. var TIME_BETWEEN_LEVELS = 5000; // 5 seconds
  10. var currentLevelTime = TIME_BETWEEN_LEVELS;
  11. var mainLoop = function (time) {
  12.    …
  13.    // number of ms since last frame draw
  14.    delta = timer(time);
  15.    // Clear the canvas
  16.    clearCanvas();
  17.    // monster.dead is set to true in updateBalls when there
  18.    // is a collision
  19.    if (monster.dead) {
  20.       currentGameState = gameStates.gameOver;
  21.    }
  22.    switch (currentGameState) {
  23.       case gameStates.gameRunning:
  24.         // draw the monster
  25.         drawMyMonster(monster.x, monster.y);
  26.         // Check inputs and move the monster
  27.         updateMonsterPosition(delta);
  28.         // update and draw balls
  29.         updateBalls(delta);
  30.         // display Score
  31.         displayScore();
  32.         // decrease currentLevelTime. Survive 5s per level
  33.         // When < 0 go to next level
  34.        currentLevelTime -= delta;
  35.        if (currentLevelTime < 0) {
  36.           goToNextLevel();
  37.        }
  38.        break;
  39.     case gameStates.mainMenu:
  40.        // TO DO! We could have a main menu with high scores etc.
  41.        break;
  42.     case gameStates.gameOver:
  43.        ctx.fillText(“GAME OVER”, 50, 100);
  44.        ctx.fillText(“Press SPACE to start again”, 50, 150);
  45.        ctx.fillText(“Move with arrow keys”, 50, 200);
  46.        ctx.fillText(“Survive 5 seconds for next level”, 50, 250);
  47.        if (inputStates.space) {
  48.           startNewGame();
  49.        }
  50.        break;
  51.     }
  52.      …
  53.    };
  54. … 

And below are the functions for starting a new level, starting a new game, and the updateBalls function that determines when a player loses and changes the current game-state to GameOver:

  1. function startNewGame() {
  2.     monster.dead = false;
  3.     currentLevelTime = 5000;
  4.     currentLevel = 1;
  5.     nbBalls = 5;
  6.     createBalls(nbBalls);
  7.     currentGameState = gameStates.gameRunning;
  8. }
  9. function goToNextLevel() {
  10.     // reset time available for next level
  11.     // 5 seconds in this example
  12.    currentLevelTime = 5000;
  13.    currentLevel++;
  14.    // Add two balls per level
  15.    nbBalls += 2;
  16.    createBalls(nbBalls);
  17. }
  18. function updateBalls(delta) {
  19.     // Move and draw each ball, test collisions,
  20.     for (var i = 0; i < ballArray.length; i++) {
  21.        …
  22.        // Test if the monster collides
  23.        if (circRectsOverlap(monster.x, monster.y,
  24.                             monster.width, monster.height,
  25.                             ball.x, ball.y, ball.radius)) {
  26.            //change the color of the ball
  27.            ball.color = ‘red’;
  28.            monster.dead = true;
  29.            // Here, a sound effect greatly improves
  30.            // the experience!
  31.            plopSound.play();
  32.        }
  33.        // 3) draw the ball
  34.        ball.draw();
  35.     }
  36. }

Leave a comment