Creating an emoji chase game with WoofJS

In this tutorial, you will learn how to create a game where the player is being chased and has to keep running for as long a possible without getting caught by the flying emoji. The smiley emoji has to avoid being caught by the ghost emoji. You can customise this game as much as you like with your own characters.

emojirun

Step 1

Go to woofjs.com, login and create a new project. The first thing we will do is change the backdrop colour. You can either provide the name of the desired colour eg. setBackdropColor(“green”) or if you want to use a specific colour you can use a colour code (colour codes begin with a # and contain a combination of 6 numbers and letters from a to f). You can find colour codes at www.codemahal.com/colourpicker. You can also use an image for your backdrop if you like (refer to the previous two tutorials).

Add the following line of code for a light green backdrop:

setBackdropColor("#8CFFC2")

emoji1

Step 2

Now we will create the player sprite. For the player sprite will use an emoji image, set its width and height to 40 and position it in the middle of the screen (0 on the x and y axis). Add the following code:

var player = new Image({
   url: “http://www.codemahal.com/sprites/smiley.png”,
   height: 40,
   width: 40,
   x:0,
   y:0
})

Tip: All of this code can be squashed into one line but to make it easier to read here, each property for the player variable has been added on a new line.

emoji2

Step 3

Next, we can add the “Game over” message text and “Press P to play again” text which will display on screen at the end of the game. Once you have added the two text objects, set them to be hidden using the gameOverText.hide() and playAgainText.hide() lines.

Add the following code:

var gameOverText = new Text({
  x: 0,
  y: 80,
  fontFamily: "Lato",
  size: 30,
  color: "#0B9957",
  text: "Game over!"
});
var playAgainText = new Text({
  x: 0,
  y: 40,
  fontFamily: "Lato",
  size: 20,
  color: "#0B9957",
  text: "Press P to play again"
});

gameOverText.hide()
playAgainText.hide()

Step 4

Now we can add movement for the player object. To do this, create a forever loop and add if statements checking if the arrow keys have been pressed on the keyboard. Add the relevant movement on the x or y axis for the player object in each if statement. Here is the code:

forever(() => {
  if (keysDown.includes('UP')) {
    player.y += 7;
  }
  if (keysDown.includes('DOWN')) {
    player.y -= 7;
  }
  if (keysDown.includes('RIGHT')) {
    player.x += 7;
  }
  if (keysDown.includes('LEFT')) {
    player.x -= 7;
  }
});

Now you should be able to move the player object (smiley emoji) around the screen using the arrow keys on the keyboard.

emoji3

Step 5

Now that we are able to move the player around, we can add enemies (in the form of ghost emojis) that will spawn in random locations at each edge of the screen pointing towards the player. Firstly, we create an empty array (an array is like a list) called enemies which will be used to store all of the enemy clones that will spawn during the game.

We will use the same enemy sprite (a ghost emoji) for each individual enemy but every half a second, clone the enemy sprite and then use random number variable to determine which position the enemy clone should start from at different edges of the screen. Once the enemy clone spawns at a random location at the edge of the screen it will be pointed towards the player and added to the enemies array.

var enemies = [];
every(0.5, "seconds", () => {
  var enemy = new Image({
    url: "http://www.codemahal.com/sprites/ghost.png",
    height: 30,
    width: 30,
    x: 0,
    y: 0
  })
  var randomNumber = random(1, 4);
  if (randomNumber == 1) {
    enemy.x = randomX();
    enemy.y = maxY;
  }
  if (randomNumber == 2) {
    enemy.x = randomX();
    enemy.y = minY;
  }
  if (randomNumber == 3) {
    enemy.x = maxX;
    enemy.y = randomY();
  }
  if (randomNumber == 4) {
    enemy.x = minX;
    enemy.y = randomY();
  }
  enemy.pointTowards(player.x, player.y);
  enemies.push(enemy);
});

emoji4

Step 6

Now that we can clone enemy sprites at different edges of the screen and point them towards the player, we will need to actually make them move towards the player. We can add a forever loop which will constantly get each individual enemy clone in the enemies array and move them (remember, each enemy clone is pointing towards the position of where the player was when that enemy clone spawned, so the enemy clones will move towards the player). We also make sure that each cloned enemy sprite is showing. Add the following code:

forever(() => {
  enemies.forEach(enemy => {
    enemy.move(6);
    enemy.show()
  })
});

emoji5

Step 7

Now we can setup the timer which records how long the player has been running around for without being caught by an enemy. First, we create a timer variable set to 0. Then we create the text which will display the timer on screen. Then, every second we increase the timer by 1 and display the updated time on screen. Add the following code:

var timer = 0
var timerText = new Text({
  x: 0,
  y: maxY - 60,
  fontFamily: "Lato",
  size: 30,
  color: "red",
  text: () => 'Timer: ' + timer
});

every(1, "second", () => {
  timer++;
  timerText.text = 'Timer: ' + timer
});

At this point this is what the game should look like:

emoji6

Step 8

Now we can add a forever loop which will go through each enemy that exists in the enemies array and check if they are touching the player. If an enemy touches the player, then the “Game over” and “Press P to play again” text will be displayed on screen. The player object will also be hidden and the freeze() function will be called which will freeze the screen.

forever(() => {
  enemies.forEach(enemy => {
    if (enemy.touching(player)) {
      gameOverText.show()
      playAgainText.show()
      player.hide()
      freeze();
    }
  })
});

emoji7

Step 9

Next, we add another forever loop. In this forever loop we check if the P key is pressed on the keyboard and if so, then show the player object on screen, hide the “Game over” and “Press P to play again” messages, and go through all the enemy clones which exist in the enemies array and delete each one. The enemies array is set to be an empty array again, the timer is set to 0, the player object is moved back to the centre of the screen, and the defrost() function is called which un-freezes the game. Add the following code:

forever(() => {
  if(keysDown.includes("P")){
    player.show()
    gameOverText.hide()
    playAgainText.hide()
    enemies.forEach(enemy => enemy.delete())
    enemies = []
    timer = 0
    player.x = 0
    player.y = 0
    defrost();
  }
})

emoji8

Step 10

The final step is to add some code which will ensure the player cannot leave the screen. By adding the following code in a forever loop, we can constantly check if the player is going beyond any edges of the screen, and if so, stop them going any further. Add the following code to your game:

forever(() => {
  if (player.x > maxX) {
    player.x = maxX;
  }
  if (player.x < minX) {
    player.x = minX;
  }
  if (player.y > maxY) {
    player.y = maxY;
  }
  if (player.y < minY) {
    player.y = minY;
  }
});

This is what the game and code will look like once you’re done!

emoji9

Now play your game and see how long you can last without getting caught by a ghost emoji! You can try adding a high score feature to the game and also adjust some of the variables to increase or decrease the speed of the enemy movements depending on how challenging you want the game to be. You could have the enemies start off moving slowly and gradually build up speed over time too. Make sure you save your work!

Complete code

// Based on the game at woofjs.com/create.html#poop-emoji

setBackdropColor("#8CFFC2")
var player = new Image({
  url: "http://www.codemahal.com/sprites/smiley.png",
  height: 40,
  width: 40,
  x: 0,
  y: 0
}) 

var gameOverText = new Text({
  x: 0,
  y: 80,
  fontFamily: "Lato",
  size: 30,
  color: "#0B9957",
  text: "Game over!"
});
var playAgainText = new Text({
  x: 0,
  y: 40,
  fontFamily: "Lato",
  size: 20,
  color: "#0B9957",
  text: "Press P to play again"
});

gameOverText.hide()
playAgainText.hide()

forever(() => {
  if (keysDown.includes('UP')) {
    player.y += 7;
  }
  if (keysDown.includes('DOWN')) {
    player.y -= 7;
  }
  if (keysDown.includes('RIGHT')) {
    player.x += 7;
  }
  if (keysDown.includes('LEFT')) {
    player.x -= 7;
  }
});

var enemies = [];
every(0.5, "seconds", () => {
  var enemy = new Image({
    url: "http://www.codemahal.com/sprites/ghost.png",
    height: 30,
    width: 30,
    x: 0,
    y: 0
  })
  var randomNumber = random(1, 4);
  if (randomNumber == 1) {
    enemy.x = randomX();
    enemy.y = maxY;
  }
  if (randomNumber == 2) {
    enemy.x = randomX();
    enemy.y = minY;
  }
  if (randomNumber == 3) {
    enemy.x = maxX;
    enemy.y = randomY();
  }
  if (randomNumber == 4) {
    enemy.x = minX;
    enemy.y = randomY();
  }
  enemy.pointTowards(player.x, player.y);
  enemies.push(enemy);
});

forever(() => {
  enemies.forEach(enemy => {
    enemy.move(6);
    enemy.show()
  })
});

var timer = 0
var timerText = new Text({
  x: 0,
  y: maxY - 60,
  fontFamily: "Lato",
  size: 30,
  color: "red",
  text: () => 'Timer: ' + timer
});

every(1, "second", () => {
  timer++;
  timerText.text = 'Timer: ' + timer
});

forever(() => {
  enemies.forEach(enemy => {
    if (enemy.touching(player)) {
      gameOverText.show()
      playAgainText.show()
      player.hide()
      freeze();
    }
  })
});

forever(() => {
  if (keysDown.includes("P")) {
    player.show()
    gameOverText.hide()
    playAgainText.hide()
    enemies.forEach(enemy => enemy.delete())
    enemies = []
    timer = 0
    player.x = 0
    player.y = 0
    defrost();
  }
})

forever(() => {
  if (player.x > maxX) {
    player.x = maxX;
  }
  if (player.x < minX) {
    player.x = minX;
  }
  if (player.y > maxY) {
    player.y = maxY;
  }
  if (player.y < minY) {
    player.y = minY;
  }
});