Create an infinite runner game in HTML with ease! Learn basics, setup, draw canvases, add jumping, obstacles, scoring, and share your creation.
Welcome to our comprehensive guide on creating an endless runner game using HTML, CSS, and JavaScript. Whether you're a beginner or looking to enhance your web development skills, this tutorial will walk you through each step to build a fun and addictive game that runs right in your browser.
Ever played games like Temple Run or Subway Surfers and thought, "I wish I could make something like that"? Well, guess what? You can! We're gonna make an endless runner game using HTML. It's gonna be fun, I promise!
These games are pretty simple but super addictive. You just run, jump, and dodge stuff. But they're great for learning how to make games. Plus, we're using HTML, CSS, and JavaScript, so you can play your game right in your web browser. Cool, right? Let's get started!
Before we start coding, let's talk about what makes these games tick. It's like knowing the rules before you play a new board game.
In these games, your character keeps running without you telling them to. It's like being on a treadmill - you're always moving forward. This means players just focus on jumping and dodging, which makes the game easier to play.
We gotta give players something to do, right? That's where obstacles come in. They're like hurdles in a race. You might need to jump over them, slide under them, or move around them. They keep the game exciting and make you pay attention.
Even though the character runs on their own, players can do things like jump or duck. It's like playing hopscotch - you decide when to jump to avoid stepping on the lines. These moves help you get past the obstacles and keep playing.
Understanding these basics helps us know what we need to build. It's like having a blueprint before you start building a Lego set.
Okay, now we're ready to start building our game. We'll use HTML, CSS, and JavaScript - they're like the building blocks of websites.
First, we need to make the main file for our game. It's like setting up a blank canvas before you start painting.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Endless Runner Game</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="gameCanvas" width="800" height="400"></canvas>
<script src="game.js"></script>
</body>
</html>
This is like the skeleton of our game. The
<canvas>
tag is where we'll draw our game, and we're linking to our CSS and JavaScript files.
We'll make two more files:
You can use any text editor to make these files. I like using Visual Studio Code , but you can use whatever you're comfortable with. The important thing is to have fun while you're coding!
The canvas is where all the action happens in our game. It's like the TV screen where you see your game characters.
In HTML, the
<canvas>
tag is special. It lets us draw stuff using JavaScript. It's perfect for games because we can change what's on it really fast.
We already put the canvas in our HTML. Now let's get it ready in JavaScript:
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
This code finds our canvas and gets it ready for 2D drawing. It's like getting your pencils and paper ready before you start drawing.
Games need to update and redraw things many times a second. We do this with a game loop. Here's a simple one:
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// We'll add game stuff here later
requestAnimationFrame(gameLoop);
}
gameLoop();
This loop clears the canvas and then runs again and again. It's like flipping through a flipbook to make an animation.
When I first learned about game loops, it felt like I was creating the heartbeat of my game. Every time the loop runs, it's like a new frame in a movie, bringing your game to life!
Now let's add the star of our game - the character that runs and jumps!
First, we'll make an object for our runner:
const player = {
x: 50,
y: canvas.height - 60,
width: 50,
height: 50,
velocityY: 0,
gravity: 1.5,
isJumping: false
};
This sets up where our player is, how big they are, and some stuff for jumping.
Let's make a function to draw our player:
function drawPlayer() {
ctx.fillStyle = '#FF0000'; // Red color
ctx.fillRect(player.x, player.y, player.width, player.height);
}
This draws a red rectangle for our player. You could make it fancier later!
We need to update the player's position each frame:
function updatePlayer() {
player.y += player.velocityY;
player.velocityY += player.gravity;
// Stop the player from falling through the ground
if (player.y + player.height >= canvas.height - 10) {
player.y = canvas.height - player.height - 10;
player.isJumping = false;
player.velocityY = 0;
}
}
This makes the player fall due to gravity but stops them at the ground.
Update your game loop to use these new functions:
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updatePlayer();
drawPlayer();
requestAnimationFrame(gameLoop);
}
Now you should see a red rectangle at the bottom of your canvas. That's your runner!
What's a runner game without jumping? Let's add that next!
We need to know when the player wants to jump. We'll use the spacebar:
document.addEventListener('keydown', function(event) {
if (event.code === 'Space' && !player.isJumping) {
player.velocityY = -20;
player.isJumping = true;
}
});
This makes the player jump up when you press the spacebar, but only if they're not already jumping.
To make the jump feel right, we might need to adjust some numbers:
const player = {
// ... other properties ...
velocityY: 0,
gravity: 0.8,
// ... other properties ...
};
Play around with these numbers until the jump feels good to you. It's like adjusting the bounce in a bouncy ball - you want it to feel just right.
Remember, jumping in games is all about timing. It's like jumping to catch a frisbee - if you jump at the wrong time, you'll miss it. In our game, players need to time their jumps to avoid obstacles. It's what makes the game fun and challenging!
A runner game isn't much fun without things to jump over, right? Let's add some obstacles!
First, we'll make a list to hold our obstacles:
const obstacles = [];
function createObstacle() {
const obstacle = {
x: canvas.width,
y: canvas.height - 60,
width: 50,
height: 50,
speed: 6 + score * 0.05 // We'll add score later
};
obstacles.push(obstacle);
}
This function makes a new obstacle and adds it to our list.
Now let's draw all our obstacles:
function drawObstacles() {
ctx.fillStyle = '#000000'; // Black color
obstacles.forEach(obstacle => {
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
});
}
We need to make the obstacles move towards the player:
function updateObstacles() {
obstacles.forEach((obstacle, index) => {
obstacle.x -= obstacle.speed;
// Remove obstacles that have gone off screen
if (obstacle.x + obstacle.width < 0) {
obstacles.splice(index, 1);
score += 1; // We'll add score later
}
});
}
Let's add new obstacles every so often:
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updatePlayer();
updateObstacles();
drawPlayer();
drawObstacles();
// Maybe add a new obstacle
if (Math.random() < 0.01) { // 1% chance each frame
createObstacle();
}
requestAnimationFrame(gameLoop);
}
Now you should see obstacles coming at your player! But wait, we can run right through them. That's not right...
We need to know when our player hits an obstacle. This is called collision detection.
Here's a function to check if the player has hit an obstacle:
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
) {
gameOver();
}
});
}
Let's make a game over function:
function gameOver() {
alert(`Game Over! You scored ${score} points!`);
// Reset the game
obstacles.length = 0;
score = 0;
player.y = canvas.height - player.height - 10;
player.velocityY = 0;
}
This shows your score and resets the game.
Don't forget to add the collision check to your game loop:
function gameLoop() {
// ... other code ...
checkCollision();
// ... other code ...
}
Now your game has some real challenge! It's like dodging traffic in a busy city - one wrong move and it's game over!
Our game works, but we can make it run even better. Let's make sure it runs smoothly on different devices.
We want our game to run at a steady speed. Here's how we can do that:
let lastTime = 0;
const fps = 60;
const fpsInterval = 1000 / fps;
function gameLoop(timestamp) {
if (!lastTime) lastTime = timestamp;
const elapsed = timestamp - lastTime;
if (elapsed > fpsInterval) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updatePlayer();
updateObstacles();
drawPlayer();
drawObstacles();
checkCollision();
if (Math.random() < 0.01) {
createObstacle();
}
lastTime = timestamp;
}
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
This makes sure our game updates 60 times per second, no matter how fast the computer is.
To make things even smoother, we can use something called delta time:
let lastTime = 0;
function gameLoop(timestamp) {
if (!lastTime) lastTime = timestamp;
const deltaTime = timestamp - lastTime;
ctx.clearRect(0, 0, canvas.width, canvas.height);
updatePlayer(deltaTime);
updateObstacles(deltaTime);
drawPlayer();
drawObstacles();
checkCollision();
if (Math.random() < 0.01) {
createObstacle();
}
lastTime = timestamp;
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
Now update your player and obstacle functions to use deltaTime:
function updatePlayer(deltaTime) {
player.y += player.velocityY * deltaTime * 0.016;
player.velocityY += player.gravity * deltaTime * 0.016;
if (player.y + player.height >= canvas.height - 10) {
player.y = canvas.height - player.height - 10;
player.isJumping = false;
player.velocityY = 0;
}
}
function updateObstacles(deltaTime) {
obstacles.forEach((obstacle, index) => {
obstacle.x -= obstacle.speed * deltaTime * 0.016;
if (obstacle.x + obstacle.width < 0) {
obstacles.splice(index, 1);
score += 1;
}
});
}
This makes sure the game runs at the same speed on all devices, even if they update at different rates.
Think of it like conducting an orchestra. You're making sure all the parts of your game play together nicely, creating a smooth and enjoyable experience for the player.
Let's add a score to our game and make it get harder as you play longer.
First, let's add a place to show the score:
<canvas id="gameCanvas" width="800" height="400"></canvas>
<canvas id="scoreCanvas" width="800" height="50"></canvas>
Now let's draw the score:
const scoreCanvas = document.getElementById('scoreCanvas');
const scoreCtx = scoreCanvas.getContext('2d');
let score = 0;
function drawScore() {
scoreCtx.clearRect(0, 0, scoreCanvas.width, scoreCanvas.height);
scoreCtx.fillStyle = '#000000';
scoreCtx.font = '24px Arial';
scoreCtx.fillText(`Score: ${score}`, 10, 30);
}
function gameLoop(timestamp) {
// ... existing code ...
drawScore();
// ... existing code ...
}
Let's make the obstacles move faster as the score goes up:
function createObstacle() {
const obstacle = {
x: canvas.width,
y: canvas.height - 60,
width: 50,
height: 50,
speed: 6 + score * 0.05
};
obstacles.push(obstacle);
}
Now the game gets harder the longer you play. It's like leveling up in a video game - each level is a bit harder than the last!
To make sure your game runs well on different devices, we need to make it efficient. Here are some tips:
Every time you draw something, it takes a little bit of time. Try to draw fewer things:
Making new objects all the time can slow down your game. Instead, try reusing objects:
const obstaclePool = [];
function createObstacle() {
let obstacle;
if (obstaclePool.length > 0) {
obstacle = obstaclePool.pop();
obstacle.x = canvas.width;
obstacle.speed = 6 + score * 0.05;
} else {
obstacle = {
x: canvas.width,
y: canvas.height - 60,
width: 50,
height: 50,
speed: 6 + score * 0.05
};
}
obstacles.push(obstacle);
}
function updateObstacles(deltaTime) {
obstacles.forEach((obstacle, index) => {
obstacle.x -= obstacle.speed * deltaTime * 0.016;
if (obstacle.x + obstacle.width < 0) {
obstaclePool.push(obstacle);
obstacles.splice(index, 1);
score += 1;
}
});
}
This reuses obstacles instead of making new ones all the time.
A big canvas takes more power to draw on. Keep it as small as you can while still looking good.
Modern web browsers can use the computer's graphics card to draw things faster. Your game should do this automatically, but avoid doing too much math in JavaScript if you can.
Remember, a fast game is like running without a heavy backpack. It's much easier and more fun!
A good game isn't just about the rules - it's about how it feels to play. Let's make our game feel great!
Make sure the controls respond right away. We've already done this with our jump:
document.addEventListener('keydown', function(event) {
if (event.code === 'Space' && !player.isJumping) {
player.velocityY = -20;
player.isJumping = true;
}
});
Let's add some visual effects to show what's going on. For example, we could change the player's color when they jump:
function drawPlayer() {
ctx.fillStyle = player.isJumping ? '#FFA500' : '#FF0000';
ctx.fillRect(player.x, player.y, player.width, player.height);
}
Sound effects can make your game feel more alive. Let's add a jump sound:
const jumpSound = new Audio('jump.mp3');
document.addEventListener('keydown', function(event) {
if (event.code === 'Space' && !player.isJumping) {
player.velocityY = -20;
player.isJumping = true;
jumpSound.play();
}
});
Don't forget to add a 'jump.mp3' file to your project!
These little touches are like adding spices to food - they make the whole experience better!
Implementing simple visual and audio effects can significantly improve the player's engagement and enjoyment.
You've made an awesome game - now let's share it with the world!
There are lots of places you can put your game online:
Here's how to use GitHub Pages:
Once your game is online, tell people about it:
Ask people to play your game and tell you what they think:
Sharing your game is like showing off a cool trick you learned - it's fun to see people enjoy something you made!
Wow, you've done it! You've made an endless runner game from scratch. That's pretty awesome!
Making games is more than just writing code - it's about creating fun experiences for people to enjoy. You've learned about game loops, player controls, obstacles, collision detection, and even how to make your game run smoothly on different devices.
Remember, this is just the beginning. You can keep adding to your game - maybe different types of obstacles, power-ups, or even different characters to play as. The sky's the limit!
Game development is a journey of learning and creativity. Start simple, try new things, and listen to what players tell you about your game. As you keep making games, you'll get better and better.
So, what are you waiting for? Your game is out there waiting to be played. Share it with your friends, family, or the whole world! And most importantly, keep creating and having fun!
Happy coding, and may your endless runner game be as fun and exciting as the games that inspired you to make it!
Continue enhancing your game by adding new features and improving existing ones to keep players engaged.
You can try this feature yourself at img2html.com .