From 93bd24e757fdefba93e2798f5b26119151bb1d93 Mon Sep 17 00:00:00 2001 From: flifloo Date: Sat, 27 Mar 2021 12:21:55 +0100 Subject: [PATCH] Custom snake sprite --- sources/js/Game.js | 9 ++- sources/js/Tile.js | 140 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 135 insertions(+), 14 deletions(-) diff --git a/sources/js/Game.js b/sources/js/Game.js index 3155e6b..5c0a724 100644 --- a/sources/js/Game.js +++ b/sources/js/Game.js @@ -175,7 +175,12 @@ export class Game { if (this.onEat && typeof this.onEat === "function") this.onEat(this.score); } - t.type = tiles.SNAKE; + if (!i) + t.type = tiles.HEAD; + else if (i === this.snake.body.length-1) + t.type = tiles.TAIL; + else + t.type = tiles.BODY; } }); } @@ -189,7 +194,7 @@ export class Game { for (const l of this.world) for (const t of l) - if (t.type === tiles.SNAKE) + if (t.type === tiles.HEAD || t.type === tiles.BODY || t.type === tiles.TAIL) t.type = tiles.EMPTY; this.updateSnake(); diff --git a/sources/js/Tile.js b/sources/js/Tile.js index 55b28ba..e89f465 100644 --- a/sources/js/Tile.js +++ b/sources/js/Tile.js @@ -1,4 +1,6 @@ import {Game} from "./Game.js"; +import {directions} from "./Snake.js"; + export class Tile { /** @@ -42,20 +44,20 @@ export class Tile { this.game.ctx.fillRect(...canvasPos, ...size); this.game.ctx.globalCompositeOperation = "source-over"; + const pxsize = Math.round(size[0]/12); + const width = canvasPos[0]; + const height = canvasPos[1]; + switch (this.type) { case tiles.EMPTY: this.game.ctx.strokeStyle = "#999999"; this.game.ctx.rect(...canvasPos, ...size); break; case tiles.APPLE: - 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); @@ -89,22 +91,134 @@ export class Tile { 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); + for (const [i,j] of [[1,1],[10,1],[1,10],[10,10]]) + this.game.ctx.fillRect(width+i*pxsize, height+j*pxsize, pxsize, pxsize); this.game.ctx.globalCompositeOperation = "source-over"; } break; - case tiles.SNAKE: - this.game.ctx.fillStyle = "#00ff5f"; - this.game.ctx.fillRect(...canvasPos, ...size); + case tiles.HEAD: + if (!pxsize) { + this.game.ctx.fillStyle = "#00ff5f"; + this.game.ctx.fillRect(...canvasPos, ...size); + } else { + this.rotate(canvasPos, size); + this.game.ctx.fillStyle = "#FF4294"; + this.game.ctx.fillRect(width + 6 * pxsize, height + pxsize, 6 * pxsize, 10 * pxsize); + this.game.ctx.fillRect(width + 4 * pxsize, height + 2 * pxsize, 6 * pxsize, 8 * pxsize); + this.game.ctx.fillRect(width + 2 * pxsize, height + 3 * pxsize, 6 * pxsize, 6 * pxsize); + this.game.ctx.fillRect(width + pxsize, height + 5 * pxsize, pxsize, 2 * pxsize); + this.game.ctx.fillStyle = "#000000"; + + this.game.ctx.fillRect(width + 6 * pxsize, height, pxsize * 6, pxsize); + this.game.ctx.fillRect(width + 6 * pxsize, height + 11 * pxsize, pxsize * 6, pxsize); + + this.game.ctx.fillRect(width + 4 * pxsize, height + pxsize, pxsize * 2, pxsize); + this.game.ctx.fillRect(width + 4 * pxsize, height + 10 * pxsize, pxsize * 2, pxsize); + + this.game.ctx.fillRect(width + 2 * pxsize, height + 2 * pxsize, pxsize * 2, pxsize); + this.game.ctx.fillRect(width + 2 * pxsize, height + 9 * pxsize, pxsize * 2, pxsize); + + this.game.ctx.fillRect(width + pxsize, height + 7 * pxsize, pxsize, pxsize * 2); + this.game.ctx.fillRect(width + pxsize, height + 3 * pxsize, pxsize, pxsize * 2); + + this.game.ctx.fillRect(width, height + 5 * pxsize, pxsize, pxsize * 2); + + this.game.ctx.fillRect(width + 6 * pxsize, height + 4 * pxsize, pxsize * 4, pxsize); + this.game.ctx.fillRect(width + 6 * pxsize, height + 7 * pxsize, pxsize * 4, pxsize); + this.game.ctx.setTransform(1, 0, 0, 1, 0, 0); + } + break; + case tiles.BODY: + if (!pxsize) { + this.game.ctx.fillStyle = "#0d5317"; + this.game.ctx.fillRect(...canvasPos, ...size); + } else { + this.rotate(canvasPos, size); + this.game.ctx.fillStyle = "#FF4294"; + this.game.ctx.fillRect(width, height, 12*pxsize, 12*pxsize); + this.game.ctx.fillStyle = "#000000"; + + this.game.ctx.fillRect(width, height, pxsize*12, pxsize); + this.game.ctx.fillRect(width, height+11*pxsize, pxsize*12, pxsize); + + for (const [i,j] of [[1,1],[1,9],[2,3],[2,7],[3,5],[5,1],[5,9],[6,3],[6,7],[7,5],[9,1],[9,9],[10,3],[10,7],[11,5]]) + this.game.ctx.fillRect(width+i*pxsize, height+j*pxsize, pxsize, pxsize*2); + + this.game.ctx.setTransform(1, 0, 0, 1, 0, 0); + } + break; + case tiles.TAIL: + if (!pxsize) { + this.game.ctx.fillStyle = "#efff00"; + this.game.ctx.fillRect(...canvasPos, ...size); + } else { + this.rotate(canvasPos, size); + this.game.ctx.fillStyle = "#FF4294"; + this.game.ctx.fillRect(width, height+pxsize, pxsize, 10*pxsize); + this.game.ctx.fillRect(width+pxsize, height+2*pxsize, pxsize, 8*pxsize); + this.game.ctx.fillRect(width+2*pxsize, height+3*pxsize, 2*pxsize, 6*pxsize); + this.game.ctx.fillRect(width+4*pxsize, height+4*pxsize, 3*pxsize, 4*pxsize); + this.game.ctx.fillRect(width+7*pxsize, height+5*pxsize, 4*pxsize, 2*pxsize); + this.game.ctx.fillStyle = "#000000"; + + this.game.ctx.fillRect(width, height, pxsize, pxsize); + this.game.ctx.fillRect(width, height+11*pxsize, pxsize, pxsize); + this.game.ctx.fillRect(width+pxsize, height+pxsize, pxsize, pxsize); + this.game.ctx.fillRect(width+pxsize, height+10*pxsize, pxsize, pxsize); + + this.game.ctx.fillRect(width+2*pxsize, height+2*pxsize, 2*pxsize, pxsize); + this.game.ctx.fillRect(width+2*pxsize, height+9*pxsize, 2*pxsize, pxsize); + + this.game.ctx.fillRect(width+4*pxsize, height+3*pxsize, 3*pxsize, pxsize); + this.game.ctx.fillRect(width+4*pxsize, height+8*pxsize, 3*pxsize, pxsize); + + this.game.ctx.fillRect(width+7*pxsize, height+4*pxsize, 4*pxsize, pxsize); + this.game.ctx.fillRect(width+7*pxsize, height+7*pxsize, 4*pxsize, pxsize); + + this.game.ctx.fillRect(width+11*pxsize, height+5*pxsize, pxsize, 2*pxsize); + this.game.ctx.fillRect(width+5*pxsize, height+5*pxsize, pxsize, 2*pxsize); + this.game.ctx.fillRect(width, height+4*pxsize, pxsize, 4*pxsize); + + this.game.ctx.fillRect(width+pxsize, height+3*pxsize, pxsize, pxsize); + this.game.ctx.fillRect(width+pxsize, height+8*pxsize, pxsize, pxsize); + this.game.ctx.fillRect(width+4*pxsize, height+4*pxsize, pxsize, pxsize); + this.game.ctx.fillRect(width+4*pxsize, height+7*pxsize, pxsize, pxsize); + this.game.ctx.setTransform(1, 0, 0, 1, 0, 0); + } break; } this.game.ctx.stroke(); } + getDirection() { + const np = this.game.snake.body[this.game.snake.body.findIndex(([x,y]) => x === this.x && y === this.y)-1]; + const d = [this.x, this.y].map((n, i) => -(n - np[i])); + + return Object.values(directions).find(([x, y]) => d[0] === x && d[1] === y); + } + + rotate(canvasPos, size) { + const cx = canvasPos[0] + 0.5 * size[0]; + const cy = canvasPos[1] + 0.5 * size[1]; + + this.game.ctx.translate(cx, cy); + switch (this.type === tiles.HEAD? this.game.lastDirection : this.getDirection()) { + case directions.UP: + this.game.ctx.rotate(Math.PI / 2); + break; + case directions.DOWN: + this.game.ctx.rotate(-Math.PI / 2); + break; + case directions.RIGHT: + this.game.ctx.rotate(-Math.PI); + break; + case directions.LEFT: + break; + } + this.game.ctx.translate(-cx, -cy); + } + /** * Get the tile position on the canvas * @returns {[int, int]} @@ -135,5 +249,7 @@ export class InvalidTileOption extends Error { export const tiles = { EMPTY: "empty", APPLE: "apple", - SNAKE: "snake" + HEAD: "head", + BODY: "body", + TAIL: "tail" };