Snake game
The famous snake game! Once you click run, click anywhere
inside the black area, and control the snake using i j k and l. Don't let
the snake hit itself or the wall!
Example created by Prashant Gupta
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// the snake is divided into small segments, which are drawn and edited on each 'draw' call
let numSegments = 10;
let direction = 'right';
const xStart = 0; //starting x coordinate for snake
const yStart = 250; //starting y coordinate for snake
const diff = 10;
let xCor = [];
let yCor = [];
let xFruit = 0;
let yFruit = 0;
let scoreElem;
function setup() {
scoreElem = createDiv('Score = 0');
scoreElem.position(20, 20);
scoreElem.id = 'score';
scoreElem.style('color', 'white');
createCanvas(500, 500);
frameRate(15);
stroke(255);
strokeWeight(10);
updateFruitCoordinates();
for (let i = 0; i < numSegments; i++) {
xCor.push(xStart + i * diff);
yCor.push(yStart);
}
}
function draw() {
background(0);
for (let i = 0; i < numSegments - 1; i++) {
line(xCor[i], yCor[i], xCor[i + 1], yCor[i + 1]);
}
updateSnakeCoordinates();
checkGameStatus();
checkForFruit();
}
/*
The segments are updated based on the direction of the snake.
All segments from 0 to n-1 are just copied over to 1 till n, i.e. segment 0
gets the value of segment 1, segment 1 gets the value of segment 2, and so on,
and this results in the movement of the snake.
The last segment is added based on the direction in which the snake is going,
if it's going left or right, the last segment's x coordinate is increased by a
predefined value 'diff' than its second to last segment. And if it's going up
or down, the segment's y coordinate is affected.
*/
function updateSnakeCoordinates() {
for (let i = 0; i < numSegments - 1; i++) {
xCor[i] = xCor[i + 1];
yCor[i] = yCor[i + 1];
}
switch (direction) {
case 'right':
xCor[numSegments - 1] = xCor[numSegments - 2] + diff;
yCor[numSegments - 1] = yCor[numSegments - 2];
break;
case 'up':
xCor[numSegments - 1] = xCor[numSegments - 2];
yCor[numSegments - 1] = yCor[numSegments - 2] - diff;
break;
case 'left':
xCor[numSegments - 1] = xCor[numSegments - 2] - diff;
yCor[numSegments - 1] = yCor[numSegments - 2];
break;
case 'down':
xCor[numSegments - 1] = xCor[numSegments - 2];
yCor[numSegments - 1] = yCor[numSegments - 2] + diff;
break;
}
}
/*
I always check the snake's head position xCor[xCor.length - 1] and
yCor[yCor.length - 1] to see if it touches the game's boundaries
or if the snake hits itself.
*/
function checkGameStatus() {
if (
xCor[xCor.length - 1] > width ||
xCor[xCor.length - 1] < 0 ||
yCor[yCor.length - 1] > height ||
yCor[yCor.length - 1] < 0 ||
checkSnakeCollision()
) {
noLoop();
const scoreVal = parseInt(scoreElem.html().substring(8));
scoreElem.html('Game ended! Your score was : ' + scoreVal);
}
}
/*
If the snake hits itself, that means the snake head's (x,y) coordinate
has to be the same as one of its own segment's (x,y) coordinate.
*/
function checkSnakeCollision() {
const snakeHeadX = xCor[xCor.length - 1];
const snakeHeadY = yCor[yCor.length - 1];
for (let i = 0; i < xCor.length - 1; i++) {
if (xCor[i] === snakeHeadX && yCor[i] === snakeHeadY) {
return true;
}
}
}
/*
Whenever the snake consumes a fruit, I increment the number of segments,
and just insert the tail segment again at the start of the array (basically
I add the last segment again at the tail, thereby extending the tail)
*/
function checkForFruit() {
point(xFruit, yFruit);
if (xCor[xCor.length - 1] === xFruit && yCor[yCor.length - 1] === yFruit) {
const prevScore = parseInt(scoreElem.html().substring(8));
scoreElem.html('Score = ' + (prevScore + 1));
xCor.unshift(xCor[0]);
yCor.unshift(yCor[0]);
numSegments++;
updateFruitCoordinates();
}
}
function updateFruitCoordinates() {
/*
The complex math logic is because I wanted the point to lie
in between 100 and width-100, and be rounded off to the nearest
number divisible by 10, since I move the snake in multiples of 10.
*/
xFruit = floor(random(10, (width - 100) / 10)) * 10;
yFruit = floor(random(10, (height - 100) / 10)) * 10;
}
function keyPressed() {
switch (keyCode) {
case 74:
if (direction !== 'right') {
direction = 'left';
}
break;
case 76:
if (direction !== 'left') {
direction = 'right';
}
break;
case 73:
if (direction !== 'down') {
direction = 'up';
}
break;
case 75:
if (direction !== 'up') {
direction = 'down';
}
break;
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX