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
}
}