2021-03-18 10:29:12 +01:00
|
|
|
import {Game} from "./Game.js";
|
|
|
|
|
|
|
|
export class Tile {
|
|
|
|
/**
|
|
|
|
* A tile of the game grid
|
|
|
|
* @param {int} x
|
|
|
|
* @param {int} y
|
|
|
|
* @param {tiles} type
|
|
|
|
* @param {Game} game
|
|
|
|
*/
|
|
|
|
constructor(x, y, type = tiles.EMPTY, game) {
|
|
|
|
if (typeof x === "number" && x >= 0 && x % 1 === 0)
|
|
|
|
this.x = x;
|
|
|
|
else
|
|
|
|
throw new InvalidTileOption("x");
|
|
|
|
|
|
|
|
if (typeof y === "number" && y >= 0 && y % 1 === 0)
|
|
|
|
this.y = y;
|
|
|
|
else
|
|
|
|
throw new InvalidTileOption("y");
|
|
|
|
|
|
|
|
if (type && Object.values(tiles).find(t => t === type))
|
|
|
|
this.type = type;
|
|
|
|
else
|
|
|
|
throw new InvalidTileOption("type");
|
|
|
|
|
|
|
|
if (game && game instanceof Game)
|
|
|
|
this.game = game;
|
|
|
|
else
|
|
|
|
throw new InvalidTileOption("game");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Draw the tile on the grid
|
|
|
|
*/
|
|
|
|
draw() {
|
|
|
|
const canvasPos = this.getCanvasPos(), size = this.getSize();
|
|
|
|
|
|
|
|
this.game.ctx.beginPath();
|
|
|
|
|
|
|
|
this.game.ctx.globalCompositeOperation = "destination-out";
|
|
|
|
this.game.ctx.fillRect(...canvasPos, ...size);
|
|
|
|
this.game.ctx.globalCompositeOperation = "source-over";
|
|
|
|
|
|
|
|
switch (this.type) {
|
|
|
|
case tiles.EMPTY:
|
2021-03-23 09:23:37 +01:00
|
|
|
this.game.ctx.strokeStyle = "#999999";
|
2021-03-18 10:29:12 +01:00
|
|
|
this.game.ctx.rect(...canvasPos, ...size);
|
|
|
|
break;
|
|
|
|
case tiles.APPLE:
|
2021-03-27 11:00:39 +01:00
|
|
|
let pxsize = Math.round(size[0]/12);
|
|
|
|
if (!pxsize) {
|
|
|
|
this.game.ctx.fillStyle = "#ff0000";
|
|
|
|
this.game.ctx.fillRect(...canvasPos, ...size);
|
|
|
|
} else {
|
|
|
|
let width = canvasPos[0];
|
|
|
|
let height = canvasPos[1];
|
|
|
|
|
|
|
|
this.game.ctx.fillStyle = "#00ffff";
|
|
|
|
this.game.ctx.fillRect(width+pxsize, height+pxsize, 10*pxsize, 10*pxsize);
|
|
|
|
|
|
|
|
this.game.ctx.fillStyle = "#000000";
|
|
|
|
|
|
|
|
this.game.ctx.fillRect(width+4*pxsize, height, pxsize*4, pxsize);
|
|
|
|
this.game.ctx.fillRect(width+4*pxsize, height+11*pxsize, pxsize*4, pxsize);
|
|
|
|
|
|
|
|
for (const i of [2,5,8])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+pxsize, pxsize*2, pxsize);
|
|
|
|
|
|
|
|
for (const i of [1,4,7,10])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+2*pxsize, pxsize, pxsize*2);
|
|
|
|
|
|
|
|
this.game.ctx.fillRect(width, height+4*pxsize, pxsize, pxsize*4);
|
|
|
|
this.game.ctx.fillRect(width+11*pxsize, height+4*pxsize, pxsize, pxsize*4);
|
|
|
|
|
|
|
|
for (const i of [1,5,6,10])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+8*pxsize, pxsize, pxsize*2);
|
|
|
|
|
|
|
|
for (const i of [2,5,8])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+10*pxsize, pxsize*2, pxsize);
|
|
|
|
|
|
|
|
for (const i of [3,8,2,9])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+4*pxsize, pxsize, pxsize);
|
|
|
|
|
|
|
|
for (const i of [1,3,8,10])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+6*pxsize, pxsize, pxsize);
|
|
|
|
|
|
|
|
for (const i of [4,7])
|
|
|
|
this.game.ctx.fillRect(width+i*pxsize, height+7*pxsize, pxsize, pxsize);
|
|
|
|
|
|
|
|
this.game.ctx.globalCompositeOperation = "destination-out";
|
|
|
|
this.game.ctx.fillRect(width+1*pxsize, height+1*pxsize, pxsize, pxsize);
|
|
|
|
this.game.ctx.fillRect(width+10*pxsize, height+1*pxsize, pxsize, pxsize);
|
|
|
|
this.game.ctx.fillRect(width+1*pxsize, height+10*pxsize, pxsize, pxsize);
|
|
|
|
this.game.ctx.fillRect(width+10*pxsize, height+10*pxsize, pxsize, pxsize);
|
|
|
|
this.game.ctx.globalCompositeOperation = "source-over";
|
|
|
|
}
|
2021-03-18 10:29:12 +01:00
|
|
|
break;
|
|
|
|
case tiles.SNAKE:
|
|
|
|
this.game.ctx.fillStyle = "#00ff5f";
|
|
|
|
this.game.ctx.fillRect(...canvasPos, ...size);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.game.ctx.stroke();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the tile position on the canvas
|
|
|
|
* @returns {[int, int]}
|
|
|
|
*/
|
|
|
|
getCanvasPos() {
|
|
|
|
return [this.getSize()[0]*this.x, this.getSize()[1]*this.y]
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the tile size on the canvas
|
|
|
|
* @returns {[int, int]}
|
|
|
|
*/
|
|
|
|
getSize() {
|
|
|
|
const s = Math.min(Math.round(this.game.ctx.canvas.width/this.game.size[0]), Math.round(this.game.ctx.canvas.height/this.game.size[1]));
|
|
|
|
return [s, s]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class InvalidTileOption extends Error {
|
|
|
|
/**
|
|
|
|
* @param {string} name
|
|
|
|
*/
|
|
|
|
constructor(name) {
|
|
|
|
super(`Invalid Tile option: ${name}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export const tiles = {
|
|
|
|
EMPTY: "empty",
|
|
|
|
APPLE: "apple",
|
|
|
|
SNAKE: "snake"
|
|
|
|
};
|