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: this.game.ctx.strokeStyle = "#999999"; this.game.ctx.rect(...canvasPos, ...size); break; case tiles.APPLE: this.game.ctx.fillStyle = "#ff0000"; this.game.ctx.fillRect(...canvasPos, ...size); 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" };