Skip to content

Instantly share code, notes, and snippets.

@koekaverna
Created July 9, 2020 13:32
Show Gist options
  • Save koekaverna/54270a042a6d857836bb1c33956f9e02 to your computer and use it in GitHub Desktop.
Save koekaverna/54270a042a6d857836bb1c33956f9e02 to your computer and use it in GitHub Desktop.
<template>
<canvas ref="canvas" width="400" height="400" class="mt-5"></canvas>
</template>
<script>
import * as sleep from 'await-sleep'
const ITEM_TYPES = [
{ icon: '🍎', boost: 1 },
{ icon: 'πŸ–', boost: 2 },
{ icon: 'πŸ₯š', boost: 3 },
{ icon: '🍀', boost: 5 },
{ icon: '🍰', boost: 7 },
{ icon: 'πŸ‰', boost: 10 },
{ icon: 'πŸ„', boost: 15 },
{ icon: 'πŸ’', boost: 20 },
{ icon: 'πŸ₯‘', boost: 30 }
]
export default {
data: () => ({
paused: false,
width: 40,
height: 40,
speed: 50,
head: {
x: 0, y: 6
},
body: [
{ x: 0, y: 0 },
{ x: 0, y: 1 },
{ x: 0, y: 2 },
{ x: 0, y: 3 },
{ x: 0, y: 4 },
{ x: 0, y: 5 },
],
items: [
],
nextItem: 5,
boost: 0,
direction: 'right',
gameOver: false,
// canvas: null,
// ctx: null
}),
methods: {
move() {
if (this.boost) {
this.boost--
} else {
this.body.splice(0, 1)
}
this.body.push(this.head)
this.eat()
let { x, y } = this.head
if (this.direction === 'right') {
x++
} else if (this.direction === 'left') {
x--
} else if (this.direction === 'up') {
y--
} else if (this.direction === 'down') {
y++
}
if(x >= this.width || y >= this.height || y < 0 || x < 0) {
throw new Error()
}
this.head = { x, y }
// if(this.body.includes({ ...this.head })) {
if(this.body.find(item => item.x === x && item.y === y)) {
throw new Error
}
},
eat () {
const { x, y } = this.head
for (let index in this.items) {
const item = this.items[index]
if (item.x === x && item.y === y) {
this.items.splice(index, 1)
this.boost = item.boost
return
}
}
},
putFood () {
const item = ITEM_TYPES[Math.floor(Math.random() * ITEM_TYPES.length)]
const x = Math.floor(Math.random() * this.height)
const y = Math.floor(Math.random() * this.width)
this.items.push({...item, x, y})
},
init () {
Object.assign(this.$data, this.$options.data.call(this))
this.canvas = this.$refs.canvas
this.ctx = this.$refs.canvas.getContext('2d')
this.tick()
},
async tick() {
if (this.paused) return
await sleep(this.speed)
this.nextItem--
if (this.nextItem <= 0) {
this.putFood()
this.nextItem = Math.floor(Math.random() * 100)
}
try {
this.move()
this.tick()
} catch (e) {
this.gameOver = true
}
this.draw()
},
keydown({ code }) {
if (code === 'ArrowUp' && this.direction !== 'down') {
this.direction = 'up'
} else if (code === 'ArrowDown' && this.direction !== 'up') {
this.direction = 'down'
} else if (code === 'ArrowRight' && this.direction !== 'left') {
this.direction = 'right'
} else if (code === 'ArrowLeft' && this.direction !== 'right') {
this.direction = 'left'
} else if (code === 'Space') {
if (this.gameOver) {
this.init()
return // !
} else {
this.paused = !this.paused
}
this.tick()
}
},
draw () {
const { ctx, canvas } = this
const x = c => Math.round(c * canvas.width / this.width)
const y = r => Math.round(r * canvas.height / this.height)
// clear
ctx.fillStyle = '#232323'
ctx.fillRect(0, 0, canvas.width, canvas.height)
// draw snake
ctx.fillStyle = 'rgb(0, 200, 50)'
this.body.map(p => ctx.fillRect(x(p.x), y(p.y), x(1), y(1)))
// draw apples
// this.items.map(p => ctx.fillRect(x(p.x), y(p.y), x(1), y(1)))
ctx.font = '10px sans'
ctx.textAlign = 'left'
ctx.textBaseline = 'top'
this.items.map(p => ctx.fillText(p.icon, x(p.x), y(p.y)))
// add crash
if (this.gameOver) {
ctx.fillStyle = 'rgba(255, 0, 0, 0.3)'
ctx.fillRect(0, 0, canvas.width, canvas.height)
}
}
},
mounted () {
this.init()
window.addEventListener('keydown', e => {
this.keydown(e)
e.preventDefault()
return false
}, false)
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment