How to make a Snake Game using JavaScript and html5


I compiled stapes to create a game similar to Nokia developed, popular game called 'snake'

Snake was first developed by Nokia, programmed in 1997 by Taneli Armanto and published on Nokia mobile devices,  It was introduced on Nokia model 6110, 3310 from 2000 and later the game was rebranded as "Snake Xenzia" Included on later mobile phone models

I made a version that is more simplified and more beginners friendly, It's based on the same idea of making a snake that grows as it eats stuff and the score increases as it grows

I'm implementing this whole game in pure vanilla JavaScript and a taste of html5 canvas, In this project the canvas is used as a renderer for the game's visual output

concepts and initial ideas

I got the idea while doing another retro gaming project, i thought it would be good too if i created this game, from start my plan had been simplicity and making this game easy to implement,
So to simplify everything i had a great deal of planning prior getting started to write any code at all,

I ended up making everything circular so that collision detection is a matter of adding the radii of colliding objects and comparing it to the distance of the same colliding objects

Objects and game characters

The game has two objects

First object

An apple is an edible entity named 'apple' it's update loop has a statement responsible for inducing blinking by randomly tangling the boolean responsible for enabling it to draw its own body

Second object

A snake is an entity capable of keeping track of it's trail, upon collision with the first object 'Apple' the snake increases it's trail gradually as a way to accommodate growth, upon receiving the input event the snake changes it's velocity factor gradually changing it's direction, In the snake's update block there's a piece of code responsible for displacing the snake's {x, y} coordinates by it's velocity factor to archive movement 'locomotion', the snake also folds it's position upon moving out of the game world boundaries

Game world space

Game world is a responsive, monochrome 2d space stretching across the viewport's width and height, completely covering it, Game function is responsible for clearing the screen and updating all constituent entites residing in it's array of entities.
I open sourced this project on Github in a public repository, contributors are welcome as long as the contribution does not change the main idea of the game

The original source code is embedded in a gist below;

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="theme-color" content="#333" />
<!-- Primary Meta Tags -->
<title>Snake Game —— Online Classic Nokia Snake Game</title>
<meta name="title" content="Snake Game —— Online Classic Nokia Snake Game">
<meta name="description" content="Snake Game is a new webgame based on the classic arcade snake game by nokia, It's responsive, can be played on desktop and smartphones written in JavaScript and html5">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://io.swana.me/snake/">
<meta property="og:title" content="Snake Game —— Online Classic Nokia Snake Game">
<meta property="og:description" content="Snake Game is a new webgame based on the classic arcade snake game by nokia, It's responsive, can be played on desktop and smartphones written in JavaScript and html5">
<meta property="og:image" content="https://io.swana.me/snake/mockup.png">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://io.swana.me/snake/">
<meta property="twitter:title" content="Snake Game —— Online Classic Nokia Snake Game">
<meta property="twitter:description" content="Snake Game is a new webgame based on the classic arcade snake game by nokia, It's responsive, can be played on desktop and smartphones written in JavaScript and html5">
<meta property="twitter:image" content="https://io.swana.me/snake/mockup.png">
<style type="text/css">
#container {
width: 100%;
height: 100%;
margin: 0 auto;
padding: 0;
}
#gameViewport {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0)
}
html,
body,
canvas {
position: absolute;
left: 0;
top: 0;
margin: auto;
overscroll-behavior: contain
}
</style>
</head>
<body scroll="no" style="margin: 0">
<canvas id="canvas"></canvas>
<script type="text/javascript" src="./snake.js"></script>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
var game, snake, apple
apple = function(params) {
this.x = params.x
this.y = params.y
this.color = params.color
this.radius = params.radius
this.update = function() {
this.blink = (Math.random() > 0.8) ? 0 : 1;
}
this.render = function() {
if(this.blink === 0) return;
context.save()
context.beginPath()
context.fillStyle = this.color
context.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
context.fill()
context.closePath()
context.restore()
}
}
apple.prototype.collides = function(c) {
var a = this.x - c.x
var b = this.y - c.y
var d = (a * a) + (b * b)
var radii = this.radius + c.radius
return radii * radii >= d
}
snake = function(params) {
this.x = params.x
this.y = params.y
this.radius = 10
this.length = 100
this.trail = []
this.direction = [0, 0]
this.color = "#78847a"
this.update = () => {
var speed = this.length / 10
this.x += this.radius * this.direction[0] * speed / 60
this.y += this.radius * this.direction[1] * speed / 60
this.trail.unshift({
x: this.x,
y: this.y,
radius: this.radius
})
if (apple.collides(this.trail[0])) {
apple.reset()
this.length += 1
}
if (this.y > canvas.height)
this.y = -this.radius
if ((this.y < -this.radius))
this.y = canvas.height - this.radius
if (this.x > canvas.width)
this.x = -this.radius
if (this.x < -this.radius)
this.x = canvas.width - this.radius
}
this.render = () => {
this.trail.splice(this.length, 100)
this.trail.forEach((cell, index) => {
var opacity = ((index / this.length) - 1) * -1
context.save()
context.translate(cell.x, cell.y)
context.rotate((45) * (Math.PI / 180))
context.translate(-cell.x, -cell.y)
context.beginPath()
context.fillStyle = 'rgba(67,77,67,'+ opacity +')';
context.arc(cell.x, cell.y, ((cell.radius + cell.radius) / 2), 0, Math.PI * 2)
context.fill()
context.closePath()
context.restore()
})
}
}
game = function(params) {
this.score = 0
this.objects = []
context = params.context
this.loop = () => {
window.requestAnimationFrame(this.loop)
this.update()
this.render()
}
this.update = () => {
this.objects.forEach((object) => {
object.update()
})
}
this.render = () => {
context.fillStyle = "#acbeac"
context.fillRect(0, 0,
canvas.width,
canvas.height
)
this.objects.forEach((object) => {
object.render()
})
// draw hub
context.font = '1em digit'
context.fillStyle = "#0f0f0f"
context.fillText('score: ' + this.score, (16), (50))
}
}
var context = canvas.getContext("2d")
var snakes = new game({
context
})
canvas.style.width = canvas.width = window.innerWidth
canvas.style.height = canvas.height = window.innerHeight
canvas.addEventListener("click", function(point) {
var snake = snakes.objects[0]
var i = {
x: point.pageX,
y: point.pageY
},
ii = {
x: snake.x,
y: snake.y
}
snake.direction[0] = 0
snake.direction[1] = 0
var dy = ii.y - i.y,
dx = ii.x - i.x
if(Math.abs(dy) > Math.abs(dx)) {
if (dy > 0) snake.direction[1] = -1
if (dy < 0) snake.direction[1] = 1
} else {
if (dx > 0) snake.direction[0] = -1
if (dx < 0) snake.direction[0] = 1
}
})
apple = new apple({
color: "#434d43",
radius: 15,
x: Math.random() * canvas.width,
y: Math.random() * canvas.height
})
apple.reset = function() {
snakes.score++
this.x = Math.random() * canvas.width
this.y = Math.random() * canvas.height
}
snakes.objects.push(new snake({
x: 50,
y: 50
}))
snakes.objects.push(apple)
snakes.loop()
view raw snakeGame.js hosted with ❤ by GitHub


Insightful references;
Full source code
Github swashvirus/snake/ repository,

Wikipedia Snake Game reference

Comments

Popular posts from this blog

JavaScript introduction to variables

How to set content disposition headers for express nodejs apps

Solutions to blocked URLs on Facebook

how to dump a postgresql database using from the terminal

How to get user's ip address in JavaScript