3D 1st Person Snake Game #2
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
This is an iterative review of this question: 3D 1st Person Snake Game #1
The next iteration can be found here: 3D 1st Person Snake Game #3
Here is a snippet of the code:
<html>
<style>
canvas
position:fixed;
left:0;
top:0;
width:99%;
height:99%;
*
padding:0px;
margin:0px
#score,#speed,#highscore,#maxspeed,#lag,#debug
position: fixed;
z-index: 100;
font-size:20px;
font-family:Verdana;
left:15px;
width: 100%;
#gameover
position:absolute;
z-index: 100;
font-size:60px;
font-family:Verdana;
margin: 0;
top: 50%;
left: 50%;
opacity:0;
transform: translate(-50%, -50%);
#maxspeed, #score, #josh, #speed, #highscore, #lag
display:block;
#maxspeed
width: 100%;
top:50px;
display:none;
#score
top: 10px;
#speed
top: 30px;
#highscore
top:30px;
#lag
top: 70px;
</style>
<div id="stats">
<div id="debug"></div>
<div id="score">Score: 0</div>
<div id="speed">Speed: 1</div>
<div id="highscore">Highscore: 1</div>
<div id="maxspeed">Highest Speed: 1</div>
<span id="lag">Lag: 0ms</span>
<div id="gameover" align="center">Game Over</div>
</div>
<div id="canvas"></div>
<p id="p"></p>
<p id="e"></p>
<script type="text/javascript" src="https://cdn.rawgit.com/alexgibson/shake.js/master/shake.js"></script>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
//========================
// One times
//========================
const random = Math.random,
floor = function(a) return ~~a,
newGeometry = THREE.Geometry,
newBufferGeometry = THREE.BufferGeometry,
newMesh = THREE.Mesh,
newLineSegments = THREE.LineSegments,
newMeshBasicMaterial = THREE.MeshBasicMaterial,
newVector3 = THREE.Vector3,
newLineBasicMaterial = THREE.LineBasicMaterial,
newBoxGeometry = THREE.BoxGeometry,
newBoxBufferGeometry = THREE.BoxBufferGeometry,
arena = new THREE.Group(),
applegeometry = new THREE.SphereBufferGeometry( 0.5, 32, 32 ),
superapplematerial= new newMeshBasicMaterial(color:"gold"),
applematerial= new newMeshBasicMaterial(color:"limegreen"),
floormaterial = new newMeshBasicMaterial(color:"lightgrey"),
wallmaterial = new newMeshBasicMaterial( color: "grey" ),
linecube = new newBoxBufferGeometry( 1,1,1 ),
edges = new THREE.EdgesGeometry( linecube ),
geometry = new newBoxBufferGeometry( 1,1,1 ),
stringify = JSON.stringify
</script>
<script id="script">
(function(THREE,ArenaWidth, ArenaLength)
'use strict'
const arenaLines = new THREE.Group(),
arenaWall = new newGeometry(),
arenaFloor = new newGeometry(),
wall1 = new newBoxGeometry( ArenaWidth+1, 1, 1 )
.translate((ArenaWidth/2)-2,1,-2);
arenaWall.merge(wall1);
arenaWall.merge(wall1.translate(0,0, ArenaLength));
const wall2 = new newBoxGeometry( 1, 1, ArenaLength+1 ).translate(ArenaWidth-2,1,(ArenaLength/2)-2);
arenaWall.merge(wall2);
arenaWall.merge(wall2.translate(-ArenaWidth,0,0));
arenaFloor.merge(new newBoxGeometry( ArenaWidth+1, 1, ArenaLength+1 ).translate((ArenaWidth/2)-2,0,(ArenaLength/2)-2))
arenaWall.mergeVertices()
arenaFloor.mergeVertices()
// Get the meshs
window.arenaWallMesh = new newMesh(arenaWall, wallmaterial);
window.arenaFloorMesh = new newMesh(arenaFloor, floormaterial);
var speed = 100,
maxwidth = 40,
maxdepdth = 40,
size = 0.5,
score = 0,
maxheight = 0,
lagNum = 0,
highscoreNum,
showlag,
maxspeedNum,
showmaxspeed,
showhighscore
//========================
// Threejs
//========================
var scene = new THREE.Scene(),
camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,60),
renderer = new THREE.WebGLRenderer(),
extrasLookup =
1:30,
2:50,
3:70,
4:90
//========================
// Reductions
//========================
const newScene = THREE.Scene
if(true /*localStorage.getItem("3dhighscore")==undefined*/)
highscoreNum=0
else
highscoreNum = localStorage.getItem("3dhighscore")
if(true /*localStorage.getItem("showlag")==undefined*/)
showlag=false
else
showlag = localStorage.getItem("showlag")
if(true /*localStorage.getItem("3dmaxspeed")==undefined*/)
maxspeedNum=100
else
maxspeedNum = localStorage.getItem("3dmaxspeed")
if(showmaxspeed==undefined)
showmaxspeed=false
if(showhighscore==undefined)
showhighscore=false
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("canvas").appendChild( renderer.domElement );
function animate()
requestAnimationFrame( animate )
renderer.render( scene, camera );
class Location
constructor(x,y,z)
return [x,y,z]
//========================
// Dom
//========================
const maxSpeedDom = document.getElementById("maxspeed"),
maxSpeedDomStyle = maxSpeedDom.style,
lagdom = document.getElementById("lag"),
lagdomstyle = lagdom.style,
highScoreDom = document.getElementById("highscore"),
highScoreDomStyle = highScoreDom.style,
scoredom = document.getElementById("score"),
speeddom = document.getElementById("speed"),
gameOverDom = document.getElementById("gameover"),
gameOverDomStyle = gameOverDom.style;
//========================
// Snake
//========================
class Snake
constructor()
this.segments = [
new Location(7,1,5),
new Location(6,1,5),
new Location(5,1,5)
];
this.direction = "forwards";
this.nextDirection = "forwards";
this.nextHead = new Location(8,1,5);
draw()
let snakeobject = new THREE.Group();
let j = this.segments.length
this.segments.forEach((item,index) =>
let i = index
let segmentColor=`rgb($255-(255/j,00,00)`
const cube = new newMesh(geometry, new newMeshBasicMaterial( color: segmentColor)),
x = item[0],
y = item[1],
z = item[2];
let pos = new newVector3(x,y,z)
const line = new newLineSegments(edges, new newLineBasicMaterial( color: segmentColor,linewidth:2 ));
cube.position.copy(pos);
line.position.copy(pos);
snakeobject.add(line,cube);
)
scene.add(snakeobject);
move()
this.segments.unshift(this.nextHead);
if(this.checkCollision())
this.segments.shift();
gameOver();
return;
;
var nextHeadPos = this.nextHead;
this.direction = this.nextDirection;
(directionSwitch[this.direction])(nextHeadPos)
if(stringify(this.segments[0]) === stringify(apple.pos))
speed=0.95*speed;
score++;
if(apple.type === "superapple")
speed = 1.10*speed;
score += 4;
apple.move();
else
this.segments.pop();
;
changeDirection(key)
switch(key)
case 39:
case 68:
case 37:
case 65:
keyLookup[key][this.direction]()
break;
case 192:
case 55:
case 56:
keyLookup[key]()
break;
checkCollision()
//========================
// Drawing
//========================
function drawStats()
var extras = 1;
if(score > highscoreNum)
highscoreNum = score;
//localStorage.setItem("3dhighscore", highscore);
if(speed < maxspeed)
maxspeedNum = speed;
//localStorage.setItem("3dmaxspeed", maxspeed);
scoredom.innerHTML=`Score: $score`;
speeddom.innerHTML=`Speed: $(((100/speed*100)`;
if(showhighscore)
extras++;
highscore.style.display = "block";
highscore.style.top = extrasLookup[extras]
highscore.innerHTML = `Highscore: $highscoreNum`;
else
highScoreDomStyle.display = "none";
;
if(showmaxspeed)
extras++;
maxspeed.style.display = "block";
maxspeed.style.top = extrasLookup[extras]
maxspeed.innerHTML = `Highest Speed: $0)/100)`;
else
maxspeed.style.display = "none";
;
if(showlag)
extras++;
lag.style.display = "block";
lag.style.top = extrasLookup[extras]
lag.innerHTML = `Lag: $lagNumms`;
else
lagdomstyle.display = "none";
;
function renderArena()
;
//========================
// Apple
//========================
class Apple
constructor()
this.pos = new Location(2,1,2)
move()
// Set the location to a random x and z.
var x = randomNumberBetween(0,ArenaWidth-4)
var z = randomNumberBetween(0,ArenaLength-4)
this.pos = new Location(x,1,z)
if(randomNumberBetween(1,11)===1&&score>15)
apple.type="superapple"
else
apple.type="apple"
draw()
var sphere
// Generate a new sphere.
if(this.type=="superapple")
sphere = new newMesh( applegeometry, superapplematerial );
else
sphere = new newMesh( applegeometry, applematerial );
// Get the data location.
var applepos=apple.pos
// Set the location of the visual apple to the data location.
sphere.position.set(applepos[0],applepos[1],applepos[2])
scene.add(sphere);
//========================
// Misc
//========================
function newGame(key)
if(key==82)
// Stop the game.
clearTimeout(gameLoop);
s=function();
// Start a new game.
var game = document.getElementById("canvas");
game.removeChild(game.childNodes[0]);
eval(document.getElementById("script").innerHTML);
gameOverDomStyle.opacity=0;
function gameOver()
s = function()
camera.position.copy(new newVector3((ArenaWidth/2)-2,Math.sqrt(
Math.pow(ArenaWidth/2,2)+Math.pow(ArenaLength/2,2)),(ArenaLength/2)-2));
camera.lookAt(new newVector3((ArenaWidth/2)-2,0,(ArenaLength/2)-2));
;
document.onkeydown=function(e)
newGame(e.keyCode);
//listen to shake event
var shakeEvent = new Shake(threshold: 15);
shakeEvent.start();
window.addEventListener('shake', function()
newGame(82)
, false);
//stop listening
function stopShake()
shakeEvent.stop();
//check if shake is supported or not.
if(!("ondevicemotion" in window))alert("Not Supported");
gameOverDomStyle.opacity = 1;
function randomNumberBetween(a,b)
return a+floor(random()*(b-a));
var apple = new Apple(),
snake = new Snake()
var directionSwitch=
"forwards":function(a)this.nextHead = new Location(a[0]+1, a[1], a[2]),
"backwards":function(a)this.nextHead = new Location(a[0]-1, a[1], a[2]),
"left":function(a)this.nextHead = new Location(a[0], a[1], a[2]-1),
"right":function(a)this.nextHead = new Location(a[0], a[1], a[2]+1)
for(var x in directionSwitch)
directionSwitch[x] = directionSwitch[x].bind(snake)
var right =
"right":function()this.nextDirection = "backwards",
"backwards":function()this.nextDirection = "left",
"forwards":function()this.nextDirection = "right",
"left":function()this.nextDirection = "forwards"
for(var x in right)
right[x] = right[x].bind(snake)
var left =
"right":function()snake.nextDirection = "forwards",
"forwards":function()snake.nextDirection = "left",
"left":function()snake.nextDirection = "backwards",
"backwards":function()snake.nextDirection = "right"
for(var x in left)
left[x] = left[x].bind(snake)
var keyLookup =
"39":right,
"68":right,
"37":left,
"65":left,
"192":function()showlag=!showlag,
"55":function()showhighscore=!showhighscore,
"56":function()showmaxspeed = !showmaxspeed
snake.draw();
apple.move();
var background = new THREE.Color( "white" ),
fog = new THREE.FogExp2( "random", 0.02625 );
let s = function()
// Start for lag detection.
var start = performance.now();
// Make a fresh scene.
scene = new newScene();
// Move the snake.
snake.move();
// Render various things onto the scene.
scene.add(arenaWallMesh,arenaFloorMesh)
snake.draw();
apple.draw();
drawStats();
// Get relevent snake parts.
let head = snake.segments[0];
let nextHead = snake.nextHead;
// Set camera position and target.
camera.position.set(head[0],head[1],head[2]);
camera.lookAt(new newVector3(nextHead[0],nextHead[1],nextHead[2]));
// Set background and fog.
scene.background = background;
scene.fog = fog;
let end = performance.now();
// Reschedule the next update
gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed)
// End for lag detection and calculation of lag.
lagNum = floor((end-start))
animate()
var gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed);
document.onkeydown = function(e)
snake.changeDirection(e.keyCode);
)(window.THREE, (((window.innerWidth/10)|0)*10-2*10)/10, (((window.innerHeight/10)|0)*10-2*10)/10)
</script>
javascript ecmascript-6 dom snake-game
add a comment |Â
up vote
5
down vote
favorite
This is an iterative review of this question: 3D 1st Person Snake Game #1
The next iteration can be found here: 3D 1st Person Snake Game #3
Here is a snippet of the code:
<html>
<style>
canvas
position:fixed;
left:0;
top:0;
width:99%;
height:99%;
*
padding:0px;
margin:0px
#score,#speed,#highscore,#maxspeed,#lag,#debug
position: fixed;
z-index: 100;
font-size:20px;
font-family:Verdana;
left:15px;
width: 100%;
#gameover
position:absolute;
z-index: 100;
font-size:60px;
font-family:Verdana;
margin: 0;
top: 50%;
left: 50%;
opacity:0;
transform: translate(-50%, -50%);
#maxspeed, #score, #josh, #speed, #highscore, #lag
display:block;
#maxspeed
width: 100%;
top:50px;
display:none;
#score
top: 10px;
#speed
top: 30px;
#highscore
top:30px;
#lag
top: 70px;
</style>
<div id="stats">
<div id="debug"></div>
<div id="score">Score: 0</div>
<div id="speed">Speed: 1</div>
<div id="highscore">Highscore: 1</div>
<div id="maxspeed">Highest Speed: 1</div>
<span id="lag">Lag: 0ms</span>
<div id="gameover" align="center">Game Over</div>
</div>
<div id="canvas"></div>
<p id="p"></p>
<p id="e"></p>
<script type="text/javascript" src="https://cdn.rawgit.com/alexgibson/shake.js/master/shake.js"></script>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
//========================
// One times
//========================
const random = Math.random,
floor = function(a) return ~~a,
newGeometry = THREE.Geometry,
newBufferGeometry = THREE.BufferGeometry,
newMesh = THREE.Mesh,
newLineSegments = THREE.LineSegments,
newMeshBasicMaterial = THREE.MeshBasicMaterial,
newVector3 = THREE.Vector3,
newLineBasicMaterial = THREE.LineBasicMaterial,
newBoxGeometry = THREE.BoxGeometry,
newBoxBufferGeometry = THREE.BoxBufferGeometry,
arena = new THREE.Group(),
applegeometry = new THREE.SphereBufferGeometry( 0.5, 32, 32 ),
superapplematerial= new newMeshBasicMaterial(color:"gold"),
applematerial= new newMeshBasicMaterial(color:"limegreen"),
floormaterial = new newMeshBasicMaterial(color:"lightgrey"),
wallmaterial = new newMeshBasicMaterial( color: "grey" ),
linecube = new newBoxBufferGeometry( 1,1,1 ),
edges = new THREE.EdgesGeometry( linecube ),
geometry = new newBoxBufferGeometry( 1,1,1 ),
stringify = JSON.stringify
</script>
<script id="script">
(function(THREE,ArenaWidth, ArenaLength)
'use strict'
const arenaLines = new THREE.Group(),
arenaWall = new newGeometry(),
arenaFloor = new newGeometry(),
wall1 = new newBoxGeometry( ArenaWidth+1, 1, 1 )
.translate((ArenaWidth/2)-2,1,-2);
arenaWall.merge(wall1);
arenaWall.merge(wall1.translate(0,0, ArenaLength));
const wall2 = new newBoxGeometry( 1, 1, ArenaLength+1 ).translate(ArenaWidth-2,1,(ArenaLength/2)-2);
arenaWall.merge(wall2);
arenaWall.merge(wall2.translate(-ArenaWidth,0,0));
arenaFloor.merge(new newBoxGeometry( ArenaWidth+1, 1, ArenaLength+1 ).translate((ArenaWidth/2)-2,0,(ArenaLength/2)-2))
arenaWall.mergeVertices()
arenaFloor.mergeVertices()
// Get the meshs
window.arenaWallMesh = new newMesh(arenaWall, wallmaterial);
window.arenaFloorMesh = new newMesh(arenaFloor, floormaterial);
var speed = 100,
maxwidth = 40,
maxdepdth = 40,
size = 0.5,
score = 0,
maxheight = 0,
lagNum = 0,
highscoreNum,
showlag,
maxspeedNum,
showmaxspeed,
showhighscore
//========================
// Threejs
//========================
var scene = new THREE.Scene(),
camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,60),
renderer = new THREE.WebGLRenderer(),
extrasLookup =
1:30,
2:50,
3:70,
4:90
//========================
// Reductions
//========================
const newScene = THREE.Scene
if(true /*localStorage.getItem("3dhighscore")==undefined*/)
highscoreNum=0
else
highscoreNum = localStorage.getItem("3dhighscore")
if(true /*localStorage.getItem("showlag")==undefined*/)
showlag=false
else
showlag = localStorage.getItem("showlag")
if(true /*localStorage.getItem("3dmaxspeed")==undefined*/)
maxspeedNum=100
else
maxspeedNum = localStorage.getItem("3dmaxspeed")
if(showmaxspeed==undefined)
showmaxspeed=false
if(showhighscore==undefined)
showhighscore=false
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("canvas").appendChild( renderer.domElement );
function animate()
requestAnimationFrame( animate )
renderer.render( scene, camera );
class Location
constructor(x,y,z)
return [x,y,z]
//========================
// Dom
//========================
const maxSpeedDom = document.getElementById("maxspeed"),
maxSpeedDomStyle = maxSpeedDom.style,
lagdom = document.getElementById("lag"),
lagdomstyle = lagdom.style,
highScoreDom = document.getElementById("highscore"),
highScoreDomStyle = highScoreDom.style,
scoredom = document.getElementById("score"),
speeddom = document.getElementById("speed"),
gameOverDom = document.getElementById("gameover"),
gameOverDomStyle = gameOverDom.style;
//========================
// Snake
//========================
class Snake
constructor()
this.segments = [
new Location(7,1,5),
new Location(6,1,5),
new Location(5,1,5)
];
this.direction = "forwards";
this.nextDirection = "forwards";
this.nextHead = new Location(8,1,5);
draw()
let snakeobject = new THREE.Group();
let j = this.segments.length
this.segments.forEach((item,index) =>
let i = index
let segmentColor=`rgb($255-(255/j,00,00)`
const cube = new newMesh(geometry, new newMeshBasicMaterial( color: segmentColor)),
x = item[0],
y = item[1],
z = item[2];
let pos = new newVector3(x,y,z)
const line = new newLineSegments(edges, new newLineBasicMaterial( color: segmentColor,linewidth:2 ));
cube.position.copy(pos);
line.position.copy(pos);
snakeobject.add(line,cube);
)
scene.add(snakeobject);
move()
this.segments.unshift(this.nextHead);
if(this.checkCollision())
this.segments.shift();
gameOver();
return;
;
var nextHeadPos = this.nextHead;
this.direction = this.nextDirection;
(directionSwitch[this.direction])(nextHeadPos)
if(stringify(this.segments[0]) === stringify(apple.pos))
speed=0.95*speed;
score++;
if(apple.type === "superapple")
speed = 1.10*speed;
score += 4;
apple.move();
else
this.segments.pop();
;
changeDirection(key)
switch(key)
case 39:
case 68:
case 37:
case 65:
keyLookup[key][this.direction]()
break;
case 192:
case 55:
case 56:
keyLookup[key]()
break;
checkCollision()
//========================
// Drawing
//========================
function drawStats()
var extras = 1;
if(score > highscoreNum)
highscoreNum = score;
//localStorage.setItem("3dhighscore", highscore);
if(speed < maxspeed)
maxspeedNum = speed;
//localStorage.setItem("3dmaxspeed", maxspeed);
scoredom.innerHTML=`Score: $score`;
speeddom.innerHTML=`Speed: $(((100/speed*100)`;
if(showhighscore)
extras++;
highscore.style.display = "block";
highscore.style.top = extrasLookup[extras]
highscore.innerHTML = `Highscore: $highscoreNum`;
else
highScoreDomStyle.display = "none";
;
if(showmaxspeed)
extras++;
maxspeed.style.display = "block";
maxspeed.style.top = extrasLookup[extras]
maxspeed.innerHTML = `Highest Speed: $0)/100)`;
else
maxspeed.style.display = "none";
;
if(showlag)
extras++;
lag.style.display = "block";
lag.style.top = extrasLookup[extras]
lag.innerHTML = `Lag: $lagNumms`;
else
lagdomstyle.display = "none";
;
function renderArena()
;
//========================
// Apple
//========================
class Apple
constructor()
this.pos = new Location(2,1,2)
move()
// Set the location to a random x and z.
var x = randomNumberBetween(0,ArenaWidth-4)
var z = randomNumberBetween(0,ArenaLength-4)
this.pos = new Location(x,1,z)
if(randomNumberBetween(1,11)===1&&score>15)
apple.type="superapple"
else
apple.type="apple"
draw()
var sphere
// Generate a new sphere.
if(this.type=="superapple")
sphere = new newMesh( applegeometry, superapplematerial );
else
sphere = new newMesh( applegeometry, applematerial );
// Get the data location.
var applepos=apple.pos
// Set the location of the visual apple to the data location.
sphere.position.set(applepos[0],applepos[1],applepos[2])
scene.add(sphere);
//========================
// Misc
//========================
function newGame(key)
if(key==82)
// Stop the game.
clearTimeout(gameLoop);
s=function();
// Start a new game.
var game = document.getElementById("canvas");
game.removeChild(game.childNodes[0]);
eval(document.getElementById("script").innerHTML);
gameOverDomStyle.opacity=0;
function gameOver()
s = function()
camera.position.copy(new newVector3((ArenaWidth/2)-2,Math.sqrt(
Math.pow(ArenaWidth/2,2)+Math.pow(ArenaLength/2,2)),(ArenaLength/2)-2));
camera.lookAt(new newVector3((ArenaWidth/2)-2,0,(ArenaLength/2)-2));
;
document.onkeydown=function(e)
newGame(e.keyCode);
//listen to shake event
var shakeEvent = new Shake(threshold: 15);
shakeEvent.start();
window.addEventListener('shake', function()
newGame(82)
, false);
//stop listening
function stopShake()
shakeEvent.stop();
//check if shake is supported or not.
if(!("ondevicemotion" in window))alert("Not Supported");
gameOverDomStyle.opacity = 1;
function randomNumberBetween(a,b)
return a+floor(random()*(b-a));
var apple = new Apple(),
snake = new Snake()
var directionSwitch=
"forwards":function(a)this.nextHead = new Location(a[0]+1, a[1], a[2]),
"backwards":function(a)this.nextHead = new Location(a[0]-1, a[1], a[2]),
"left":function(a)this.nextHead = new Location(a[0], a[1], a[2]-1),
"right":function(a)this.nextHead = new Location(a[0], a[1], a[2]+1)
for(var x in directionSwitch)
directionSwitch[x] = directionSwitch[x].bind(snake)
var right =
"right":function()this.nextDirection = "backwards",
"backwards":function()this.nextDirection = "left",
"forwards":function()this.nextDirection = "right",
"left":function()this.nextDirection = "forwards"
for(var x in right)
right[x] = right[x].bind(snake)
var left =
"right":function()snake.nextDirection = "forwards",
"forwards":function()snake.nextDirection = "left",
"left":function()snake.nextDirection = "backwards",
"backwards":function()snake.nextDirection = "right"
for(var x in left)
left[x] = left[x].bind(snake)
var keyLookup =
"39":right,
"68":right,
"37":left,
"65":left,
"192":function()showlag=!showlag,
"55":function()showhighscore=!showhighscore,
"56":function()showmaxspeed = !showmaxspeed
snake.draw();
apple.move();
var background = new THREE.Color( "white" ),
fog = new THREE.FogExp2( "random", 0.02625 );
let s = function()
// Start for lag detection.
var start = performance.now();
// Make a fresh scene.
scene = new newScene();
// Move the snake.
snake.move();
// Render various things onto the scene.
scene.add(arenaWallMesh,arenaFloorMesh)
snake.draw();
apple.draw();
drawStats();
// Get relevent snake parts.
let head = snake.segments[0];
let nextHead = snake.nextHead;
// Set camera position and target.
camera.position.set(head[0],head[1],head[2]);
camera.lookAt(new newVector3(nextHead[0],nextHead[1],nextHead[2]));
// Set background and fog.
scene.background = background;
scene.fog = fog;
let end = performance.now();
// Reschedule the next update
gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed)
// End for lag detection and calculation of lag.
lagNum = floor((end-start))
animate()
var gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed);
document.onkeydown = function(e)
snake.changeDirection(e.keyCode);
)(window.THREE, (((window.innerWidth/10)|0)*10-2*10)/10, (((window.innerHeight/10)|0)*10-2*10)/10)
</script>
javascript ecmascript-6 dom snake-game
Note: For the snippet, click "run", "Full page", purposely lose, and then click "r". Unfortunately the snippet makes the game small...
â FreezePhoenix
May 14 at 16:49
2
Oh maaan. It's so hard to play. Sorry, now got zero time to write an actual review! i.stack.imgur.com/gfiZi.png
â Igor Soloydenko
May 14 at 18:02
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
This is an iterative review of this question: 3D 1st Person Snake Game #1
The next iteration can be found here: 3D 1st Person Snake Game #3
Here is a snippet of the code:
<html>
<style>
canvas
position:fixed;
left:0;
top:0;
width:99%;
height:99%;
*
padding:0px;
margin:0px
#score,#speed,#highscore,#maxspeed,#lag,#debug
position: fixed;
z-index: 100;
font-size:20px;
font-family:Verdana;
left:15px;
width: 100%;
#gameover
position:absolute;
z-index: 100;
font-size:60px;
font-family:Verdana;
margin: 0;
top: 50%;
left: 50%;
opacity:0;
transform: translate(-50%, -50%);
#maxspeed, #score, #josh, #speed, #highscore, #lag
display:block;
#maxspeed
width: 100%;
top:50px;
display:none;
#score
top: 10px;
#speed
top: 30px;
#highscore
top:30px;
#lag
top: 70px;
</style>
<div id="stats">
<div id="debug"></div>
<div id="score">Score: 0</div>
<div id="speed">Speed: 1</div>
<div id="highscore">Highscore: 1</div>
<div id="maxspeed">Highest Speed: 1</div>
<span id="lag">Lag: 0ms</span>
<div id="gameover" align="center">Game Over</div>
</div>
<div id="canvas"></div>
<p id="p"></p>
<p id="e"></p>
<script type="text/javascript" src="https://cdn.rawgit.com/alexgibson/shake.js/master/shake.js"></script>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
//========================
// One times
//========================
const random = Math.random,
floor = function(a) return ~~a,
newGeometry = THREE.Geometry,
newBufferGeometry = THREE.BufferGeometry,
newMesh = THREE.Mesh,
newLineSegments = THREE.LineSegments,
newMeshBasicMaterial = THREE.MeshBasicMaterial,
newVector3 = THREE.Vector3,
newLineBasicMaterial = THREE.LineBasicMaterial,
newBoxGeometry = THREE.BoxGeometry,
newBoxBufferGeometry = THREE.BoxBufferGeometry,
arena = new THREE.Group(),
applegeometry = new THREE.SphereBufferGeometry( 0.5, 32, 32 ),
superapplematerial= new newMeshBasicMaterial(color:"gold"),
applematerial= new newMeshBasicMaterial(color:"limegreen"),
floormaterial = new newMeshBasicMaterial(color:"lightgrey"),
wallmaterial = new newMeshBasicMaterial( color: "grey" ),
linecube = new newBoxBufferGeometry( 1,1,1 ),
edges = new THREE.EdgesGeometry( linecube ),
geometry = new newBoxBufferGeometry( 1,1,1 ),
stringify = JSON.stringify
</script>
<script id="script">
(function(THREE,ArenaWidth, ArenaLength)
'use strict'
const arenaLines = new THREE.Group(),
arenaWall = new newGeometry(),
arenaFloor = new newGeometry(),
wall1 = new newBoxGeometry( ArenaWidth+1, 1, 1 )
.translate((ArenaWidth/2)-2,1,-2);
arenaWall.merge(wall1);
arenaWall.merge(wall1.translate(0,0, ArenaLength));
const wall2 = new newBoxGeometry( 1, 1, ArenaLength+1 ).translate(ArenaWidth-2,1,(ArenaLength/2)-2);
arenaWall.merge(wall2);
arenaWall.merge(wall2.translate(-ArenaWidth,0,0));
arenaFloor.merge(new newBoxGeometry( ArenaWidth+1, 1, ArenaLength+1 ).translate((ArenaWidth/2)-2,0,(ArenaLength/2)-2))
arenaWall.mergeVertices()
arenaFloor.mergeVertices()
// Get the meshs
window.arenaWallMesh = new newMesh(arenaWall, wallmaterial);
window.arenaFloorMesh = new newMesh(arenaFloor, floormaterial);
var speed = 100,
maxwidth = 40,
maxdepdth = 40,
size = 0.5,
score = 0,
maxheight = 0,
lagNum = 0,
highscoreNum,
showlag,
maxspeedNum,
showmaxspeed,
showhighscore
//========================
// Threejs
//========================
var scene = new THREE.Scene(),
camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,60),
renderer = new THREE.WebGLRenderer(),
extrasLookup =
1:30,
2:50,
3:70,
4:90
//========================
// Reductions
//========================
const newScene = THREE.Scene
if(true /*localStorage.getItem("3dhighscore")==undefined*/)
highscoreNum=0
else
highscoreNum = localStorage.getItem("3dhighscore")
if(true /*localStorage.getItem("showlag")==undefined*/)
showlag=false
else
showlag = localStorage.getItem("showlag")
if(true /*localStorage.getItem("3dmaxspeed")==undefined*/)
maxspeedNum=100
else
maxspeedNum = localStorage.getItem("3dmaxspeed")
if(showmaxspeed==undefined)
showmaxspeed=false
if(showhighscore==undefined)
showhighscore=false
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("canvas").appendChild( renderer.domElement );
function animate()
requestAnimationFrame( animate )
renderer.render( scene, camera );
class Location
constructor(x,y,z)
return [x,y,z]
//========================
// Dom
//========================
const maxSpeedDom = document.getElementById("maxspeed"),
maxSpeedDomStyle = maxSpeedDom.style,
lagdom = document.getElementById("lag"),
lagdomstyle = lagdom.style,
highScoreDom = document.getElementById("highscore"),
highScoreDomStyle = highScoreDom.style,
scoredom = document.getElementById("score"),
speeddom = document.getElementById("speed"),
gameOverDom = document.getElementById("gameover"),
gameOverDomStyle = gameOverDom.style;
//========================
// Snake
//========================
class Snake
constructor()
this.segments = [
new Location(7,1,5),
new Location(6,1,5),
new Location(5,1,5)
];
this.direction = "forwards";
this.nextDirection = "forwards";
this.nextHead = new Location(8,1,5);
draw()
let snakeobject = new THREE.Group();
let j = this.segments.length
this.segments.forEach((item,index) =>
let i = index
let segmentColor=`rgb($255-(255/j,00,00)`
const cube = new newMesh(geometry, new newMeshBasicMaterial( color: segmentColor)),
x = item[0],
y = item[1],
z = item[2];
let pos = new newVector3(x,y,z)
const line = new newLineSegments(edges, new newLineBasicMaterial( color: segmentColor,linewidth:2 ));
cube.position.copy(pos);
line.position.copy(pos);
snakeobject.add(line,cube);
)
scene.add(snakeobject);
move()
this.segments.unshift(this.nextHead);
if(this.checkCollision())
this.segments.shift();
gameOver();
return;
;
var nextHeadPos = this.nextHead;
this.direction = this.nextDirection;
(directionSwitch[this.direction])(nextHeadPos)
if(stringify(this.segments[0]) === stringify(apple.pos))
speed=0.95*speed;
score++;
if(apple.type === "superapple")
speed = 1.10*speed;
score += 4;
apple.move();
else
this.segments.pop();
;
changeDirection(key)
switch(key)
case 39:
case 68:
case 37:
case 65:
keyLookup[key][this.direction]()
break;
case 192:
case 55:
case 56:
keyLookup[key]()
break;
checkCollision()
//========================
// Drawing
//========================
function drawStats()
var extras = 1;
if(score > highscoreNum)
highscoreNum = score;
//localStorage.setItem("3dhighscore", highscore);
if(speed < maxspeed)
maxspeedNum = speed;
//localStorage.setItem("3dmaxspeed", maxspeed);
scoredom.innerHTML=`Score: $score`;
speeddom.innerHTML=`Speed: $(((100/speed*100)`;
if(showhighscore)
extras++;
highscore.style.display = "block";
highscore.style.top = extrasLookup[extras]
highscore.innerHTML = `Highscore: $highscoreNum`;
else
highScoreDomStyle.display = "none";
;
if(showmaxspeed)
extras++;
maxspeed.style.display = "block";
maxspeed.style.top = extrasLookup[extras]
maxspeed.innerHTML = `Highest Speed: $0)/100)`;
else
maxspeed.style.display = "none";
;
if(showlag)
extras++;
lag.style.display = "block";
lag.style.top = extrasLookup[extras]
lag.innerHTML = `Lag: $lagNumms`;
else
lagdomstyle.display = "none";
;
function renderArena()
;
//========================
// Apple
//========================
class Apple
constructor()
this.pos = new Location(2,1,2)
move()
// Set the location to a random x and z.
var x = randomNumberBetween(0,ArenaWidth-4)
var z = randomNumberBetween(0,ArenaLength-4)
this.pos = new Location(x,1,z)
if(randomNumberBetween(1,11)===1&&score>15)
apple.type="superapple"
else
apple.type="apple"
draw()
var sphere
// Generate a new sphere.
if(this.type=="superapple")
sphere = new newMesh( applegeometry, superapplematerial );
else
sphere = new newMesh( applegeometry, applematerial );
// Get the data location.
var applepos=apple.pos
// Set the location of the visual apple to the data location.
sphere.position.set(applepos[0],applepos[1],applepos[2])
scene.add(sphere);
//========================
// Misc
//========================
function newGame(key)
if(key==82)
// Stop the game.
clearTimeout(gameLoop);
s=function();
// Start a new game.
var game = document.getElementById("canvas");
game.removeChild(game.childNodes[0]);
eval(document.getElementById("script").innerHTML);
gameOverDomStyle.opacity=0;
function gameOver()
s = function()
camera.position.copy(new newVector3((ArenaWidth/2)-2,Math.sqrt(
Math.pow(ArenaWidth/2,2)+Math.pow(ArenaLength/2,2)),(ArenaLength/2)-2));
camera.lookAt(new newVector3((ArenaWidth/2)-2,0,(ArenaLength/2)-2));
;
document.onkeydown=function(e)
newGame(e.keyCode);
//listen to shake event
var shakeEvent = new Shake(threshold: 15);
shakeEvent.start();
window.addEventListener('shake', function()
newGame(82)
, false);
//stop listening
function stopShake()
shakeEvent.stop();
//check if shake is supported or not.
if(!("ondevicemotion" in window))alert("Not Supported");
gameOverDomStyle.opacity = 1;
function randomNumberBetween(a,b)
return a+floor(random()*(b-a));
var apple = new Apple(),
snake = new Snake()
var directionSwitch=
"forwards":function(a)this.nextHead = new Location(a[0]+1, a[1], a[2]),
"backwards":function(a)this.nextHead = new Location(a[0]-1, a[1], a[2]),
"left":function(a)this.nextHead = new Location(a[0], a[1], a[2]-1),
"right":function(a)this.nextHead = new Location(a[0], a[1], a[2]+1)
for(var x in directionSwitch)
directionSwitch[x] = directionSwitch[x].bind(snake)
var right =
"right":function()this.nextDirection = "backwards",
"backwards":function()this.nextDirection = "left",
"forwards":function()this.nextDirection = "right",
"left":function()this.nextDirection = "forwards"
for(var x in right)
right[x] = right[x].bind(snake)
var left =
"right":function()snake.nextDirection = "forwards",
"forwards":function()snake.nextDirection = "left",
"left":function()snake.nextDirection = "backwards",
"backwards":function()snake.nextDirection = "right"
for(var x in left)
left[x] = left[x].bind(snake)
var keyLookup =
"39":right,
"68":right,
"37":left,
"65":left,
"192":function()showlag=!showlag,
"55":function()showhighscore=!showhighscore,
"56":function()showmaxspeed = !showmaxspeed
snake.draw();
apple.move();
var background = new THREE.Color( "white" ),
fog = new THREE.FogExp2( "random", 0.02625 );
let s = function()
// Start for lag detection.
var start = performance.now();
// Make a fresh scene.
scene = new newScene();
// Move the snake.
snake.move();
// Render various things onto the scene.
scene.add(arenaWallMesh,arenaFloorMesh)
snake.draw();
apple.draw();
drawStats();
// Get relevent snake parts.
let head = snake.segments[0];
let nextHead = snake.nextHead;
// Set camera position and target.
camera.position.set(head[0],head[1],head[2]);
camera.lookAt(new newVector3(nextHead[0],nextHead[1],nextHead[2]));
// Set background and fog.
scene.background = background;
scene.fog = fog;
let end = performance.now();
// Reschedule the next update
gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed)
// End for lag detection and calculation of lag.
lagNum = floor((end-start))
animate()
var gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed);
document.onkeydown = function(e)
snake.changeDirection(e.keyCode);
)(window.THREE, (((window.innerWidth/10)|0)*10-2*10)/10, (((window.innerHeight/10)|0)*10-2*10)/10)
</script>
javascript ecmascript-6 dom snake-game
This is an iterative review of this question: 3D 1st Person Snake Game #1
The next iteration can be found here: 3D 1st Person Snake Game #3
Here is a snippet of the code:
<html>
<style>
canvas
position:fixed;
left:0;
top:0;
width:99%;
height:99%;
*
padding:0px;
margin:0px
#score,#speed,#highscore,#maxspeed,#lag,#debug
position: fixed;
z-index: 100;
font-size:20px;
font-family:Verdana;
left:15px;
width: 100%;
#gameover
position:absolute;
z-index: 100;
font-size:60px;
font-family:Verdana;
margin: 0;
top: 50%;
left: 50%;
opacity:0;
transform: translate(-50%, -50%);
#maxspeed, #score, #josh, #speed, #highscore, #lag
display:block;
#maxspeed
width: 100%;
top:50px;
display:none;
#score
top: 10px;
#speed
top: 30px;
#highscore
top:30px;
#lag
top: 70px;
</style>
<div id="stats">
<div id="debug"></div>
<div id="score">Score: 0</div>
<div id="speed">Speed: 1</div>
<div id="highscore">Highscore: 1</div>
<div id="maxspeed">Highest Speed: 1</div>
<span id="lag">Lag: 0ms</span>
<div id="gameover" align="center">Game Over</div>
</div>
<div id="canvas"></div>
<p id="p"></p>
<p id="e"></p>
<script type="text/javascript" src="https://cdn.rawgit.com/alexgibson/shake.js/master/shake.js"></script>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
//========================
// One times
//========================
const random = Math.random,
floor = function(a) return ~~a,
newGeometry = THREE.Geometry,
newBufferGeometry = THREE.BufferGeometry,
newMesh = THREE.Mesh,
newLineSegments = THREE.LineSegments,
newMeshBasicMaterial = THREE.MeshBasicMaterial,
newVector3 = THREE.Vector3,
newLineBasicMaterial = THREE.LineBasicMaterial,
newBoxGeometry = THREE.BoxGeometry,
newBoxBufferGeometry = THREE.BoxBufferGeometry,
arena = new THREE.Group(),
applegeometry = new THREE.SphereBufferGeometry( 0.5, 32, 32 ),
superapplematerial= new newMeshBasicMaterial(color:"gold"),
applematerial= new newMeshBasicMaterial(color:"limegreen"),
floormaterial = new newMeshBasicMaterial(color:"lightgrey"),
wallmaterial = new newMeshBasicMaterial( color: "grey" ),
linecube = new newBoxBufferGeometry( 1,1,1 ),
edges = new THREE.EdgesGeometry( linecube ),
geometry = new newBoxBufferGeometry( 1,1,1 ),
stringify = JSON.stringify
</script>
<script id="script">
(function(THREE,ArenaWidth, ArenaLength)
'use strict'
const arenaLines = new THREE.Group(),
arenaWall = new newGeometry(),
arenaFloor = new newGeometry(),
wall1 = new newBoxGeometry( ArenaWidth+1, 1, 1 )
.translate((ArenaWidth/2)-2,1,-2);
arenaWall.merge(wall1);
arenaWall.merge(wall1.translate(0,0, ArenaLength));
const wall2 = new newBoxGeometry( 1, 1, ArenaLength+1 ).translate(ArenaWidth-2,1,(ArenaLength/2)-2);
arenaWall.merge(wall2);
arenaWall.merge(wall2.translate(-ArenaWidth,0,0));
arenaFloor.merge(new newBoxGeometry( ArenaWidth+1, 1, ArenaLength+1 ).translate((ArenaWidth/2)-2,0,(ArenaLength/2)-2))
arenaWall.mergeVertices()
arenaFloor.mergeVertices()
// Get the meshs
window.arenaWallMesh = new newMesh(arenaWall, wallmaterial);
window.arenaFloorMesh = new newMesh(arenaFloor, floormaterial);
var speed = 100,
maxwidth = 40,
maxdepdth = 40,
size = 0.5,
score = 0,
maxheight = 0,
lagNum = 0,
highscoreNum,
showlag,
maxspeedNum,
showmaxspeed,
showhighscore
//========================
// Threejs
//========================
var scene = new THREE.Scene(),
camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,60),
renderer = new THREE.WebGLRenderer(),
extrasLookup =
1:30,
2:50,
3:70,
4:90
//========================
// Reductions
//========================
const newScene = THREE.Scene
if(true /*localStorage.getItem("3dhighscore")==undefined*/)
highscoreNum=0
else
highscoreNum = localStorage.getItem("3dhighscore")
if(true /*localStorage.getItem("showlag")==undefined*/)
showlag=false
else
showlag = localStorage.getItem("showlag")
if(true /*localStorage.getItem("3dmaxspeed")==undefined*/)
maxspeedNum=100
else
maxspeedNum = localStorage.getItem("3dmaxspeed")
if(showmaxspeed==undefined)
showmaxspeed=false
if(showhighscore==undefined)
showhighscore=false
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("canvas").appendChild( renderer.domElement );
function animate()
requestAnimationFrame( animate )
renderer.render( scene, camera );
class Location
constructor(x,y,z)
return [x,y,z]
//========================
// Dom
//========================
const maxSpeedDom = document.getElementById("maxspeed"),
maxSpeedDomStyle = maxSpeedDom.style,
lagdom = document.getElementById("lag"),
lagdomstyle = lagdom.style,
highScoreDom = document.getElementById("highscore"),
highScoreDomStyle = highScoreDom.style,
scoredom = document.getElementById("score"),
speeddom = document.getElementById("speed"),
gameOverDom = document.getElementById("gameover"),
gameOverDomStyle = gameOverDom.style;
//========================
// Snake
//========================
class Snake
constructor()
this.segments = [
new Location(7,1,5),
new Location(6,1,5),
new Location(5,1,5)
];
this.direction = "forwards";
this.nextDirection = "forwards";
this.nextHead = new Location(8,1,5);
draw()
let snakeobject = new THREE.Group();
let j = this.segments.length
this.segments.forEach((item,index) =>
let i = index
let segmentColor=`rgb($255-(255/j,00,00)`
const cube = new newMesh(geometry, new newMeshBasicMaterial( color: segmentColor)),
x = item[0],
y = item[1],
z = item[2];
let pos = new newVector3(x,y,z)
const line = new newLineSegments(edges, new newLineBasicMaterial( color: segmentColor,linewidth:2 ));
cube.position.copy(pos);
line.position.copy(pos);
snakeobject.add(line,cube);
)
scene.add(snakeobject);
move()
this.segments.unshift(this.nextHead);
if(this.checkCollision())
this.segments.shift();
gameOver();
return;
;
var nextHeadPos = this.nextHead;
this.direction = this.nextDirection;
(directionSwitch[this.direction])(nextHeadPos)
if(stringify(this.segments[0]) === stringify(apple.pos))
speed=0.95*speed;
score++;
if(apple.type === "superapple")
speed = 1.10*speed;
score += 4;
apple.move();
else
this.segments.pop();
;
changeDirection(key)
switch(key)
case 39:
case 68:
case 37:
case 65:
keyLookup[key][this.direction]()
break;
case 192:
case 55:
case 56:
keyLookup[key]()
break;
checkCollision()
//========================
// Drawing
//========================
function drawStats()
var extras = 1;
if(score > highscoreNum)
highscoreNum = score;
//localStorage.setItem("3dhighscore", highscore);
if(speed < maxspeed)
maxspeedNum = speed;
//localStorage.setItem("3dmaxspeed", maxspeed);
scoredom.innerHTML=`Score: $score`;
speeddom.innerHTML=`Speed: $(((100/speed*100)`;
if(showhighscore)
extras++;
highscore.style.display = "block";
highscore.style.top = extrasLookup[extras]
highscore.innerHTML = `Highscore: $highscoreNum`;
else
highScoreDomStyle.display = "none";
;
if(showmaxspeed)
extras++;
maxspeed.style.display = "block";
maxspeed.style.top = extrasLookup[extras]
maxspeed.innerHTML = `Highest Speed: $0)/100)`;
else
maxspeed.style.display = "none";
;
if(showlag)
extras++;
lag.style.display = "block";
lag.style.top = extrasLookup[extras]
lag.innerHTML = `Lag: $lagNumms`;
else
lagdomstyle.display = "none";
;
function renderArena()
;
//========================
// Apple
//========================
class Apple
constructor()
this.pos = new Location(2,1,2)
move()
// Set the location to a random x and z.
var x = randomNumberBetween(0,ArenaWidth-4)
var z = randomNumberBetween(0,ArenaLength-4)
this.pos = new Location(x,1,z)
if(randomNumberBetween(1,11)===1&&score>15)
apple.type="superapple"
else
apple.type="apple"
draw()
var sphere
// Generate a new sphere.
if(this.type=="superapple")
sphere = new newMesh( applegeometry, superapplematerial );
else
sphere = new newMesh( applegeometry, applematerial );
// Get the data location.
var applepos=apple.pos
// Set the location of the visual apple to the data location.
sphere.position.set(applepos[0],applepos[1],applepos[2])
scene.add(sphere);
//========================
// Misc
//========================
function newGame(key)
if(key==82)
// Stop the game.
clearTimeout(gameLoop);
s=function();
// Start a new game.
var game = document.getElementById("canvas");
game.removeChild(game.childNodes[0]);
eval(document.getElementById("script").innerHTML);
gameOverDomStyle.opacity=0;
function gameOver()
s = function()
camera.position.copy(new newVector3((ArenaWidth/2)-2,Math.sqrt(
Math.pow(ArenaWidth/2,2)+Math.pow(ArenaLength/2,2)),(ArenaLength/2)-2));
camera.lookAt(new newVector3((ArenaWidth/2)-2,0,(ArenaLength/2)-2));
;
document.onkeydown=function(e)
newGame(e.keyCode);
//listen to shake event
var shakeEvent = new Shake(threshold: 15);
shakeEvent.start();
window.addEventListener('shake', function()
newGame(82)
, false);
//stop listening
function stopShake()
shakeEvent.stop();
//check if shake is supported or not.
if(!("ondevicemotion" in window))alert("Not Supported");
gameOverDomStyle.opacity = 1;
function randomNumberBetween(a,b)
return a+floor(random()*(b-a));
var apple = new Apple(),
snake = new Snake()
var directionSwitch=
"forwards":function(a)this.nextHead = new Location(a[0]+1, a[1], a[2]),
"backwards":function(a)this.nextHead = new Location(a[0]-1, a[1], a[2]),
"left":function(a)this.nextHead = new Location(a[0], a[1], a[2]-1),
"right":function(a)this.nextHead = new Location(a[0], a[1], a[2]+1)
for(var x in directionSwitch)
directionSwitch[x] = directionSwitch[x].bind(snake)
var right =
"right":function()this.nextDirection = "backwards",
"backwards":function()this.nextDirection = "left",
"forwards":function()this.nextDirection = "right",
"left":function()this.nextDirection = "forwards"
for(var x in right)
right[x] = right[x].bind(snake)
var left =
"right":function()snake.nextDirection = "forwards",
"forwards":function()snake.nextDirection = "left",
"left":function()snake.nextDirection = "backwards",
"backwards":function()snake.nextDirection = "right"
for(var x in left)
left[x] = left[x].bind(snake)
var keyLookup =
"39":right,
"68":right,
"37":left,
"65":left,
"192":function()showlag=!showlag,
"55":function()showhighscore=!showhighscore,
"56":function()showmaxspeed = !showmaxspeed
snake.draw();
apple.move();
var background = new THREE.Color( "white" ),
fog = new THREE.FogExp2( "random", 0.02625 );
let s = function()
// Start for lag detection.
var start = performance.now();
// Make a fresh scene.
scene = new newScene();
// Move the snake.
snake.move();
// Render various things onto the scene.
scene.add(arenaWallMesh,arenaFloorMesh)
snake.draw();
apple.draw();
drawStats();
// Get relevent snake parts.
let head = snake.segments[0];
let nextHead = snake.nextHead;
// Set camera position and target.
camera.position.set(head[0],head[1],head[2]);
camera.lookAt(new newVector3(nextHead[0],nextHead[1],nextHead[2]));
// Set background and fog.
scene.background = background;
scene.fog = fog;
let end = performance.now();
// Reschedule the next update
gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed)
// End for lag detection and calculation of lag.
lagNum = floor((end-start))
animate()
var gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed);
document.onkeydown = function(e)
snake.changeDirection(e.keyCode);
)(window.THREE, (((window.innerWidth/10)|0)*10-2*10)/10, (((window.innerHeight/10)|0)*10-2*10)/10)
</script>
<html>
<style>
canvas
position:fixed;
left:0;
top:0;
width:99%;
height:99%;
*
padding:0px;
margin:0px
#score,#speed,#highscore,#maxspeed,#lag,#debug
position: fixed;
z-index: 100;
font-size:20px;
font-family:Verdana;
left:15px;
width: 100%;
#gameover
position:absolute;
z-index: 100;
font-size:60px;
font-family:Verdana;
margin: 0;
top: 50%;
left: 50%;
opacity:0;
transform: translate(-50%, -50%);
#maxspeed, #score, #josh, #speed, #highscore, #lag
display:block;
#maxspeed
width: 100%;
top:50px;
display:none;
#score
top: 10px;
#speed
top: 30px;
#highscore
top:30px;
#lag
top: 70px;
</style>
<div id="stats">
<div id="debug"></div>
<div id="score">Score: 0</div>
<div id="speed">Speed: 1</div>
<div id="highscore">Highscore: 1</div>
<div id="maxspeed">Highest Speed: 1</div>
<span id="lag">Lag: 0ms</span>
<div id="gameover" align="center">Game Over</div>
</div>
<div id="canvas"></div>
<p id="p"></p>
<p id="e"></p>
<script type="text/javascript" src="https://cdn.rawgit.com/alexgibson/shake.js/master/shake.js"></script>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
//========================
// One times
//========================
const random = Math.random,
floor = function(a) return ~~a,
newGeometry = THREE.Geometry,
newBufferGeometry = THREE.BufferGeometry,
newMesh = THREE.Mesh,
newLineSegments = THREE.LineSegments,
newMeshBasicMaterial = THREE.MeshBasicMaterial,
newVector3 = THREE.Vector3,
newLineBasicMaterial = THREE.LineBasicMaterial,
newBoxGeometry = THREE.BoxGeometry,
newBoxBufferGeometry = THREE.BoxBufferGeometry,
arena = new THREE.Group(),
applegeometry = new THREE.SphereBufferGeometry( 0.5, 32, 32 ),
superapplematerial= new newMeshBasicMaterial(color:"gold"),
applematerial= new newMeshBasicMaterial(color:"limegreen"),
floormaterial = new newMeshBasicMaterial(color:"lightgrey"),
wallmaterial = new newMeshBasicMaterial( color: "grey" ),
linecube = new newBoxBufferGeometry( 1,1,1 ),
edges = new THREE.EdgesGeometry( linecube ),
geometry = new newBoxBufferGeometry( 1,1,1 ),
stringify = JSON.stringify
</script>
<script id="script">
(function(THREE,ArenaWidth, ArenaLength)
'use strict'
const arenaLines = new THREE.Group(),
arenaWall = new newGeometry(),
arenaFloor = new newGeometry(),
wall1 = new newBoxGeometry( ArenaWidth+1, 1, 1 )
.translate((ArenaWidth/2)-2,1,-2);
arenaWall.merge(wall1);
arenaWall.merge(wall1.translate(0,0, ArenaLength));
const wall2 = new newBoxGeometry( 1, 1, ArenaLength+1 ).translate(ArenaWidth-2,1,(ArenaLength/2)-2);
arenaWall.merge(wall2);
arenaWall.merge(wall2.translate(-ArenaWidth,0,0));
arenaFloor.merge(new newBoxGeometry( ArenaWidth+1, 1, ArenaLength+1 ).translate((ArenaWidth/2)-2,0,(ArenaLength/2)-2))
arenaWall.mergeVertices()
arenaFloor.mergeVertices()
// Get the meshs
window.arenaWallMesh = new newMesh(arenaWall, wallmaterial);
window.arenaFloorMesh = new newMesh(arenaFloor, floormaterial);
var speed = 100,
maxwidth = 40,
maxdepdth = 40,
size = 0.5,
score = 0,
maxheight = 0,
lagNum = 0,
highscoreNum,
showlag,
maxspeedNum,
showmaxspeed,
showhighscore
//========================
// Threejs
//========================
var scene = new THREE.Scene(),
camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,60),
renderer = new THREE.WebGLRenderer(),
extrasLookup =
1:30,
2:50,
3:70,
4:90
//========================
// Reductions
//========================
const newScene = THREE.Scene
if(true /*localStorage.getItem("3dhighscore")==undefined*/)
highscoreNum=0
else
highscoreNum = localStorage.getItem("3dhighscore")
if(true /*localStorage.getItem("showlag")==undefined*/)
showlag=false
else
showlag = localStorage.getItem("showlag")
if(true /*localStorage.getItem("3dmaxspeed")==undefined*/)
maxspeedNum=100
else
maxspeedNum = localStorage.getItem("3dmaxspeed")
if(showmaxspeed==undefined)
showmaxspeed=false
if(showhighscore==undefined)
showhighscore=false
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("canvas").appendChild( renderer.domElement );
function animate()
requestAnimationFrame( animate )
renderer.render( scene, camera );
class Location
constructor(x,y,z)
return [x,y,z]
//========================
// Dom
//========================
const maxSpeedDom = document.getElementById("maxspeed"),
maxSpeedDomStyle = maxSpeedDom.style,
lagdom = document.getElementById("lag"),
lagdomstyle = lagdom.style,
highScoreDom = document.getElementById("highscore"),
highScoreDomStyle = highScoreDom.style,
scoredom = document.getElementById("score"),
speeddom = document.getElementById("speed"),
gameOverDom = document.getElementById("gameover"),
gameOverDomStyle = gameOverDom.style;
//========================
// Snake
//========================
class Snake
constructor()
this.segments = [
new Location(7,1,5),
new Location(6,1,5),
new Location(5,1,5)
];
this.direction = "forwards";
this.nextDirection = "forwards";
this.nextHead = new Location(8,1,5);
draw()
let snakeobject = new THREE.Group();
let j = this.segments.length
this.segments.forEach((item,index) =>
let i = index
let segmentColor=`rgb($255-(255/j,00,00)`
const cube = new newMesh(geometry, new newMeshBasicMaterial( color: segmentColor)),
x = item[0],
y = item[1],
z = item[2];
let pos = new newVector3(x,y,z)
const line = new newLineSegments(edges, new newLineBasicMaterial( color: segmentColor,linewidth:2 ));
cube.position.copy(pos);
line.position.copy(pos);
snakeobject.add(line,cube);
)
scene.add(snakeobject);
move()
this.segments.unshift(this.nextHead);
if(this.checkCollision())
this.segments.shift();
gameOver();
return;
;
var nextHeadPos = this.nextHead;
this.direction = this.nextDirection;
(directionSwitch[this.direction])(nextHeadPos)
if(stringify(this.segments[0]) === stringify(apple.pos))
speed=0.95*speed;
score++;
if(apple.type === "superapple")
speed = 1.10*speed;
score += 4;
apple.move();
else
this.segments.pop();
;
changeDirection(key)
switch(key)
case 39:
case 68:
case 37:
case 65:
keyLookup[key][this.direction]()
break;
case 192:
case 55:
case 56:
keyLookup[key]()
break;
checkCollision()
//========================
// Drawing
//========================
function drawStats()
var extras = 1;
if(score > highscoreNum)
highscoreNum = score;
//localStorage.setItem("3dhighscore", highscore);
if(speed < maxspeed)
maxspeedNum = speed;
//localStorage.setItem("3dmaxspeed", maxspeed);
scoredom.innerHTML=`Score: $score`;
speeddom.innerHTML=`Speed: $(((100/speed*100)`;
if(showhighscore)
extras++;
highscore.style.display = "block";
highscore.style.top = extrasLookup[extras]
highscore.innerHTML = `Highscore: $highscoreNum`;
else
highScoreDomStyle.display = "none";
;
if(showmaxspeed)
extras++;
maxspeed.style.display = "block";
maxspeed.style.top = extrasLookup[extras]
maxspeed.innerHTML = `Highest Speed: $0)/100)`;
else
maxspeed.style.display = "none";
;
if(showlag)
extras++;
lag.style.display = "block";
lag.style.top = extrasLookup[extras]
lag.innerHTML = `Lag: $lagNumms`;
else
lagdomstyle.display = "none";
;
function renderArena()
;
//========================
// Apple
//========================
class Apple
constructor()
this.pos = new Location(2,1,2)
move()
// Set the location to a random x and z.
var x = randomNumberBetween(0,ArenaWidth-4)
var z = randomNumberBetween(0,ArenaLength-4)
this.pos = new Location(x,1,z)
if(randomNumberBetween(1,11)===1&&score>15)
apple.type="superapple"
else
apple.type="apple"
draw()
var sphere
// Generate a new sphere.
if(this.type=="superapple")
sphere = new newMesh( applegeometry, superapplematerial );
else
sphere = new newMesh( applegeometry, applematerial );
// Get the data location.
var applepos=apple.pos
// Set the location of the visual apple to the data location.
sphere.position.set(applepos[0],applepos[1],applepos[2])
scene.add(sphere);
//========================
// Misc
//========================
function newGame(key)
if(key==82)
// Stop the game.
clearTimeout(gameLoop);
s=function();
// Start a new game.
var game = document.getElementById("canvas");
game.removeChild(game.childNodes[0]);
eval(document.getElementById("script").innerHTML);
gameOverDomStyle.opacity=0;
function gameOver()
s = function()
camera.position.copy(new newVector3((ArenaWidth/2)-2,Math.sqrt(
Math.pow(ArenaWidth/2,2)+Math.pow(ArenaLength/2,2)),(ArenaLength/2)-2));
camera.lookAt(new newVector3((ArenaWidth/2)-2,0,(ArenaLength/2)-2));
;
document.onkeydown=function(e)
newGame(e.keyCode);
//listen to shake event
var shakeEvent = new Shake(threshold: 15);
shakeEvent.start();
window.addEventListener('shake', function()
newGame(82)
, false);
//stop listening
function stopShake()
shakeEvent.stop();
//check if shake is supported or not.
if(!("ondevicemotion" in window))alert("Not Supported");
gameOverDomStyle.opacity = 1;
function randomNumberBetween(a,b)
return a+floor(random()*(b-a));
var apple = new Apple(),
snake = new Snake()
var directionSwitch=
"forwards":function(a)this.nextHead = new Location(a[0]+1, a[1], a[2]),
"backwards":function(a)this.nextHead = new Location(a[0]-1, a[1], a[2]),
"left":function(a)this.nextHead = new Location(a[0], a[1], a[2]-1),
"right":function(a)this.nextHead = new Location(a[0], a[1], a[2]+1)
for(var x in directionSwitch)
directionSwitch[x] = directionSwitch[x].bind(snake)
var right =
"right":function()this.nextDirection = "backwards",
"backwards":function()this.nextDirection = "left",
"forwards":function()this.nextDirection = "right",
"left":function()this.nextDirection = "forwards"
for(var x in right)
right[x] = right[x].bind(snake)
var left =
"right":function()snake.nextDirection = "forwards",
"forwards":function()snake.nextDirection = "left",
"left":function()snake.nextDirection = "backwards",
"backwards":function()snake.nextDirection = "right"
for(var x in left)
left[x] = left[x].bind(snake)
var keyLookup =
"39":right,
"68":right,
"37":left,
"65":left,
"192":function()showlag=!showlag,
"55":function()showhighscore=!showhighscore,
"56":function()showmaxspeed = !showmaxspeed
snake.draw();
apple.move();
var background = new THREE.Color( "white" ),
fog = new THREE.FogExp2( "random", 0.02625 );
let s = function()
// Start for lag detection.
var start = performance.now();
// Make a fresh scene.
scene = new newScene();
// Move the snake.
snake.move();
// Render various things onto the scene.
scene.add(arenaWallMesh,arenaFloorMesh)
snake.draw();
apple.draw();
drawStats();
// Get relevent snake parts.
let head = snake.segments[0];
let nextHead = snake.nextHead;
// Set camera position and target.
camera.position.set(head[0],head[1],head[2]);
camera.lookAt(new newVector3(nextHead[0],nextHead[1],nextHead[2]));
// Set background and fog.
scene.background = background;
scene.fog = fog;
let end = performance.now();
// Reschedule the next update
gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed)
// End for lag detection and calculation of lag.
lagNum = floor((end-start))
animate()
var gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed);
document.onkeydown = function(e)
snake.changeDirection(e.keyCode);
)(window.THREE, (((window.innerWidth/10)|0)*10-2*10)/10, (((window.innerHeight/10)|0)*10-2*10)/10)
</script>
<html>
<style>
canvas
position:fixed;
left:0;
top:0;
width:99%;
height:99%;
*
padding:0px;
margin:0px
#score,#speed,#highscore,#maxspeed,#lag,#debug
position: fixed;
z-index: 100;
font-size:20px;
font-family:Verdana;
left:15px;
width: 100%;
#gameover
position:absolute;
z-index: 100;
font-size:60px;
font-family:Verdana;
margin: 0;
top: 50%;
left: 50%;
opacity:0;
transform: translate(-50%, -50%);
#maxspeed, #score, #josh, #speed, #highscore, #lag
display:block;
#maxspeed
width: 100%;
top:50px;
display:none;
#score
top: 10px;
#speed
top: 30px;
#highscore
top:30px;
#lag
top: 70px;
</style>
<div id="stats">
<div id="debug"></div>
<div id="score">Score: 0</div>
<div id="speed">Speed: 1</div>
<div id="highscore">Highscore: 1</div>
<div id="maxspeed">Highest Speed: 1</div>
<span id="lag">Lag: 0ms</span>
<div id="gameover" align="center">Game Over</div>
</div>
<div id="canvas"></div>
<p id="p"></p>
<p id="e"></p>
<script type="text/javascript" src="https://cdn.rawgit.com/alexgibson/shake.js/master/shake.js"></script>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
//========================
// One times
//========================
const random = Math.random,
floor = function(a) return ~~a,
newGeometry = THREE.Geometry,
newBufferGeometry = THREE.BufferGeometry,
newMesh = THREE.Mesh,
newLineSegments = THREE.LineSegments,
newMeshBasicMaterial = THREE.MeshBasicMaterial,
newVector3 = THREE.Vector3,
newLineBasicMaterial = THREE.LineBasicMaterial,
newBoxGeometry = THREE.BoxGeometry,
newBoxBufferGeometry = THREE.BoxBufferGeometry,
arena = new THREE.Group(),
applegeometry = new THREE.SphereBufferGeometry( 0.5, 32, 32 ),
superapplematerial= new newMeshBasicMaterial(color:"gold"),
applematerial= new newMeshBasicMaterial(color:"limegreen"),
floormaterial = new newMeshBasicMaterial(color:"lightgrey"),
wallmaterial = new newMeshBasicMaterial( color: "grey" ),
linecube = new newBoxBufferGeometry( 1,1,1 ),
edges = new THREE.EdgesGeometry( linecube ),
geometry = new newBoxBufferGeometry( 1,1,1 ),
stringify = JSON.stringify
</script>
<script id="script">
(function(THREE,ArenaWidth, ArenaLength)
'use strict'
const arenaLines = new THREE.Group(),
arenaWall = new newGeometry(),
arenaFloor = new newGeometry(),
wall1 = new newBoxGeometry( ArenaWidth+1, 1, 1 )
.translate((ArenaWidth/2)-2,1,-2);
arenaWall.merge(wall1);
arenaWall.merge(wall1.translate(0,0, ArenaLength));
const wall2 = new newBoxGeometry( 1, 1, ArenaLength+1 ).translate(ArenaWidth-2,1,(ArenaLength/2)-2);
arenaWall.merge(wall2);
arenaWall.merge(wall2.translate(-ArenaWidth,0,0));
arenaFloor.merge(new newBoxGeometry( ArenaWidth+1, 1, ArenaLength+1 ).translate((ArenaWidth/2)-2,0,(ArenaLength/2)-2))
arenaWall.mergeVertices()
arenaFloor.mergeVertices()
// Get the meshs
window.arenaWallMesh = new newMesh(arenaWall, wallmaterial);
window.arenaFloorMesh = new newMesh(arenaFloor, floormaterial);
var speed = 100,
maxwidth = 40,
maxdepdth = 40,
size = 0.5,
score = 0,
maxheight = 0,
lagNum = 0,
highscoreNum,
showlag,
maxspeedNum,
showmaxspeed,
showhighscore
//========================
// Threejs
//========================
var scene = new THREE.Scene(),
camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,60),
renderer = new THREE.WebGLRenderer(),
extrasLookup =
1:30,
2:50,
3:70,
4:90
//========================
// Reductions
//========================
const newScene = THREE.Scene
if(true /*localStorage.getItem("3dhighscore")==undefined*/)
highscoreNum=0
else
highscoreNum = localStorage.getItem("3dhighscore")
if(true /*localStorage.getItem("showlag")==undefined*/)
showlag=false
else
showlag = localStorage.getItem("showlag")
if(true /*localStorage.getItem("3dmaxspeed")==undefined*/)
maxspeedNum=100
else
maxspeedNum = localStorage.getItem("3dmaxspeed")
if(showmaxspeed==undefined)
showmaxspeed=false
if(showhighscore==undefined)
showhighscore=false
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("canvas").appendChild( renderer.domElement );
function animate()
requestAnimationFrame( animate )
renderer.render( scene, camera );
class Location
constructor(x,y,z)
return [x,y,z]
//========================
// Dom
//========================
const maxSpeedDom = document.getElementById("maxspeed"),
maxSpeedDomStyle = maxSpeedDom.style,
lagdom = document.getElementById("lag"),
lagdomstyle = lagdom.style,
highScoreDom = document.getElementById("highscore"),
highScoreDomStyle = highScoreDom.style,
scoredom = document.getElementById("score"),
speeddom = document.getElementById("speed"),
gameOverDom = document.getElementById("gameover"),
gameOverDomStyle = gameOverDom.style;
//========================
// Snake
//========================
class Snake
constructor()
this.segments = [
new Location(7,1,5),
new Location(6,1,5),
new Location(5,1,5)
];
this.direction = "forwards";
this.nextDirection = "forwards";
this.nextHead = new Location(8,1,5);
draw()
let snakeobject = new THREE.Group();
let j = this.segments.length
this.segments.forEach((item,index) =>
let i = index
let segmentColor=`rgb($255-(255/j,00,00)`
const cube = new newMesh(geometry, new newMeshBasicMaterial( color: segmentColor)),
x = item[0],
y = item[1],
z = item[2];
let pos = new newVector3(x,y,z)
const line = new newLineSegments(edges, new newLineBasicMaterial( color: segmentColor,linewidth:2 ));
cube.position.copy(pos);
line.position.copy(pos);
snakeobject.add(line,cube);
)
scene.add(snakeobject);
move()
this.segments.unshift(this.nextHead);
if(this.checkCollision())
this.segments.shift();
gameOver();
return;
;
var nextHeadPos = this.nextHead;
this.direction = this.nextDirection;
(directionSwitch[this.direction])(nextHeadPos)
if(stringify(this.segments[0]) === stringify(apple.pos))
speed=0.95*speed;
score++;
if(apple.type === "superapple")
speed = 1.10*speed;
score += 4;
apple.move();
else
this.segments.pop();
;
changeDirection(key)
switch(key)
case 39:
case 68:
case 37:
case 65:
keyLookup[key][this.direction]()
break;
case 192:
case 55:
case 56:
keyLookup[key]()
break;
checkCollision()
//========================
// Drawing
//========================
function drawStats()
var extras = 1;
if(score > highscoreNum)
highscoreNum = score;
//localStorage.setItem("3dhighscore", highscore);
if(speed < maxspeed)
maxspeedNum = speed;
//localStorage.setItem("3dmaxspeed", maxspeed);
scoredom.innerHTML=`Score: $score`;
speeddom.innerHTML=`Speed: $(((100/speed*100)`;
if(showhighscore)
extras++;
highscore.style.display = "block";
highscore.style.top = extrasLookup[extras]
highscore.innerHTML = `Highscore: $highscoreNum`;
else
highScoreDomStyle.display = "none";
;
if(showmaxspeed)
extras++;
maxspeed.style.display = "block";
maxspeed.style.top = extrasLookup[extras]
maxspeed.innerHTML = `Highest Speed: $0)/100)`;
else
maxspeed.style.display = "none";
;
if(showlag)
extras++;
lag.style.display = "block";
lag.style.top = extrasLookup[extras]
lag.innerHTML = `Lag: $lagNumms`;
else
lagdomstyle.display = "none";
;
function renderArena()
;
//========================
// Apple
//========================
class Apple
constructor()
this.pos = new Location(2,1,2)
move()
// Set the location to a random x and z.
var x = randomNumberBetween(0,ArenaWidth-4)
var z = randomNumberBetween(0,ArenaLength-4)
this.pos = new Location(x,1,z)
if(randomNumberBetween(1,11)===1&&score>15)
apple.type="superapple"
else
apple.type="apple"
draw()
var sphere
// Generate a new sphere.
if(this.type=="superapple")
sphere = new newMesh( applegeometry, superapplematerial );
else
sphere = new newMesh( applegeometry, applematerial );
// Get the data location.
var applepos=apple.pos
// Set the location of the visual apple to the data location.
sphere.position.set(applepos[0],applepos[1],applepos[2])
scene.add(sphere);
//========================
// Misc
//========================
function newGame(key)
if(key==82)
// Stop the game.
clearTimeout(gameLoop);
s=function();
// Start a new game.
var game = document.getElementById("canvas");
game.removeChild(game.childNodes[0]);
eval(document.getElementById("script").innerHTML);
gameOverDomStyle.opacity=0;
function gameOver()
s = function()
camera.position.copy(new newVector3((ArenaWidth/2)-2,Math.sqrt(
Math.pow(ArenaWidth/2,2)+Math.pow(ArenaLength/2,2)),(ArenaLength/2)-2));
camera.lookAt(new newVector3((ArenaWidth/2)-2,0,(ArenaLength/2)-2));
;
document.onkeydown=function(e)
newGame(e.keyCode);
//listen to shake event
var shakeEvent = new Shake(threshold: 15);
shakeEvent.start();
window.addEventListener('shake', function()
newGame(82)
, false);
//stop listening
function stopShake()
shakeEvent.stop();
//check if shake is supported or not.
if(!("ondevicemotion" in window))alert("Not Supported");
gameOverDomStyle.opacity = 1;
function randomNumberBetween(a,b)
return a+floor(random()*(b-a));
var apple = new Apple(),
snake = new Snake()
var directionSwitch=
"forwards":function(a)this.nextHead = new Location(a[0]+1, a[1], a[2]),
"backwards":function(a)this.nextHead = new Location(a[0]-1, a[1], a[2]),
"left":function(a)this.nextHead = new Location(a[0], a[1], a[2]-1),
"right":function(a)this.nextHead = new Location(a[0], a[1], a[2]+1)
for(var x in directionSwitch)
directionSwitch[x] = directionSwitch[x].bind(snake)
var right =
"right":function()this.nextDirection = "backwards",
"backwards":function()this.nextDirection = "left",
"forwards":function()this.nextDirection = "right",
"left":function()this.nextDirection = "forwards"
for(var x in right)
right[x] = right[x].bind(snake)
var left =
"right":function()snake.nextDirection = "forwards",
"forwards":function()snake.nextDirection = "left",
"left":function()snake.nextDirection = "backwards",
"backwards":function()snake.nextDirection = "right"
for(var x in left)
left[x] = left[x].bind(snake)
var keyLookup =
"39":right,
"68":right,
"37":left,
"65":left,
"192":function()showlag=!showlag,
"55":function()showhighscore=!showhighscore,
"56":function()showmaxspeed = !showmaxspeed
snake.draw();
apple.move();
var background = new THREE.Color( "white" ),
fog = new THREE.FogExp2( "random", 0.02625 );
let s = function()
// Start for lag detection.
var start = performance.now();
// Make a fresh scene.
scene = new newScene();
// Move the snake.
snake.move();
// Render various things onto the scene.
scene.add(arenaWallMesh,arenaFloorMesh)
snake.draw();
apple.draw();
drawStats();
// Get relevent snake parts.
let head = snake.segments[0];
let nextHead = snake.nextHead;
// Set camera position and target.
camera.position.set(head[0],head[1],head[2]);
camera.lookAt(new newVector3(nextHead[0],nextHead[1],nextHead[2]));
// Set background and fog.
scene.background = background;
scene.fog = fog;
let end = performance.now();
// Reschedule the next update
gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed)
// End for lag detection and calculation of lag.
lagNum = floor((end-start))
animate()
var gameLoop = setTimeout(function()
requestAnimationFrame(s)
,speed);
document.onkeydown = function(e)
snake.changeDirection(e.keyCode);
)(window.THREE, (((window.innerWidth/10)|0)*10-2*10)/10, (((window.innerHeight/10)|0)*10-2*10)/10)
</script>
javascript ecmascript-6 dom snake-game
edited May 21 at 12:02
asked May 14 at 16:29
FreezePhoenix
310218
310218
Note: For the snippet, click "run", "Full page", purposely lose, and then click "r". Unfortunately the snippet makes the game small...
â FreezePhoenix
May 14 at 16:49
2
Oh maaan. It's so hard to play. Sorry, now got zero time to write an actual review! i.stack.imgur.com/gfiZi.png
â Igor Soloydenko
May 14 at 18:02
add a comment |Â
Note: For the snippet, click "run", "Full page", purposely lose, and then click "r". Unfortunately the snippet makes the game small...
â FreezePhoenix
May 14 at 16:49
2
Oh maaan. It's so hard to play. Sorry, now got zero time to write an actual review! i.stack.imgur.com/gfiZi.png
â Igor Soloydenko
May 14 at 18:02
Note: For the snippet, click "run", "Full page", purposely lose, and then click "r". Unfortunately the snippet makes the game small...
â FreezePhoenix
May 14 at 16:49
Note: For the snippet, click "run", "Full page", purposely lose, and then click "r". Unfortunately the snippet makes the game small...
â FreezePhoenix
May 14 at 16:49
2
2
Oh maaan. It's so hard to play. Sorry, now got zero time to write an actual review! i.stack.imgur.com/gfiZi.png
â Igor Soloydenko
May 14 at 18:02
Oh maaan. It's so hard to play. Sorry, now got zero time to write an actual review! i.stack.imgur.com/gfiZi.png
â Igor Soloydenko
May 14 at 18:02
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
Feedback
I like how the DOM elements are stored in constants at the beginning of the code. It seems that a lot of the feedback from previous answers has been incorporated, except a few things like resetting the game without using eval()
, and other es-6 features like classes. The CSS styles look succinct and appear to be sufficient.
Suggestions/Comments
In the function
checkCollision()
it might be fitting to use Array.prototype.some() instead of assigning the value of a boolean inside the callback of aforEach()
. Also, that loop call comes after the check for a wall collision - if there is a wall collision, the function could immediately returntrue
instead of also looping through the segments.As was mentioned by samurai8 in the answer to your previous review there are still places where
var
is used instead oflet
Blindman's answer on the first game mentioned using semi-colons - it appears most lines have them but some still don't.- The HTML snippet doesn't have a
<body>
tag - apparently it still works and perhaps you have one in other environments but it feels weird not to have one. The event listener for shake could be simplified: Use Function.prototype.bind() to create a partially applied function:
window.addEventListener('shake', function()
newGame(82)
, false);Can be simplified to:
window.addEventListener('shake', newGame.bind(null,82), false);
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Feedback
I like how the DOM elements are stored in constants at the beginning of the code. It seems that a lot of the feedback from previous answers has been incorporated, except a few things like resetting the game without using eval()
, and other es-6 features like classes. The CSS styles look succinct and appear to be sufficient.
Suggestions/Comments
In the function
checkCollision()
it might be fitting to use Array.prototype.some() instead of assigning the value of a boolean inside the callback of aforEach()
. Also, that loop call comes after the check for a wall collision - if there is a wall collision, the function could immediately returntrue
instead of also looping through the segments.As was mentioned by samurai8 in the answer to your previous review there are still places where
var
is used instead oflet
Blindman's answer on the first game mentioned using semi-colons - it appears most lines have them but some still don't.- The HTML snippet doesn't have a
<body>
tag - apparently it still works and perhaps you have one in other environments but it feels weird not to have one. The event listener for shake could be simplified: Use Function.prototype.bind() to create a partially applied function:
window.addEventListener('shake', function()
newGame(82)
, false);Can be simplified to:
window.addEventListener('shake', newGame.bind(null,82), false);
add a comment |Â
up vote
3
down vote
accepted
Feedback
I like how the DOM elements are stored in constants at the beginning of the code. It seems that a lot of the feedback from previous answers has been incorporated, except a few things like resetting the game without using eval()
, and other es-6 features like classes. The CSS styles look succinct and appear to be sufficient.
Suggestions/Comments
In the function
checkCollision()
it might be fitting to use Array.prototype.some() instead of assigning the value of a boolean inside the callback of aforEach()
. Also, that loop call comes after the check for a wall collision - if there is a wall collision, the function could immediately returntrue
instead of also looping through the segments.As was mentioned by samurai8 in the answer to your previous review there are still places where
var
is used instead oflet
Blindman's answer on the first game mentioned using semi-colons - it appears most lines have them but some still don't.- The HTML snippet doesn't have a
<body>
tag - apparently it still works and perhaps you have one in other environments but it feels weird not to have one. The event listener for shake could be simplified: Use Function.prototype.bind() to create a partially applied function:
window.addEventListener('shake', function()
newGame(82)
, false);Can be simplified to:
window.addEventListener('shake', newGame.bind(null,82), false);
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Feedback
I like how the DOM elements are stored in constants at the beginning of the code. It seems that a lot of the feedback from previous answers has been incorporated, except a few things like resetting the game without using eval()
, and other es-6 features like classes. The CSS styles look succinct and appear to be sufficient.
Suggestions/Comments
In the function
checkCollision()
it might be fitting to use Array.prototype.some() instead of assigning the value of a boolean inside the callback of aforEach()
. Also, that loop call comes after the check for a wall collision - if there is a wall collision, the function could immediately returntrue
instead of also looping through the segments.As was mentioned by samurai8 in the answer to your previous review there are still places where
var
is used instead oflet
Blindman's answer on the first game mentioned using semi-colons - it appears most lines have them but some still don't.- The HTML snippet doesn't have a
<body>
tag - apparently it still works and perhaps you have one in other environments but it feels weird not to have one. The event listener for shake could be simplified: Use Function.prototype.bind() to create a partially applied function:
window.addEventListener('shake', function()
newGame(82)
, false);Can be simplified to:
window.addEventListener('shake', newGame.bind(null,82), false);
Feedback
I like how the DOM elements are stored in constants at the beginning of the code. It seems that a lot of the feedback from previous answers has been incorporated, except a few things like resetting the game without using eval()
, and other es-6 features like classes. The CSS styles look succinct and appear to be sufficient.
Suggestions/Comments
In the function
checkCollision()
it might be fitting to use Array.prototype.some() instead of assigning the value of a boolean inside the callback of aforEach()
. Also, that loop call comes after the check for a wall collision - if there is a wall collision, the function could immediately returntrue
instead of also looping through the segments.As was mentioned by samurai8 in the answer to your previous review there are still places where
var
is used instead oflet
Blindman's answer on the first game mentioned using semi-colons - it appears most lines have them but some still don't.- The HTML snippet doesn't have a
<body>
tag - apparently it still works and perhaps you have one in other environments but it feels weird not to have one. The event listener for shake could be simplified: Use Function.prototype.bind() to create a partially applied function:
window.addEventListener('shake', function()
newGame(82)
, false);Can be simplified to:
window.addEventListener('shake', newGame.bind(null,82), false);
answered May 14 at 18:47
Sam Onela
5,77461543
5,77461543
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194377%2f3d-1st-person-snake-game-2%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Note: For the snippet, click "run", "Full page", purposely lose, and then click "r". Unfortunately the snippet makes the game small...
â FreezePhoenix
May 14 at 16:49
2
Oh maaan. It's so hard to play. Sorry, now got zero time to write an actual review! i.stack.imgur.com/gfiZi.png
â Igor Soloydenko
May 14 at 18:02