Merge branch 'master' of github.com:h7x4ABk3g/IT2
This commit is contained in:
@@ -16,6 +16,13 @@
|
|||||||
<canvas id="game"></canvas>
|
<canvas id="game"></canvas>
|
||||||
|
|
||||||
<button class="big" id="start">Start game</button>
|
<button class="big" id="start">Start game</button>
|
||||||
|
<button class="big" id="reset">Reset</button>
|
||||||
|
score: <span id="score"></span> Highscore: <span id="highscore"></span>
|
||||||
|
<form id="pixelAmountForm">
|
||||||
|
<label for="pixelAmount">Size of map:</label>
|
||||||
|
<input type="number" id="pixelAmount" min="5" max="40" value="20">
|
||||||
|
<input type="submit" value="Apply">
|
||||||
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -1,26 +1,27 @@
|
|||||||
// @ts-check
|
|
||||||
|
|
||||||
/* Initialize variables */
|
/* Initialize variables */
|
||||||
const pixelSize = 20; //Cannot be odd
|
const pixelSize = 20; //Cannot be odd
|
||||||
const pixelAmount = 30;
|
const pixelAmount = 30;
|
||||||
|
|
||||||
/* Register HTML DOM elements by variables */
|
/* Register HTML DOM elements by variables */
|
||||||
const canvas = document.getElementById('game');
|
const canvas = document.getElementById('game');
|
||||||
const game = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
const startButton = document.getElementById('start');
|
const startButton = document.getElementById('start');
|
||||||
|
const resetButton = document.getElementById('reset');
|
||||||
|
const scoreSpan = document.getElementById('score');
|
||||||
|
const highscoreSpan = document.getElementById('highscore');
|
||||||
|
const pixelAmountInput = document.getElementById('pixelAmount');
|
||||||
|
const pixelAmountForm = document.getElementById('pixelAmountForm');
|
||||||
|
|
||||||
/* Add event listeners */
|
scoreSpan.innerHTML = score;
|
||||||
document.addEventListener('keydown', updateDirection, false);
|
highscoreSpan.innerHTML = highscore;
|
||||||
startButton.addEventListener('click', gameLoop, false);
|
|
||||||
|
|
||||||
/* Initialize HTML */
|
/* Initialize HTML */
|
||||||
canvas.style.display = 'block';
|
canvas.style.display = 'block';
|
||||||
game.canvas.width = game.canvas.height = pixelSize * pixelAmount;
|
ctx.canvas.width = ctx.canvas.height = (pixelAmount + 1) * pixelSize;
|
||||||
canvas.style.backgroundColor = '#ffffff';
|
canvas.style.backgroundColor = '#ffffff';
|
||||||
|
|
||||||
/* Snake object */
|
/* Snake object */
|
||||||
const snake = {
|
const snake = {
|
||||||
speed: 5, //in FPS
|
|
||||||
direction: 'right',
|
direction: 'right',
|
||||||
color: '#00ff00',
|
color: '#00ff00',
|
||||||
tail: [
|
tail: [
|
||||||
@@ -29,24 +30,11 @@ const snake = {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
[0, 0],
|
[0, 0],
|
||||||
],
|
],
|
||||||
|
deadTail: [0, 0],
|
||||||
/* Draw the snake by the tail array */
|
|
||||||
draw() {
|
|
||||||
game.fillStyle = this.color;
|
|
||||||
|
|
||||||
for (let tailPoint = 0; tailPoint < this.tail.length; tailPoint++) {
|
|
||||||
/* Correct tailpoint x and y to actual size */
|
|
||||||
const realPosition = this.tail[tailPoint].map(point => point * pixelSize);
|
|
||||||
|
|
||||||
game.fillRect(realPosition[0], realPosition[1], pixelSize, pixelSize);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Generate the next tail array */
|
/* Generate the next tail array */
|
||||||
updateTail() {
|
updateTail() {
|
||||||
const realPosition = this.tail.pop().map(point => point * pixelSize);
|
//Add new point to tail based on snake direction
|
||||||
game.clearRect(realPosition[0], realPosition[1], pixelSize, pixelSize);
|
|
||||||
|
|
||||||
switch (this.direction) {
|
switch (this.direction) {
|
||||||
case 'left':
|
case 'left':
|
||||||
this.tail.unshift([this.tail[0][0] - 1, this.tail[0][1]]);
|
this.tail.unshift([this.tail[0][0] - 1, this.tail[0][1]]);
|
||||||
@@ -61,47 +49,196 @@ const snake = {
|
|||||||
this.tail.unshift([this.tail[0][0], this.tail[0][1] + 1]);
|
this.tail.unshift([this.tail[0][0], this.tail[0][1] + 1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.deadTail = this.tail.pop();
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Draw the snake by the tail array */
|
||||||
|
draw() {
|
||||||
|
ctx.fillStyle = this.color;
|
||||||
|
|
||||||
|
const clearPosition = this.deadTail.map(point => point * pixelSize);
|
||||||
|
ctx.clearRect(clearPosition[0], clearPosition[1], pixelSize, pixelSize);
|
||||||
|
|
||||||
|
for (let tailPoint = 0; tailPoint < this.tail.length; tailPoint++) {
|
||||||
|
/* Correct tailpoint x and y to actual size */
|
||||||
|
const realPosition = this.tail[tailPoint].map(point => point * pixelSize);
|
||||||
|
|
||||||
|
ctx.fillRect(realPosition[0], realPosition[1], pixelSize, pixelSize);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addTail() {
|
||||||
|
this.tail.push[this.deadTail];
|
||||||
|
},
|
||||||
|
|
||||||
|
tailCrossing() {
|
||||||
|
return new Set(this.tail).size !== this.tail.length; //TODO: fix function
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Apple object */
|
/* Apple object */
|
||||||
const apple = {
|
const apple = {
|
||||||
position: [20, 20],
|
position: [Math.floor(pixelAmount / 2), Math.floor(pixelAmount / 2)],
|
||||||
color: 'red',
|
color: 'red',
|
||||||
|
|
||||||
|
/* Sets position to the middle based on pixelAmount */
|
||||||
|
setStartPosition() {
|
||||||
|
this.position = [Math.floor(pixelAmount / 2), Math.floor(pixelAmount / 2)];
|
||||||
|
},
|
||||||
|
|
||||||
/* Generate new coordinates */
|
/* Generate new coordinates */
|
||||||
generate() {
|
generatePosition() {
|
||||||
this.position.map(() => Math.floor(Math.random() * pixelAmount));
|
this.position = game.getClearSpotRandom(); //TODO: Switch between the functions based on how much the snake has eaten
|
||||||
|
console.debug(`%cApple position: ${this.position}`, 'color: red');
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Draw the apple */
|
/* Draw the apple */
|
||||||
draw() {
|
draw() {
|
||||||
const realPosition = this.position.map(point => point * pixelSize);
|
const realPosition = this.position.map(point => point * pixelSize);
|
||||||
|
|
||||||
game.fillStyle = this.color;
|
ctx.fillStyle = this.color;
|
||||||
game.fillRect(realPosition[0], realPosition[1], pixelSize, pixelSize);
|
ctx.fillRect(realPosition[0], realPosition[1], pixelSize, pixelSize);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Wrapper function for gameloop */
|
/* Handles everything that happens on the canvas */
|
||||||
function gameLoop() {
|
const game = {
|
||||||
/* Slow down loop by snake speed*/
|
fps: 5,
|
||||||
setTimeout(() => {
|
hasEnded: false,
|
||||||
window.requestAnimationFrame(gameLoop);
|
isPaused: false,
|
||||||
gameUpdate();
|
|
||||||
}, 1000 / snake.speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Function that is being run each tick */
|
/* Game init function */
|
||||||
function gameUpdate() {
|
init() {
|
||||||
/* Draw snake */
|
apple.draw();
|
||||||
snake.draw();
|
},
|
||||||
snake.updateTail();
|
|
||||||
|
|
||||||
if (snake.tail[0] === apple.position) {
|
/* Game loop function */
|
||||||
|
loop() {
|
||||||
|
/* Draw snake */
|
||||||
|
snake.updateTail();
|
||||||
|
snake.draw();
|
||||||
|
|
||||||
|
if (snake.tail[0].toString() === apple.position.toString()) {
|
||||||
|
console.debug('Snake ate apple');
|
||||||
|
score += 1;
|
||||||
|
scoreSpan.innerHTML = score;
|
||||||
|
snake.updateTail();
|
||||||
|
apple.generatePosition();
|
||||||
|
apple.draw();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
snake.tail[0][0] > pixelAmount ||
|
||||||
|
snake.tail[0][1] > pixelAmount ||
|
||||||
|
snake.tail[0][0] < 0 ||
|
||||||
|
snake.tail[0][1] < 0 ||
|
||||||
|
snake.tailCrossing()
|
||||||
|
) {
|
||||||
|
this.hasEnded = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
/*TODO: get board size from localstorage */
|
||||||
|
snake.tail = [
|
||||||
|
[3, 0],
|
||||||
|
[2, 0],
|
||||||
|
[1, 0],
|
||||||
|
[0, 0],
|
||||||
|
];
|
||||||
|
snake.direction = 'right';
|
||||||
|
apple.setStartPosition();
|
||||||
|
game.hasEnded = false;
|
||||||
|
ctx.fillStyle = '#ffffff';
|
||||||
|
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Function to determine whether a coordinate hits the snake
|
||||||
|
* Retuns a bool
|
||||||
|
*/
|
||||||
|
hitsSnake(coordinate) {
|
||||||
|
return snake.tail
|
||||||
|
.map(snakeCoordinate => snakeCoordinate.toString()) //TODO: Rewrite
|
||||||
|
.toString()
|
||||||
|
.includes(coordinate.toString());
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Function to be used if the snake is covering a small part of the map
|
||||||
|
* Returns a coordinate array
|
||||||
|
*/
|
||||||
|
getClearSpotRandom() {
|
||||||
|
while (true) {
|
||||||
|
const coordinate = Array.from({length: 2}, () =>
|
||||||
|
Math.floor(Math.random() * pixelAmount)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!this.hitsSnake(coordinate)) {
|
||||||
|
return coordinate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Function to be used if the snake is covering a big part of the map
|
||||||
|
* Returns a coordinate array
|
||||||
|
*/
|
||||||
|
getClearSpotForce() {
|
||||||
|
clearSpots = [];
|
||||||
|
|
||||||
|
for (let x = 0; x < pixelAmount; x++) {
|
||||||
|
for (let y = 0; y < pixelAmount; y++) {
|
||||||
|
if (!this.hitsSnake([x, y])) {
|
||||||
|
clearSpots.push([x, y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clearSpots[Math.floor(Math.random() * clearSpots.length)];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Wrapper function requesting a gameloop */
|
||||||
|
function getLoop() {
|
||||||
|
/* Slow down loop by game fps */
|
||||||
|
if (!game.hasEnded) {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.requestAnimationFrame(getLoop);
|
||||||
|
game.loop();
|
||||||
|
}, 1000 / game.fps);
|
||||||
|
} else {
|
||||||
|
console.debug('Game over');
|
||||||
|
|
||||||
|
if (score > highscore) {
|
||||||
|
console.debug('New highcore');
|
||||||
|
highscore = score;
|
||||||
|
window.localStorage.setItem('highscore', highscore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add event listeners */
|
||||||
|
document.addEventListener('keydown', updateDirection, false);
|
||||||
|
startButton.addEventListener(
|
||||||
|
'click',
|
||||||
|
() => {
|
||||||
|
game.init();
|
||||||
|
getLoop();
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
resetButton.addEventListener('click', game.reset, false);
|
||||||
|
pixelAmountForm.addEventListener('submit', updatePixelAmount, false);
|
||||||
|
|
||||||
|
/* Updates size of canvas */
|
||||||
|
function updatePixelAmount(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
pixelAmount = parseInt(pixelAmountInput.value);
|
||||||
|
console.debug('Updated canvas size');
|
||||||
|
ctx.canvas.width = ctx.canvas.height = (pixelAmount + 1) * pixelSize;
|
||||||
|
apple.setStartPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear higscore from localStorage */
|
||||||
|
const clearHighscore = () => (window.localStorage.highscore = 0);
|
||||||
|
|
||||||
/* Update direction for snake */
|
/* Update direction for snake */
|
||||||
function updateDirection(evt) {
|
function updateDirection(evt) {
|
||||||
const key = evt.code;
|
const key = evt.code;
|
||||||
@@ -134,4 +271,6 @@ function updateDirection(evt) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Add pause function
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user