Copyright GENIUS
The aim of this game is to use the arrow keys to direct the monster to the bullseye.
This game shows:
Play game
/* Author: Derek O Reilly, Dundalk Institute of Technology, Ireland. */ /* There should always be a javaScript file with the same name as the html file. */ /* This file always holds the playGame function(). */ /* It also holds game specific code, which will be different for each game */ /******************** Declare game specific global data and functions *****************/ /* images must be declared as global, so that they will load before the game starts */ let obstaclesImage = new Image(); obstaclesImage.src = "images/obstacles.png"; let monsterImage = new Image(); monsterImage.src = "images/monster.png"; let bullseyeImage = new Image(); bullseyeImage.src = "images/bullseye.png"; let starsImage = new Image(); starsImage.src = "images/stars.png"; /* Direction that the skeleton is walking */ /* Note that this matches the row in the gameObject image for the given direction */ const UP = 0; const LEFT = 1; const DOWN = 2; const RIGHT = 3; const STOPPED = 4; const START = 5; /* The various gameObjects */ /* These are the positions that each gameObject is held in the gameObjects[] array */ const BACKGROUND = 0; const OBSTACLES = 1; const BULLSEYE = 2; const MONSTER = 3; const WIN_MESSAGE = 4; /******************* END OF Declare game specific data and functions *****************/ /* Always have a playGame() function */ /* However, the content of this function will be different for each game */ function playGame() { /* We need to initialise the game objects outside of the Game class */ /* This function does this initialisation. */ /* This function will: */ /* 1. create the various game game gameObjects */ /* 2. store the game gameObjects in an array */ /* 3. create a new Game to display the game gameObjects */ /* 4. start the Game */ /* Create the various gameObjects for this game. */ /* This is game specific code. It will be different for each game, as each game will have it own gameObjects */ gameObjects[BACKGROUND] = new StaticImage(starsImage, 0, 0, canvas.width, canvas.height); gameObjects[OBSTACLES] = new StaticImage(obstaclesImage, 0, 0, canvas.width, canvas.height); gameObjects[BULLSEYE] = new Bullseye(bullseyeImage, canvas.width - 50, canvas.height - 50, 50, 50); gameObjects[MONSTER] = new Monster(monsterImage); /* END OF game specific code. */ /* Always create a game that uses the gameObject array */ let game = new MonsterCanvasGame(obstaclesImage); /* Always play the game */ game.start(); /* If they are needed, then include any game-specific mouse and keyboard listners */ document.addEventListener('keydown', function (e) { if (e.keyCode === 37) // left { gameObjects[MONSTER].setDirection(LEFT); } else if (e.keyCode === 38) // up { gameObjects[MONSTER].setDirection(UP); } else if (e.keyCode === 39) // right { gameObjects[MONSTER].setDirection(RIGHT); } else if (e.keyCode === 40) // down { gameObjects[MONSTER].setDirection(DOWN); } else if (e.keyCode === 32) // space { gameObjects[MONSTER].setDirection(START); } }); document.addEventListener('keyup', function (e) { gameObjects[MONSTER].setDirection(STOPPED); }); }
The game displays a monster, a background, a bullseye and obstacles.
gameObjects[BACKGROUND] = new StaticImage(starsImage, 0, 0, canvas.width, canvas.height); gameObjects[OBSTACLES] = new StaticImage(obstaclesImage, 0, 0, canvas.width, canvas.height); gameObjects[BULLSEYE] = new Bullseye(bullseyeImage, canvas.width - 50, canvas.height - 50, 50, 50); gameObjects[MONSTER] = new Monster(monsterImage);
The arrow keys are used to control the direction that the monster moves.
document.addEventListener('keydown', function (e) { if (e.keyCode === 37) // left { gameObjects[MONSTER].setDirection(LEFT); } else if (e.keyCode === 38) // up { gameObjects[MONSTER].setDirection(UP); } else if (e.keyCode === 39) // right { gameObjects[MONSTER].setDirection(RIGHT); } else if (e.keyCode === 40) // down { gameObjects[MONSTER].setDirection(DOWN); } else if (e.keyCode === 32) // space { gameObjects[MONSTER].setDirection(START); } });
The monster stops moving when the arrow keys are released.
document.addEventListener('keyup', function (e) { gameObjects[MONSTER].setDirection(STOPPED); });
/* Author: Derek O Reilly, Dundalk Institute of Technology, Ireland. */ /* A CanvasGame that implements collision detection. */ /* The game allows the user to walk a skeleton around a maze. */ /* If the skeleton is guided to the maze exit, then a win message appears. */ class MonsterCanvasGame extends CanvasGame { constructor(obstaclesImage) { super(); /* this.monsterObstalesCtx will be used for collision detection */ let monsterObstalesOffscreenCanvas = document.createElement('canvas'); monsterObstalesOffscreenCanvas.width = canvas.width; monsterObstalesOffscreenCanvas.height = canvas.height; this.monsterObstalesCtx = monsterObstalesOffscreenCanvas.getContext('2d'); this.monsterObstalesCtx.drawImage(obstaclesImage, 0, 0, canvas.width, canvas.height); this.screenShakeInterval = null; this.screenIsRotatingToTheLeft = false; this.NUMBER_OF_SCREEN_SHAKES_INTERATIONS = 10; this.numberOfScreenShakes = 0; } collisionDetection() { if (!this.monsterObstalesCtx) { return; } let imageData = this.monsterObstalesCtx.getImageData(gameObjects[MONSTER].getX(), gameObjects[MONSTER].getY(), 1, 1); let dataTop = imageData.data; imageData = this.monsterObstalesCtx.getImageData(gameObjects[MONSTER].getX() + gameObjects[MONSTER].getWidth() * 0.8, gameObjects[MONSTER].getY(), 1, 1); let dataRight = imageData.data; imageData = this.monsterObstalesCtx.getImageData(gameObjects[MONSTER].getX(), gameObjects[MONSTER].getY() + gameObjects[MONSTER].getHeight() * 0.8, 1, 1); let dataBottom = imageData.data; imageData = this.monsterObstalesCtx.getImageData(gameObjects[MONSTER].getX() + gameObjects[MONSTER].getWidth() * 0.8, gameObjects[MONSTER].getY() + gameObjects[MONSTER].getHeight() * 0.8, 1, 1); let dataLeft = imageData.data; if ((dataTop[3] !== 0) || (dataRight[3] !== 0) || (dataBottom[3] !== 0) || (dataLeft[3] !== 0)) { if (gameObjects[MONSTER].getDirection() === UP) { gameObjects[MONSTER].setDirection(DOWN); gameObjects[MONSTER].setY(gameObjects[MONSTER].getY() + 5); } else if (gameObjects[MONSTER].getDirection() === DOWN) { gameObjects[MONSTER].setDirection(UP); gameObjects[MONSTER].setY(gameObjects[MONSTER].getY() - 5); } else if (gameObjects[MONSTER].getDirection() === LEFT) { gameObjects[MONSTER].setDirection(RIGHT); } else if (gameObjects[MONSTER].getDirection() === RIGHT) { gameObjects[MONSTER].setDirection(LEFT); } if (this.screenShakeInterval === null) { this.screenShakeInterval = setInterval(this.shakeScreen.bind(this), 10); } } else if (gameObjects[BULLSEYE].pointIsInsideBullseyeRectangle(gameObjects[MONSTER].getX() + gameObjects[MONSTER].getWidth() * 0.5, gameObjects[MONSTER].getY() + gameObjects[MONSTER].getHeight() * 0.5)) { /* Player has won */ for (let i = 0; i < gameObjects.length; i++) /* stop all gameObjects from animating */ { gameObjects[i].stop(); } gameObjects[WIN_MESSAGE] = new StaticText("Well Done!", 20, 280, "Times Roman", 100, "red"); gameObjects[WIN_MESSAGE].start(); /* render win message */ } } render() { ctx.save(); if (this.screenShakeInterval !== null) // hit an obstacle { if (this.screenIsRotatingToTheLeft) { ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate(Math.radians(1)); ctx.translate(-canvas.width / 2, -canvas.height / 2); } else { ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate(Math.radians(-1)); ctx.translate(-canvas.width / 2, -canvas.height / 2); } } super.render(); ctx.restore(); } shakeScreen() { if (this.screenIsRotatingToTheLeft) { this.screenIsRotatingToTheLeft = false; } else // screen is rotating to the right { this.screenIsRotatingToTheLeft = true; } this.numberOfScreenShakes++; if (this.numberOfScreenShakes >= this.NUMBER_OF_SCREEN_SHAKES_INTERATIONS) { this.numberOfScreenShakes = 0; clearInterval(this.screenShakeInterval); this.screenShakeInterval = null; } } }
Whenever the skeleton hits the maze grid, if changes direction.
/* Player has won */ for (let i = 0; i < gameObjects.length; i++) /* stop all gameObjects from animating */ { gameObjects[i].stop(); } gameObjects[WIN_MESSAGE] = new StaticText("Well Done!", 20, 280, "Times Roman", 100, "red"); gameObjects[WIN_MESSAGE].start(); /* render win message */
/* Author: Derek O Reilly, Dundalk Institute of Technology, Ireland. */ class Monster extends GameObject { /* Each gameObject MUST have a constructor() and a render() method. */ /* If the object animates, then it must also have an updateState() method. */ constructor(monsterImage) { super(5); /* as this class extends from GameObject, you must always call super() */ /* These variables depend on the object */ this.startX = 20; this.startY = 20; this.x = this.startX; this.y = this.startY; this.monsterImage = monsterImage; this.width = 40; this.height = 40; this.setDirection(STOPPED); } updateState() { if (this.direction === UP) { this.y--; } else if (this.direction === LEFT) { this.x--; } else if (this.direction === DOWN) { this.y++; } else if (this.direction === RIGHT) { this.x++; } } render() { ctx.drawImage(this.monsterImage, this.x, this.y, this.width, this.height); } setDirection(newDirection) { if (this.direction !== START) { this.direction = newDirection; } else // spacebar hit, so set monster back to start { this.x = this.startX; this.y = this.startY; this.direction = STOPPED; } } getDirection() { return(this.direction); } getX() { return this.x; } getY() { return this.y; } setX(newX) { this.x = newX; } setY(newY) { this.y = newY; } getWidth() { return this.width; } getHeight() { return this.height; } }
/* Author: Derek O Reilly, Dundalk Institute of Technology, Ireland. */ class Bullseye extends StaticImage { /* Each gameObject MUST have a constructor() and a render() method. */ /* If the object animates, then it must also have an updateState() method. */ constructor(image, x, y, width, height) { super(image, x, y, width, height); /* as this class extends from GameObject, you must always call super() */ /* These variables depend on the object */ this.image = image; this.width = width; this.height = height; this.x = x; this.y = y; this.bullseyeSize = 10; // the granularity of the bullseye target. } getX() { return this.x; } getY() { return this.y; } getWidth() { return this.width; } getHeight() { return this.height; } pointIsInsideBullseyeRectangle(pointX, pointY) { /* The bullseye is set to have a width and height of bullseySize */ /* The bulleseye is set from the centre of the bullseye image */ let bullseyeX = this.x + ((this.width - this.bullseyeSize) / 2); let bullseyeY = this.y + ((this.height - this.bullseyeSize) / 2); if ((pointX > bullseyeX) && (pointY > bullseyeY)) { if (pointX > bullseyeX) { if ((pointX - bullseyeX) > this.bullseyeSize) { return false; // to the right of this gameObject } } if (pointY > bullseyeY) { if ((pointY - bullseyeY) > this.bullseyeSize) { return false; // below this gameObject } } } else // above or to the left of this gameObject { return false; } return true; // inside this gameObject } }