diff --git a/index.html b/index.html
index 2765af8..1815392 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,6 @@
-
KyFlo Snake
@@ -22,6 +21,8 @@
+
+
diff --git a/sources/js/Game.js b/sources/js/Game.js
index 1145588..0f05d5a 100644
--- a/sources/js/Game.js
+++ b/sources/js/Game.js
@@ -6,44 +6,27 @@ export class Game {
/**
* Generate a new game of Snake
* @param {HTMLCanvasElement} canvas
- * @param {[int, int]} size
- * @param {directions} direction
- * @param {int} snakeSpeed
- * @param {int} appleSpeed
- * @param {int} lives
*/
- constructor(canvas, {size = [15, 15], direction = directions.RIGHT, snakeSpeed = 500, appleSpeed = 5000, lives = 3} = {}) {
+ constructor(canvas) {
if (canvas && canvas.nodeName === "CANVAS")
this.ctx = canvas.getContext("2d");
else
throw new InvalidGameOption("canvas");
- if (size && Array.isArray(size) && size.length === 2 && size.filter(s => typeof s === "number" && s > 0 && s % 1 === 0).length === size.length)
- this.size = size;
- else
- throw new InvalidGameOption("size");
-
- if (direction && Object.values(directions).find(([x,y]) => direction[0] === x && direction[1] === y))
- this.direction = this.startDirection = this.lastDirection = direction;
- else
- throw new InvalidGameOption("direction");
-
- if (snakeSpeed && typeof snakeSpeed === "number" && snakeSpeed > 0 && snakeSpeed % 1 === 0)
- this.snakeSpeed = snakeSpeed;
- else
- throw new InvalidGameOption("snakeSpeed");
-
- if (appleSpeed && typeof appleSpeed === "number" && appleSpeed > 0 && appleSpeed % 1 === 0)
- this.appleSpeed = appleSpeed;
- else
- throw new InvalidGameOption("appleSpeed");
+ this.size = [15, 15];
+ this.direction = directions.RIGHT;
+ this.snakeSpeed = 500;
+ this.appleSpeed = 5000;
+ this.lives = 3;
this.world = [];
this.apple = false;
this.score = 0;
- this.lives = lives;
this.onStart = null;
this.onStop = null;
+ this.onEat = null;
+ this.onDie = null;
+ this.onGameOver = null;
}
/**
@@ -62,7 +45,7 @@ export class Game {
* Init the canvas
*/
initCanvas() {
- this.ctx.canvas.ownerDocument.addEventListener("keyup", ev => {
+ this.ctx.canvas.ownerDocument.addEventListener("keydown", ev => {
switch (ev.key) {
case "ArrowUp":
if (this.lastDirection !== directions.DOWN)
@@ -146,10 +129,14 @@ export class Game {
if (err instanceof GameOver) {
this.lives--;
if (this.lives <= 0) {
- alert(`Game over !\nYour score is: ${this.score}`);
+ if (this.onGameOver && typeof this.onGameOver === "function")
+ this.onGameOver(this.score);
this.stop();
- } else
+ } else {
+ if (this.onDie && typeof this.onDie === "function")
+ this.onDie(this.lives);
this.restart();
+ }
} else {
console.error(err);
alert("An error occurred !");
@@ -170,6 +157,8 @@ export class Game {
this.snake.eat();
this.apple = false;
this.score++;
+ if (this.onEat && typeof this.onEat === "function")
+ this.onEat(this.score);
}
t.type = tiles.SNAKE;
}
@@ -218,6 +207,41 @@ export class Game {
return pos;
}
+
+ /**
+ * Generate a new game of Snake
+ * @param {[int, int]} size
+ * @param {directions} direction
+ * @param {int} snakeSpeed
+ * @param {int} appleSpeed
+ * @param {int} lives
+ */
+ load({size = [15, 15], direction = directions.RIGHT, snakeSpeed = 500, appleSpeed = 5000, lives = 3} = {}) {
+ if (size && Array.isArray(size) && size.length === 2 && size.filter(s => typeof s === "number" && s > 0 && s % 1 === 0).length === size.length)
+ this.size = size;
+ else
+ throw new InvalidGameOption("size");
+
+ if (direction && Object.values(directions).find(([x,y]) => direction[0] === x && direction[1] === y))
+ this.direction = this.startDirection = this.lastDirection = direction;
+ else
+ throw new InvalidGameOption("direction");
+
+ if (snakeSpeed && typeof snakeSpeed === "number" && snakeSpeed > 0 && snakeSpeed % 1 === 0)
+ this.snakeSpeed = snakeSpeed;
+ else
+ throw new InvalidGameOption("snakeSpeed");
+
+ if (appleSpeed && typeof appleSpeed === "number" && appleSpeed > 0 && appleSpeed % 1 === 0)
+ this.appleSpeed = appleSpeed;
+ else
+ throw new InvalidGameOption("appleSpeed");
+
+ if (lives && typeof lives === "number" && lives > 0 && lives % 1 === 0)
+ this.lives = lives;
+ else
+ throw new InvalidGameOption("lives");
+ }
}
export class InvalidGameOption extends Error {
diff --git a/sources/js/index.js b/sources/js/index.js
index 3790915..a5760e2 100644
--- a/sources/js/index.js
+++ b/sources/js/index.js
@@ -4,7 +4,17 @@ const canvas = document.getElementById("canvas");
const menu = document.getElementById("menu");
const menuLevel = document.querySelector(".menu-level");
const gameZone = document.getElementById("game");
-let game;
+const score = document.getElementById("score");
+const lives = document.getElementById("lives");
+const audio = new Audio("sources/sound/main.mp3");
+const startSound = new Audio("sources/sound/onStart.mp3");
+const eatSound = new Audio("sources/sound/onEat.mp3");
+const dieSound = new Audio("sources/sound/onDie.mp3");
+const gameOverSound = new Audio("sources/sound/onGameOver.mp3");
+const game = new Game(canvas);
+
+
+startSound.volume = "0.2";
req.open("GET", "sources/levels.json");
req.onerror = () => console.error("Fail to load XML request");
@@ -16,10 +26,37 @@ req.onload = () => {
else
levels = null;
loadLevels(levels);
-}
+};
req.send();
+game.onStart = () => {
+ updateLives(game.lives);
+ updateScore(game.score);
+ menu.classList.add("invisible");
+ canvas.classList.remove("invisible");
+};
+
+game.onStop = () => {
+ menu.classList.remove("invisible");
+ canvas.classList.add("invisible");
+};
+
+game.onEat = (score) => {
+ eatSound.play();
+ updateScore(score);
+};
+
+game.onDie = lives => {
+ dieSound.play();
+ updateLives(lives);
+};
+
+game.onGameOver = (score) => {
+ gameOverSound.play();
+ alert(`Game over !\nYour score is: ${score}`);
+};
+
function loadLevels(levels) {
if (!levels) {
menuLevel.innerHTML = "";
@@ -35,25 +72,28 @@ function loadLevels(levels) {
}
}
-const loadGame = data => {
- game = new Game(canvas, data);
-
- game.onStart = () => {
- menu.classList.add("invisible");
- canvas.classList.remove("invisible");
- };
-
- game.onStop = () => {
- menu.classList.remove("invisible");
- canvas.classList.add("invisible");
- };
-
+function loadGame(data) {
+ game.load(data);
game.start();
+ startSound.play();
};
+function updateScore(s) {
+ score.innerText = s;
+}
+
+function updateLives(l) {
+ lives.innerText = l;
+}
+
document.addEventListener('DOMContentLoaded', function() {
M.AutoInit();
- canvas.width = gameZone.offsetWidth;
- canvas.height = gameZone.offsetHeight;
+ canvas.width = gameZone.clientWidth;
+ canvas.height = gameZone.clientHeight;
+});
+
+audio.addEventListener("canplaythrough", () => {
+ audio.volume = 0.1;
+ audio.play();
});
diff --git a/sources/sound/onDie.mp3 b/sources/sound/onDie.mp3
new file mode 100644
index 0000000..27bfd8f
Binary files /dev/null and b/sources/sound/onDie.mp3 differ
diff --git a/sources/sound/onEat.mp3 b/sources/sound/onEat.mp3
new file mode 100644
index 0000000..65e634b
Binary files /dev/null and b/sources/sound/onEat.mp3 differ
diff --git a/sources/sound/onGameOver.mp3 b/sources/sound/onGameOver.mp3
new file mode 100644
index 0000000..3b15a5c
Binary files /dev/null and b/sources/sound/onGameOver.mp3 differ
diff --git a/sources/sound/onStart.mp3 b/sources/sound/onStart.mp3
new file mode 100644
index 0000000..e12e368
Binary files /dev/null and b/sources/sound/onStart.mp3 differ