Hello! I am currently working on my personal JavaScript snake game project. I have a snake and apple on the screen right now. I have not yet added the border collision. Right now, I don't know how to force the snake to line up exactly with the apple (the snake and apple can touch even when not aligned properly).
What I have tried:
I have mainly tried checking if the x and y positions are a multiple of my snake width and height before letting the snake move. At the same time for the apple, I tried to find the nearest coordinate point from my random point that would be a multiple of the snake width and height. However, that didn't seem to work, so I deleted that code and I am back on square one. My code below is what I have. Any help is greatly appreciated, and let me know if you need any clarification!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<link rel="stylesheet" href="snake.css">
</head>
<body>
<canvas id="canvas"></canvas>
<script src="snake.js"></script>
</body>
</html>
#canvas {
position: absolute;
background-color: black;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const snakeWidth = 20;
const snakeHeight = 20;
let snakeX = canvas.width / 2;
let snakeY = canvas.height / 2;
let speedX = 0;
let speedY = 0;
const snakeSpeed = 1;
const snakeArray = [];
let prevKey = '';
const posHistory = [];
const canvasArea = canvas.width * canvas.height;
let randX = Math.random() * canvas.width;
let randY = Math.random() * canvas.height;
console.log(snakeX);
console.log(snakeY);
canvas.addEventListener("resize", () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
snakeArray[0].draw();
apple.drawApple();
});
class Snake {
constructor() {
this.width = snakeWidth;
this.height = snakeHeight;
this.x = snakeX - (this.width / 2);
this.y = snakeY - (this.height / 2);
this.speedX = speedX;
this.speedY = speedY;
}
updateHead() {
posHistory.push([this.x, this.y]);
this.x += speedX;
this.y += speedY;
if (posHistory.length >= canvasArea)
posHistory.pop();
}
updateTail(index) {
this.x = posHistory[posHistory.length - index][0];
this.y = posHistory[posHistory.length - index][1];
}
draw() {
ctx.fillStyle = 'green';
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
snakeArray.push(new Snake());
class Apple {
constructor() {
this.width = snakeWidth;
this.height = snakeHeight;
this.x = randX - (randX % this.width);
this.y = randY - (randY % this.height);
}
drawApple() {
ctx.fillStyle = 'red';
ctx.fillRect(this.x, this.y, this.width, this.height);
}
appleCollision() {
for (let i = 0; i < snakeArray.length; i++) {
if (Math.abs(this.x - snakeArray[i].x) <= 20 && Math.abs(this.y - snakeArray[i].y) <= 20) {
addSnake();
randX = Math.random() * canvas.width;
randY = Math.random() * canvas.height;
this.x = randX;
this.y = randY;
console.log(this.x, this.y);
; }
}
}
}
const apple = new Apple();
document.addEventListener("keydown", (event) => {
switch (event.key) {
case 'ArrowUp':
if (prevKey !== 'down') {
speedX = 0;
speedY = -1 * snakeSpeed;
prevKey = 'up';
}
break;
case 'ArrowRight':
if (prevKey !== 'left') {
speedX = snakeSpeed;
speedY = 0;
prevKey = 'right';
}
break;
case 'ArrowDown':
if (prevKey !== 'up') {
speedX = 0;
speedY = snakeSpeed;
prevKey = 'down';
}
break;
case 'ArrowLeft':
if (prevKey !== 'right') {
speedX = -1 * snakeSpeed;
speedY = 0;
prevKey = 'left';
}
break;
}
});
function handleSnake() {
snakeArray[0].updateHead();
for (let i = 1; i < snakeArray.length; i++) {
snakeArray[i].updateTail(i);
}
for (let j = 0; j < snakeArray.length; j++) {
snakeArray[j].draw();
}
}
function handleApple() {
apple.appleCollision();
apple.drawApple();
}
function addSnake() {
for (let i = 0; i < Math.round(snakeWidth / snakeSpeed); i++)
snakeArray.push(new Snake());
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
handleSnake();
handleApple();
requestAnimationFrame(animate);
}
animate();