HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

HTML5 Snake Game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gamehtml5snake

Problem

This is the first version of my first HTML5 game. Beyond the standard features, I've added a high scores board which uses local storage to keep track of the scores.

You can move the snake with the arrow keys. Unlike the normal game, running into the wall doesn't kill the snake, only when it runs into itself. This will display the "Game Over" screen, at which point you can either enter your name or be anonymous as 'Noname'. You can view the high scores at any time by pressing the 'Highscores' button. From there you are also able to go back to the main menu and start a new game.

I'd like feedback to focus on the JavaScript, especially with regards to cleanliness and readability, as well as overall best practices.

As a side note, I'm not sure if the stack snippets will run properly because of the use of local storage, but it works fine if run normally.



`"use strict";
(function (){
let canvas = document.getElementById('gameboard');
let scoreBoard = document.querySelector('.scoreboard');
let highscoreLabel = document.querySelector('.highscore');
let restartBtn = document.getElementById('restart');
let gameOverScreen = document.querySelector('.gameover-screen');
let finalScoreLabel = document.querySelector('.final-score');
let playerNameInput = document.querySelector('.player-name');
let highscoreBoardBtn = document.getElementById('highscores-btn');
let highscoresBoard = document.querySelector('.highscores-board');
let highscoresList = document.querySelector('.highscores-list');
let highscoresReturnBtn = document.getElementById('return-from-highscores');

canvas.width = 800;
canvas.height = 600;
let ctx = canvas.getContext('2d');

let isPlayerSaved,
state,
points,
playerName,
snakeBody,
direction,
blockSize,
snakeHead,
apple;

let init = function() {
canvas.style.display = "block";
gameOverScreen.style.display = "none";

isPlayerSaved = false;//this flag helps eliminate duplicates from highscore board;if it's value's true,sa

Solution

In general this is how would a JS game architecture look like.
You certainly can get it working with another architecture but this one will give good performance and responsiveness.

You have to careful with calls from within the event handlers.
You want to release the event handler ASAP - so call only quick core methods.

Everything else (like save to disks, network io) try to do it in the core thread/timer where the process should be triggered by some indicator in the shared data for example.

Comments on specific moments:

1) Global funcitons


let generateApple = function() { .. }

when you put that code in the global scope it is the same like


function generateApple() { .. }

Where the latter is a bit more readable in my opinion.

2) Global functions 2

You are using global functions most of the time - that allows you to call everything from everywhere and makes your program look like a bow of spaghetti. No offense I love it .. however in the long term makes your code hard to read and maintain.

I'd suggest you to keep your code separated in namespaces classes at least.


var Core={};
Core.prototype.generateApple = function() { .. }
Core.prototype.checkForCollisions = function() { .. }


var UI = {};
UI.prototype.draw = function() { .. }

This will allow you to have separation of concerns and will help you understand and maintain your own code better.

3) Naming conventions


function loop() { .. } // Is expected to have a loop inside

Try to find name to represent what is the code inside doing.
If the code is handling user input, renders the content to screen and updates the high score table .. call it like that.


handleUserInputRenderScreeContentAndUpdateHighScoreTable()

This should hint you to break code in purposeful functions separated by concern.

4) Event handlers

Mind you - these function are called on mouse or button click. if you want responsive UI and happy users keep them short and fast.
If it would take time the user would expect at a "please wait" indicator.

I would love to see it again after you apply these principals.

Context

StackExchange Code Review Q#135319, answer score: 2

Revisions (0)

No revisions yet.