@deveckad/snakegame
Version:
The snake game.
309 lines (259 loc) • 7.15 kB
JavaScript
const socket = io()
const BG_COLOUR = '#231f20'
const SNAKE_COLOUR = '#c2c2c2'
const FOOD_COLOUR = '#e66916'
const canvas = document.querySelector('canvas')
const msgDisplay = document.querySelector('.msg-display')
const ctx = canvas.getContext('2d')
var pos, vel, tail, food, score, hiscore
var keyPressed = false
var gameRunning = false
var gameStarted = false
canvas.width = canvas.height = 550
const GRID_SIZE = 22
const TILE_SIZE = canvas.width / GRID_SIZE
const FR = 7
socket.on('hiscore', (hiscr) => {
hiscore = hiscr
})
function init() {
gameStarted = gameRunning = false
msgDisplay.innerText = 'Press any key to start...'
pos = { x: 10, y: 10 }
vel = { x: 1, y: 0 }
tail = [
{ x: 8, y: 10 },
{ x: 9, y: 10 },
{ x: 10, y: 10 }
]
score = 0
randomFood()
paintGame()
}
init()
setInterval(() => {
requestAnimationFrame(gameLoop)
}, 1000 / FR)
function randomFood() {
food = {
x: Math.floor(Math.random() * TILE_SIZE),
y: Math.floor(Math.random() * TILE_SIZE)
}
for (const cell of tail) {
if (food.x === cell.x && food.y === cell.y) {
randomFood()
}
}
}
function gameLoop() {
if (gameRunning) {
keyPressed = false
paintGame()
pos.x += vel.x
pos.y += vel.y
if (food.x === pos.x && food.y === pos.y) {
score++
refreshMsgDisplay()
tail.push({ ...pos })
pos.x += vel.x
pos.y += vel.y
randomFood()
}
if (pos.x < 0 || pos.x > TILE_SIZE || pos.y < 0 || pos.y > TILE_SIZE) {
gameOver()
}
if (vel.x || vel.y) {
for (const cell of tail) {
if (pos.x === cell.x && pos.y === cell.y) {
return gameOver()
}
}
tail.push({ ...pos })
tail.shift()
}
}
}
document.addEventListener('keydown', keydown)
function keydown(e) {
if (!gameStarted) {
gameStarted = gameRunning = true
refreshMsgDisplay()
}
var vel2
switch (e.keyCode) {
case 37: {
vel2 = { x: -1, y: 0 }
break
}
case 38: {
vel2 = { x: 0, y: -1 }
break
}
case 39: {
vel2 = { x: 1, y: 0 }
break
}
case 40: {
vel2 = { x: 0, y: 1 }
break
}
default:
return
}
if (!isOpposite(vel, vel2) && !keyPressed) {
vel = vel2
}
keyPressed = true
}
function isOpposite(firstDir, secondDir) {
// console.log("Opposite: " + firstDir + " " + secondDir)
return !(
!(firstDir.x + secondDir.x == 0 && firstDir.y + secondDir.y == 0)
// || (firstDir.x == 0 && firstDir.y == 0)
)
}
function gameOver() {
gameRunning = false
socket.emit('gethiscore')
socket.on('rethiscore', (hiscore) => {
var msg = `Game Over! Your score is ${score}`
var hiscoreMsg = ` and hi-score is ${hiscore.score}, maked by ${hiscore.name}!`
var resultMsg
if (score > hiscore.score) {
hiscoreMsg = ' and it is hi-score! Enter name to save it:'
resultMsg = msg + hiscoreMsg
var name = prompt(resultMsg)
socket.emit('newhiscore', JSON.stringify({ name, score }))
} else {
var resultMsg = msg + hiscoreMsg
alert(resultMsg)
}
init()
})
}
function refreshMsgDisplay() {
msgDisplay.innerText = `Score: ${score}`
}
function paintGame() {
ctx.fillStyle = BG_COLOUR
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = SNAKE_COLOUR
for (const cell of tail) {
ctx.fillRect(cell.x * GRID_SIZE, cell.y * GRID_SIZE, GRID_SIZE, GRID_SIZE)
}
ctx.fillStyle = FOOD_COLOUR
ctx.fillRect(food.x * GRID_SIZE, food.y * GRID_SIZE, GRID_SIZE, GRID_SIZE)
}
// old version
// const socket = io()
// const BG_COLOR = '#231f20';
// const SNAKE_COLOR = '#c2c2c2';
// const FOOD_COLOR = '#e66916';
// const GRID_SIZE = 22
// const SCREEN_SIZE = 550
// const TILE_SIZE = SCREEN_SIZE / GRID_SIZE
// const FR = 10
// const canvas = document.querySelector('canvas')
// const ctx = canvas.getContext('2d')
// var gameState
// canvas.width = canvas.height = SCREEN_SIZE
// document.addEventListener('keydown', keyDown)
// init()
// function keyDown(e) {
// switch (e.keyCode) {
// case 37: {
// console.log('right');
// break;
// }
// case 38: {
// console.log('up');
// break;
// }
// case 39: {
// console.log('left');
// break;
// }
// case 40: {
// console.log('down');
// break;
// }
// }
// }
// function init() {
// gameState = {
// player: {
// pos: {
// x: 5,
// x: 5,
// },
// vel: {
// x: 0,
// x: 0,
// },
// tail: [],
// initLength: 3
// },
// food: {
// x: 0,
// y: 0,
// },
// score: 0
// }
// initTail()
// console.log(gameState.player.tail)
// randomFood()
// gameLoop()
// }
// function initTail() {
// for (var i = 0; i < gameState.player.initLength; i++) {
// gameState.player.tail.push({x: gameState.player.pos.x - i - 1, y: gameState.player.pos.y})
// }
// gameState.player.tail.reverse()
// }
// function randomFood() {
// if (gameState.score + gameState.player.initLength >= GRID_SIZE * GRID_SIZE) {
// gameOver()
// }
// gameState.food.x = Math.floor(Math.random() * GRID_SIZE)
// gameState.food.y = Math.floor(Math.random() * GRID_SIZE)
// gameState.player.tail.forEach(cell => {
// if (gameState.food.x == cell.x && gameState.food.y == cell.y) {
// randomFood()
// }
// })
// }
// function gameLoop() {
// ctx.fillStyle = BG_COLOR
// ctx.fillRect(0, 0, SCREEN_SIZE, SCREEN_SIZE)
// ctx.fillStyle = SNAKE_COLOR
// gameState.player.tail.forEach(cell => {
// ctx.fillRect(cell.x * TILE_SIZE, cell.y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
// })
// ctx.fillStyle = FOOD_COLOR
// ctx.fillRect(gameState.food.x * TILE_SIZE, gameState.food.y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
// gameState.player.pos.x += gameState.player.vel.x
// gameState.player.pos.y += gameState.player.vel.y
// if (gameState.player.vel.x || gameState.player.vel.y) {
// if (gameState.player.pos.x == gameState.food.x && gameState.player.pos.y == gameState.food.y) {
// gameState.score++
// gameState.player.tail.push({ ...gameState.player.pos })
// gameState.player.pos.x += gameState.player.vel.x
// gameState.player.pos.y += gameState.player.vel.y
// }
// if (gameState.player.pos.x <= 0 || gameState.player.pos.y <= 0 || gameState.player.pos.x > GRID_SIZE || gameState.player.pos.y > GRID_SIZE) {
// gameOver()
// }
// gameState.player.tail.forEach(cell => {
// if (cell.x == gameState.player.pos.x && cell.y == gameState.player.pos.y) {
// gameOver()
// }
// })
// gameState.player.tail.push({ ...gameState.player.pos })
// snake.shift()
// }
// setTimeout(() => requestAnimationFrame(gameLoop), 1000 / FR)
// }
// function gameOver() {
// alert('Game Over!')
// init()
// }