Sitemap / Advertise

Introduction

This particular game is my first game and entry in the JavaScript Game series. You need to escape every moving obstacle while moving the box to survive in this game.


Tags

Share

JavaScript Game: Escaping Box

Advertisement:


read_later

Read Later



read_later

Read Later

Introduction

This particular game is my first game and entry in the JavaScript Game series. You need to escape every moving obstacle while moving the box to survive in this game.

Tags

Share





Advertisement

Advertisement





Introduction

I am new to developing and designing a game using JavaScript. In this project series named JavaScript Game, I will share games I develop from basic to advanced. This particular game is my first game and entry in the JavaScript Game series. You need to escape every moving obstacle while moving the box to survive in this game.

Click 'Preview' to try.

For more information about the code files, please visit Source Code section below.

Step 1: Features

- Press Enter to start the game.

project-image
Figure - 32.1

- Move the box using arrow keys

project-image
Figure - 32.2

- Pause and resume the game using the escape key.

project-image
Figure - 32.3

- When you get caught by any pre-defined obstacles, game over. Press Enter to restart.

project-image
Figure - 32.4

Step 2: Index

- Import the Game class.

- Get the canvas element.

- Create the 2d context to draw.

- Define the game width and the game height.

- Define the game object.

- Create the loop function to update and draw the game using requestAnimationFrame(loop);.

project-image
Figure - 32.5

Step 3: Game

- Import Box, InputHandler, Obstacles, and Collision classes.

- Define game states.

- Create game objects. And, attach the class itself to the created game objects.

- Update each game object if the game state is running.

- Proceed after drawing each object unless there is not a change in the game state.

- Define pause() and gameOver() functions.

project-image
Figure - 32.6


project-image
Figure - 32.7

Step 4: Box

- Get the game width and the game height from the Game class.

- Define the size, position, speed, and acceleration of the box.

- Define moveRight(), moveLeft(), moveBottom(), moveUp(), and stop() functions.

- Draw the background of the canvas and the box.

- Update the position of the box if it did not hit the border.

project-image
Figure - 32.8


project-image
Figure - 32.9

Step 5: Obstacles

- Get the game width and the game height from the Game class.

- Define obstacles' properties - id, position, speed, size.

- Define obstacle objects for each obstacle to draw them.

- Draw each object.

- Create the move(object) function to animate each obstacle object.

- Update each obstacle object executing the move(object) function.

project-image
Figure - 32.10

Step 6: Collision

- Get objects and variables from the Game class.

- Create the detect_Collision(box, object) function to detect any collision between the box and the obstacles to activate the gameOver() function.

- Update the detect_Collision(box, object) function for each obstacle object.

project-image
Figure - 32.11

Step 7: InputHandler

- Get objects and variables from the Game class.

- If the right arrow is pressed, execute the moveRight() function.

- If the up arrow is pressed, execute the moveUp() function.

- If the left arrow is pressed, execute the moveLeft() function.

- If the down arrow is pressed, execute the moveBottom() function.

- To avoid the page navigation while pressing arrows, use event.preventDefault();

- If the escape key is pressed, pause or resume the game.

- If the enter key is pressed, start the game in the INITIAL state.

- If the enter key is pressed, restart the game in the GAMEOVER state.

- On keyup, stop the box executing the stop() function.

project-image
Figure - 32.12


project-image
Figure - 32.13

Source Code

Please sign in to download source code files and the game, including index.css and index.html, in a zipped folder and try it on your computer.

Zip Folder

Download


Index

Download



import Game from './game.js';

let canvas = document.getElementById("game");
let ctx = canvas.getContext("2d");

const GAME_WIDTH = 300;
const GAME_HEIGHT = 600;

let game = new Game(GAME_WIDTH, GAME_HEIGHT);

function loop(timestamp){
	// Define if needed.
	let deltaTime;
	
	ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
	
    game.update(deltaTime);
	game.draw(ctx);
	
	requestAnimationFrame(loop);
}

requestAnimationFrame(loop);


Game

Download



import Box from './box.js';
import InputHandler from './keyInput.js';
import Obstacles from './obstacles.js';
import Collision from './collision.js';

export default class Game{
	constructor(gameWidth, gameHeight){
		this.gameWidth = gameWidth;
		this.gameHeight = gameHeight;
		
		this.STATE = {
			PAUSED: 0,
			RUNNING: 1,
			INITIAL: 2,
			GAMEOVER: 3
		};
		
		this.gameState = this.STATE.INITIAL;
		
	    this.box = new Box(this);
        this.obstacles = new Obstacles(this);
		this.collision = new Collision(this);
		new InputHandler(this);
		this.objects=[];

	}
	
	start(){
		this.gameState = this.STATE.RUNNING;
		
		this.objects = [this.box, this.obstacles, this.collision];
	}
	
	update(deltaTime){
		if(this.gameState == this.STATE.PAUSED || this.gameState == this.STATE.INITIAL || this.gameState == this.STATE.GAMEOVER) return;
		
	    this.objects.forEach((object) => object.update(deltaTime));
	}
	
	draw(ctx){
		this.objects.forEach((object) => object.draw(ctx));
		
		if(this.gameState == this.STATE.PAUSED){
			ctx.fillStyle = "rgba(78, 88, 81, 0.6)";
			ctx.fillRect(0, 0, this.gameWidth, this.gameHeight);
			ctx.font = "30px Times";
			ctx.fillStyle = "white";
			ctx.textAlign = "center";
			ctx.fillText("You are on a break :)", this.gameWidth / 2, this.gameHeight / 3);
		}
		
		if(this.gameState == this.STATE.INITIAL){
			ctx.fillStyle = "#1F2020";
			ctx.fillRect(0, 0, this.gameWidth, this.gameHeight);
			ctx.font = "30px Times";
			ctx.fillStyle = "white";
			ctx.textAlign = "center";
			ctx.fillText("Press Enter to Start", this.gameWidth / 2, this.gameHeight / 2);
		}
		
		if(this.gameState == this.STATE.GAMEOVER){
			ctx.fillStyle = "#1F2020";
			ctx.fillRect(0, 0, this.gameWidth, this.gameHeight);
			ctx.font = "30px Times";
			ctx.fillStyle = "white";
			ctx.textAlign = "center";
			ctx.fillText("GAME OVER !!!", this.gameWidth / 2, this.gameHeight / 2);
		}
	}
	
	pause(){
		if(this.gameState == this.STATE.PAUSED){
			this.gameState = this.STATE.RUNNING
		}else{
			this.gameState = this.STATE.PAUSED;
		}
	}
	
	gameOver(){
		this.gameState = this.STATE.GAMEOVER;
	}
}




export default class Box{
	constructor(game){
		this.gameWidth = game.gameWidth;
		this.gameHeight = game.gameHeight;
		this.width = 25;
		this.height = 25;
		
		this.position = {
			x: this.gameWidth / 2 - this.width / 2,
			y: this.gameHeight / 2 - this.height / 2
		};
		
		this.accelerate = 10;
		
		this.speed = {
			x: 0,
			y: 0
		};
	}
	
	moveRight(){
		this.speed.x = -this.accelerate;
	}
	
	moveLeft(){
		this.speed.x = this.accelerate;
	}
	
	moveUp(){
		this.speed.y = -this.accelerate;
	}
	
	moveBottom(){
		this.speed.y = this.accelerate;
	}
	
	stop(){
		this.speed.x = 0;
		this.speed.y = 0;
	}
	
	draw(ctx){
		ctx.drawImage(document.getElementById("background"), 0, 0, this.gameWidth, this.gameHeight);
		ctx.fillStyle = "red";
		ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
	}
	
	update(deltaTime){
		this.position.x += this.speed.x;
		this.position.y += this.speed.y;
		
		if(this.position.x < 0) this.position.x = 0;
		if(this.position.x + this.width > this.gameWidth) this.position.x = this.gameWidth - this.width;
		if(this.position.y < 0) this.position.y = 0;
		if(this.position.y + this.height > this.gameHeight) this.position.y = this.gameHeight - this.height;
		
	}
}


Obstacles

Download



export default class Obstacles{
	constructor(game){
		this.gameWidth = game.gameWidth;
		this.gameHeight = game.gameHeight;
		
		this.obstacles = {
			bomb: {id: document.getElementById("obs_bomb"), position:{x: 15, y: 15}, speed: {x: 1, y: 1}, size:{x: 30, y: 30}},
			bomb_2: {id: document.getElementById("obs_bomb"), position:{x: 50, y: 30}, speed: {x: 2, y: 2}, size:{x: 30, y: 30}},
			bomb_3: {id: document.getElementById("obs_bomb"), position:{x: 100, y: 45}, speed: {x: 3, y: 3}, size:{x: 30, y: 30}},
			bomb_4: {id: document.getElementById("obs_bomb"), position:{x: 150, y: 60}, speed: {x: 4, y: 4}, size:{x: 30, y: 30}},
			bomb_5: {id: document.getElementById("obs_bomb"), position:{x: 200, y: 75}, speed: {x: 5, y: 5}, size:{x: 30, y: 30}},
			danger: {id: document.getElementById("obs_danger"), position:{x: 200, y: 475}, speed: {x: 5, y: 5}, size:{x: 40, y: 40}},
			danger_2: {id: document.getElementById("obs_danger"), position:{x: 150, y: 460}, speed: {x: 4, y: 4}, size:{x: 40, y: 40}},
			danger_3: {id: document.getElementById("obs_danger"), position:{x: 100, y: 445}, speed: {x: 3, y: 3}, size:{x: 40, y: 40}},
			danger_4: {id: document.getElementById("obs_danger"), position:{x: 50, y: 430}, speed: {x: 2, y: 2}, size:{x: 40, y: 40}},
			danger_5: {id: document.getElementById("obs_danger"), position:{x: 15, y: 415}, speed: {x: 1, y: 1}, size:{x: 40, y: 40}}
		};
		
		this.obs_objects = [this.obstacles.bomb, this.obstacles.bomb_2, this.obstacles.bomb_3, this.obstacles.bomb_4, this.obstacles.bomb_5, this.obstacles.danger, this.obstacles.danger_2, this.obstacles.danger_3, this.obstacles.danger_4, this.obstacles.danger_5];
		
	}
	
	draw(ctx){
		this.obs_objects.forEach((object) => ctx.drawImage(object.id, object.position.x, object.position.y, object.size.x, object.size.y));
	}
	
	move(object){
		object.position.x += object.speed.x;
		object.position.y += object.speed.y;
		
		if(object.position.x + object.size.x > this.gameWidth || object.position.x < 0) object.speed.x = -object.speed.x; 
		if(object.position.y + object.size.y > this.gameHeight || object.position.y < 0) object.speed.y = -object.speed.y; 
	}
	
	update(deltaTime){
		this.obs_objects.forEach((object) => this.move(object));
	}
}


Collision

Download



export default class Collision{
	constructor(game){
		// GET ALL INFO FROM THE GAME CLASS
		this.game = game;
		
		this.gameWidth = game.gameWidth;
		this.gameHeight = game.gameHeight;
		
		
	}
	
	detect_Collision(box, object){
		let bottomOfObstacle = object.position.y + object.size.y;
        let leftOfObstacle = object.position.x;
        let rightOfObstacle = object.position.x + object.size.x;
        let topOfObstacle = object.position.y;
        
        let bottomOfBox = box.position.y + box.height;
        let leftOfBox = box.position.x;		
        let rightOfBox = box.position.x + box.width;		
        let topOfBox = box.position.y;
        
        if(leftOfBox < rightOfObstacle && rightOfBox > leftOfObstacle && topOfBox < bottomOfObstacle && bottomOfBox > topOfObstacle) this.game.gameOver();		
	}
	
	draw(ctx){
		
	}
	
	update(deltaTime){
		this.game.obstacles.obs_objects.forEach((object) => this.detect_Collision(this.game.box, object));
	}
}


InputHandler

Download



export default class InputHandler{
	constructor(game){
		// GET ALL INFO FROM THE GAME CLASS
		this.game = game;
		
		document.addEventListener("keydown", (event) => {
			let key = event.keyCode || event.which;
			switch(key){
				case 37:
				this.game.box.moveRight();
				break;
				case 38:
				event.preventDefault();
				this.game.box.moveUp();
				break;
				case 39:
				this.game.box.moveLeft();
				break;
				case 40:
				event.preventDefault();
				this.game.box.moveBottom();
				break;
				case 27:
				if(this.game.gameState == this.game.STATE.GAMEOVER || this.game.gameState == this.game.STATE.INITIAL) return;
				this.game.pause();
				break;
				case 13:
				if(this.game.gameState == this.game.STATE.PAUSED) return;
				if(this.game.gameState == this.game.STATE.GAMEOVER) location.reload();
				this.game.start();
				break;

			}
		});
		
		document.addEventListener("keyup", (event) => {
			let key = event.keyCode || event.which;
			switch(key){
				case 37:
				if(this.game.box.speed.x < 0) this.game.box.stop();
				break;
				case 38:
				if(this.game.box.speed.y < 0) this.game.box.stop();
				break;
				case 39:
				if(this.game.box.speed.x > 0) this.game.box.stop();
				break;
				case 40:
				if(this.game.box.speed.y > 0) this.game.box.stop();
				break;

			}
		});
	}
}