For this weeks assignment I decided to create the popular Snake game. In the creative process I tried to optimize it and I am quite happy with the results. I created a simple class for a snake element and then reused it while creating food items.
To make the game even more optimized I decided to draw the snake in a specific fashion. When the snake eats their food, the food is not “added” to it. Rather than that, the last part of the snake is not removed from it a single time, as it would usually be. That makes the transition a lot smoother and also makes the code cleaner.
With regard to the hit boxes I made them simple as the game was designed on a 10px grid. As a result the snake elements are 10px/10px. Due to that, I could simply compare the X and Y dimensions of the Snake’s leading tile against food’s location, rather than comparing whole ranges, which would be much less efficient.
class snakeRect { constructor(x, y) { this.x = x; this.y = y; } } score = 0; food = new snakeRect(-10,-10); vx = -10; vy = 0; snake = [new snakeRect(200, 200), new snakeRect(210, 200), new snakeRect(220, 200), new snakeRect(230, 200), ]; function setup() { createCanvas(400, 400); textSize(50); food.x = round(random(0, (width-10)/10))*10; food.y = round(random(0, (height-10)/10))*10; } function draw() { background(220); fill(255); textAlign(LEFT); text(score, 20, 50); if (isGameOver()){ textAlign(CENTER); translate(width/2, height/2); fill(255); text('Game Over', 0, 0); return; } drawSnake(); drawFood(); if (frameCount%5==0) { moveSnake(); } } function getFood() { randX = round(random(0, (width-10)/10))*10; randY = round(random(0, (height-10)/10))*10; for(i=0; i<snake.length; i++) { if (snake[i].x==randX && snake[i].y==randY) { getFood(); } } food.x = randX; food.y = randY; } function drawFood() { fill(255, 255, 0); rect(food.x, food.y, 10, 10); } function drawSnake() { fill(200,200,0); for (i=0; i<snake.length; i++) { rect(snake[i].x, snake[i].y, 10, 10); } } function moveSnake() { newElem = new snakeRect(snake[0].x+vx, snake[0].y+vy); snake.unshift(newElem); if (snake[0].x === food.x && snake[0].y === food.y) { score+=10; getFood(); } else { snake.pop(); } } function keyPressed() { if (keyCode===LEFT_ARROW && vx!=10) { vx=-10; vy=0; } else if (keyCode === RIGHT_ARROW && vx!=-10) { vx=10; vy=0; } else if (keyCode === UP_ARROW && vy!=10) { vx=0; vy=-10; } else if (keyCode === DOWN_ARROW && vy!=-10) { vx=0; vy=10; } } function isGameOver() { for (i=4; i<snake.length; i++) { if (snake[i].x === snake[0].x && snake[i].y === snake[0].y) { return true; } } return snake[0].x<0 || snake[0].x>width-10 || snake[0].y<0 || snake[0].y>height-10; }