DEV Community

Cover image for From Concept to Code: Building a Simple Endless Runner Game
Chipm0nk
Chipm0nk

Posted on

From Concept to Code: Building a Simple Endless Runner Game

Creating an endless runner game is a fun way to dive into game development. These games are straightforward, addictive, and allow for plenty of creative tweaks. Think about it: with just a few simple mechanics-running, jumping, dodging-you can make something that keeps players glued to their screens.

Games like Temple Run, Flappy Bird, and Subway Surfers all started with this same simple idea, yet they've entertained millions worldwide.

In this guide, I'll show you how to build your own endless runner from scratch. We'll keep things simple and walk through the essential steps to get a basic game up and running.

Step 1: Understand the Core Mechanics

Before diving into code, let's break down what makes an endless runner game work. The core mechanics are simple:

Automatic movement: The main character moves forward automatically, so the player doesn't need to control the forward motion.

Obstacles: These appear on the screen, and players need to react quickly to avoid them.

Player actions: Usually, players can either jump, duck, or maybe shoot to interact with obstacles.

These core mechanics give us a blueprint for what we'll need to build. The idea is to keep things as simple as possible while ensuring a smooth experience.

Step 2: Start with the Basic Structure

To build a basic endless runner, you can start by setting up a structure in HTML, CSS, and JavaScript.

Setting Up the HTML Canvas

First, create a basic HTML file with a canvas element. Here's what that might look like:

First, create a basic HTML file with a canvas element:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Endless Runner</title>
  <style>
    canvas {
      background-color: #eee;
      display: block;
      margin: 0 auto;
    }
  </style>
</head>
<body>
  <canvas id="gameCanvas" width="800" height="400"></canvas>
  <script src="game.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Configuring the Canvas in JavaScript

Next, we'll need to create a basic game loop in JavaScript to keep our game running. The game loop is the "heart" of the game, updating the screen every frame.

Here's a simple version of a game loop:

const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");

function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // Game code goes here

  requestAnimationFrame(gameLoop); // keeps the loop going
}

gameLoop();
Enter fullscreen mode Exit fullscreen mode

Explanation: We're using requestAnimationFrame to run the gameLoop function continuously, which will update the game every frame. This function clears the screen, and later we'll add our game objects here.

Step 3: Adding the Player Character

In endless runners, the player character often only has one or two actions, like jumping or ducking. For this guide, let's keep it simple and focus on jumping.

Creating a Simple Player Object

We'll define the player as an object with properties like position, size, and velocity. Here's an example:

const player = {
  x: 50,
  y: canvas.height - 60,
  width: 50,
  height: 50,
  color: "blue",
  velocityY: 0,
  isJumping: false
};

Enter fullscreen mode Exit fullscreen mode

This gives us a square "player" who can jump. The isJumping property will help us control whether the player can jump again or not.

Drawing the Player on the Screen

Add the following to the gameLoop to draw the player:

function drawPlayer() {
  ctx.fillStyle = player.color;
  ctx.fillRect(player.x, player.y, player.width, player.height);
}

Enter fullscreen mode Exit fullscreen mode

Call drawPlayer() in the game loop:

function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  drawPlayer();
  requestAnimationFrame(gameLoop);
}

Enter fullscreen mode Exit fullscreen mode

Step 4: Adding Jump Mechanics

To make the player jump, we'll listen for keyboard input. When the player presses the "Space" key, the player character should jump.

Handling the Jump Action

document.addEventListener("keydown", (event) => {
  if (event.code === "Space" && !player.isJumping) {
    player.velocityY = -10;
    player.isJumping = true;
  }
});

Enter fullscreen mode Exit fullscreen mode

When Space is pressed, we set the player's vertical velocity to a negative value so it moves upward. We also set isJumping to true, preventing double jumps.

Implementing Gravity

Gravity will bring the player back down after they jump. This can be done by adding a constant force pulling the player down each frame:

function updatePlayer() {
  player.y += player.velocityY;
  player.velocityY += 0.5; // Gravity effect

  // Ground detection
  if (player.y > canvas.height - player.height) {
    player.y = canvas.height - player.height;
    player.velocityY = 0;
    player.isJumping = false;
  }
}

Enter fullscreen mode Exit fullscreen mode

Now, call updatePlayer() in the gameLoop to make the player fall back down after jumping.

Step 5: Creating Obstacles

Obstacles make endless runners challenging. They appear from the right side of the screen and move left. If the player hits an obstacle, it's game over.

Defining Obstacle Properties

Here's a simple way to set up obstacles:

const obstacles = [];

function createObstacle() {
  obstacles.push({
    x: canvas.width,
    y: canvas.height - 50,
    width: 20,
    height: 50,
    color: "red"
  });
}

Enter fullscreen mode Exit fullscreen mode

This function creates a new obstacle at the right edge of the canvas. We can then move it left each frame.

Moving Obstacles

In gameLoop, add a function to move and draw obstacles:

function updateObstacles() {
  obstacles.forEach((obstacle, index) => {
    obstacle.x -= 5; // Speed of obstacle

    // Remove obstacles that go off-screen
    if (obstacle.x + obstacle.width < 0) {
      obstacles.splice(index, 1);
    }
  });
}

function drawObstacles() {
  obstacles.forEach(obstacle => {
    ctx.fillStyle = obstacle.color;
    ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
  });
}

Enter fullscreen mode Exit fullscreen mode

Add updateObstacles() and drawObstacles() to gameLoop.

Step 6: Collision Detection

Now, let's add collision detection. If the player hits an obstacle, the game will stop or restart.

function checkCollision() {
  obstacles.forEach(obstacle => {
    if (
      player.x < obstacle.x + obstacle.width &&
      player.x + player.width > obstacle.x &&
      player.y < obstacle.y + obstacle.height &&
      player.y + player.height > obstacle.y
    ) {
      alert("Game Over!");
      window.location.reload();
    }
  });
}

Enter fullscreen mode Exit fullscreen mode

Run checkCollision() inside the gameLoop.

Step 7: Bringing It All Together

Here's the complete gameLoop after adding all these functions:

function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  updatePlayer();
  updateObstacles();
  checkCollision();

  drawPlayer();
  drawObstacles();

  requestAnimationFrame(gameLoop);
}

Enter fullscreen mode Exit fullscreen mode

Finally...

Endless runner games are simple to create but offer a lot of room for creativity. You can add different obstacles, power-ups, and even level progression. Start small, and as you grow, add more features to make your game unique.

Who is behind this post?

So this is Chipm0nk a Scratch game developer, currently working on a project to make geometry dash an endless runner game. See you in the comment box!

Top comments (0)