1
0
Fork 0
This repository has been archived on 2024-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
Snake/sources/js/Snake.js
2021-03-30 09:20:03 +02:00

81 lines
2 KiB
JavaScript

import {GameOver} from "./Game.js";
export class Snake {
/**
* The snake of the game
* @param options
*/
constructor({startPos = [8,8], size = 4, startDirection = directions.RIGHT} = {}) {
if (startPos && Array.isArray(startPos) && startPos.length === 2 && startPos.filter(s => typeof s === "number" && s > 0 && s % 1 === 0).length === startPos.length)
this.body = [startPos];
else
throw new InvalidSnakeOption("startPos");
if (size && typeof size === "number" && size > 1 && size % 1 === 0)
this.size = size;
else
throw new InvalidSnakeOption("size");
// Generate snake body
for (let s = 1; s < this.size; s++) {
const pos = this.body[this.body.length - 1].map((n, i) => n - startDirection[i]);
if (pos.find(v => v < 0))
throw new InvalidSnakeOption("startPos too small");
this.body.push(pos);
}
this.eating = false;
this.narrowing = false;
}
/**
* Move the snake body
* @param {directions} direction
*/
move(direction) {
if (!this.eating)
this.body.pop();
else
this.eating = false;
const pos = this.body[0].map((n, i) => n + direction[i]);
if (this.body.find(([x,y]) => pos[0] === x && pos[1] === y))
throw new GameOver();
if (!this.narrowing)
this.body.unshift(pos);
else
this.narrowing = false;
}
/**
* Enable eating
*/
eat() {
this.eating = true;
}
/**
* Enable narrowing
*/
shrink() {
this.narrowing = true;
}
}
export const directions = {
UP: [0, -1],
RIGHT: [1, 0],
DOWN: [0, 1],
LEFT: [-1, 0]
};
export class InvalidSnakeOption extends Error {
/**
* @param {string} name
*/
constructor(name) {
super(`Invalid Snake option: ${name}`);
}
}