242 lines
7.2 KiB
Vue
242 lines
7.2 KiB
Vue
<template>
|
|
<div class="game">
|
|
<b-modal v-model="playerIsDead">
|
|
<h1 class="titleDed">DED</h1>
|
|
<h2 class="title">Score: {{player.score}}</h2>
|
|
<h3 class="subtitle">Best score: {{player.bestScore}}</h3>
|
|
<b-button @click="respawn">Respawn</b-button>
|
|
<b-button @click="quit">Quit</b-button>
|
|
</b-modal>
|
|
<canvas
|
|
class="game-canvas"
|
|
ref="canvas">
|
|
</canvas>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { send } from '@/store/socketPlugin'
|
|
import { render } from '@/game/render.js'
|
|
import { sound } from '@/game/sound.js'
|
|
import { Explosion } from '@/game/sprites.js'
|
|
|
|
export default {
|
|
name: 'Game',
|
|
props: ['showDebug', 'showLeaderboard'],
|
|
data () {
|
|
return {
|
|
mouse: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
camera: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
stats: {
|
|
totalWalls: 0,
|
|
lastUpdateTime: {},
|
|
lastFrame: 0,
|
|
lastSpriteFrame: 0
|
|
},
|
|
deadPlayers: [],
|
|
renderTimer: null
|
|
}
|
|
},
|
|
computed: {
|
|
canvas () {
|
|
return this.$refs.canvas
|
|
},
|
|
context () {
|
|
return this.canvas.getContext('2d')
|
|
},
|
|
settings () {
|
|
return this.$store.state.game.settings
|
|
},
|
|
player () {
|
|
return this.$store.state.game.player
|
|
},
|
|
sprites () {
|
|
return this.$store.state.game.sprites
|
|
},
|
|
players () {
|
|
const pastUpdate = this.$store.state.game.updates[0]
|
|
const nextUpdate = this.$store.state.game.updates[1]
|
|
|
|
if (pastUpdate === undefined) return []
|
|
if (pastUpdate.players === undefined) return []
|
|
if (nextUpdate === undefined) return pastUpdate.players
|
|
|
|
return nextUpdate.players
|
|
},
|
|
isPaused () {
|
|
return this.$store.state.game.paused
|
|
},
|
|
leaderboard () {
|
|
return this.$store.state.game.leaderboard
|
|
},
|
|
playerIsDead () {
|
|
return this.player.state === 'DEAD'
|
|
}
|
|
},
|
|
mounted () {
|
|
this.setCanvasSize()
|
|
this.canvas.addEventListener('mousemove', this.mouseEvent)
|
|
this.canvas.addEventListener('touchmove', this.touchEvent)
|
|
this.canvas.addEventListener('resize', this.setCanvasSize)
|
|
// this.renderTimer = setInterval(this.render, 1000 / 60)
|
|
// this.renderTimer = setInterval(this.renderSprites, 1000 / 30)
|
|
this.render()
|
|
},
|
|
methods: {
|
|
render () {
|
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
|
render.borders(this.context, this.canvas, this.camera, this.settings)
|
|
|
|
// const players = update.computePlayers(this.$store.state.game.updates, this.$store.state.game.firstUpdateTime, this.$store.state.game.gameStartTime)
|
|
|
|
if (!this.players) return
|
|
this.stats.totalWalls = 0
|
|
|
|
this.players.forEach(player => {
|
|
if (player.color === this.player.color) {
|
|
this.camera.x = player.x
|
|
this.camera.y = player.y
|
|
}
|
|
|
|
if (player.state === 'DEAD') this.context.globalAlpha = 0.1
|
|
|
|
// render.wallsBezier(this.context, this.canvas, this.camera, this.settings, player)
|
|
render.walls(this.context, this.canvas, this.camera, this.settings, player)
|
|
|
|
if (player.name === 'e' || player.name === 'q' || player.name === 'r' || player.name === 't') render.playerFace(this.context, this.canvas, this.camera, this.settings, player, player.name)
|
|
else render.player(this.context, this.canvas, this.camera, this.settings, player)
|
|
|
|
if (player.state === 'DEAD') this.context.globalAlpha = 1
|
|
|
|
this.stats.totalWalls += player.walls.length
|
|
|
|
// Check if player was dead before for one time event
|
|
if (player.state === 'DEAD' && !this.deadPlayers.includes(player.id)) {
|
|
this.deadPlayers.push(player.id)
|
|
sound.explosion()
|
|
this.sprites.push(new Explosion(player.x, player.y))
|
|
}
|
|
|
|
// Remove player from dead list
|
|
if (player.state !== 'DEAD' && this.deadPlayers.includes(player.id)) {
|
|
const i = this.deadPlayers.indexOf(player.id)
|
|
this.deadPlayers.splice(i, 1)
|
|
}
|
|
})
|
|
|
|
this.renderSprites()
|
|
|
|
render.mouse(this.context, this.mouse, this.player)
|
|
|
|
if (this.showLeaderboard) {
|
|
render.leaderboard(this.context, this.canvas, this.leaderboard)
|
|
}
|
|
|
|
if (this.showDebug) {
|
|
render.debug(this.context, this.camera, this.mouse, this.canvas, this.stats)
|
|
}
|
|
|
|
this.stats.lastFrame = performance.now()
|
|
|
|
const nextUpdate = this.$store.state.game.updates[1]
|
|
if (nextUpdate !== undefined) this.stats.lastUpdateTime = nextUpdate.time
|
|
requestAnimationFrame(this.render, this.canvas)
|
|
},
|
|
renderSprites () {
|
|
let nextFrame = false
|
|
// Check if needed to show next frame for animations
|
|
if ((performance.now() - this.stats.lastSpriteFrame) > 50) {
|
|
nextFrame = true
|
|
this.stats.lastSpriteFrame = performance.now()
|
|
}
|
|
|
|
this.sprites.forEach((sprite, index, object) => {
|
|
render.sprite(this.context, this.canvas, this.camera, sprite)
|
|
if (nextFrame) {
|
|
if (sprite.framesCounter === sprite.frames) {
|
|
if (sprite.removeAfterAnimation) {
|
|
object.splice(index, 1)
|
|
} else {
|
|
// console.log('SPRITE ', index, 'frame reset')
|
|
sprite.framesCounter = 0
|
|
}
|
|
} else {
|
|
// console.log('SPRITE ', index, 'frame++', sprite.framesCounter)
|
|
sprite.framesCounter++
|
|
}
|
|
}
|
|
})
|
|
},
|
|
mouseEvent (event) {
|
|
var rect = this.canvas.getBoundingClientRect()
|
|
this.mouse.x = event.clientX - rect.left
|
|
this.mouse.y = event.clientY - rect.top
|
|
|
|
this.sendAngleUpdate()
|
|
},
|
|
touchEvent (event) {
|
|
var rect = this.canvas.getBoundingClientRect()
|
|
this.mouse.x = event.touch[0].clientX - rect.left
|
|
this.mouse.y = event.touch[0].clientY - rect.top
|
|
|
|
this.sendAngleUpdate()
|
|
},
|
|
sendAngleUpdate () {
|
|
var dx = this.mouse.x - this.canvas.width / 2
|
|
var dy = this.mouse.y - this.canvas.height / 2
|
|
|
|
this.player.targetAngle = Math.atan2(dy, dx)
|
|
this.player.angle = this.player.targetAngle
|
|
send({ player: this.player, type: 'update' })
|
|
},
|
|
updatePlayer (player) {
|
|
player.x += this.settings.playerSpeed * Math.cos(player.angle)
|
|
player.y += this.settings.playerSpeed * Math.sin(player.angle)
|
|
|
|
player.angle = player.targetAngle
|
|
},
|
|
interpolatePlayer (pastPlayer, nextPlayer, dt) {
|
|
var player = {}
|
|
player.color = pastPlayer.color
|
|
player.walls = pastPlayer.walls
|
|
player.lastWall = pastPlayer.lastWall
|
|
|
|
player.x = pastPlayer.x + (nextPlayer.x - pastPlayer.x) * dt
|
|
player.y = pastPlayer.y + (nextPlayer.y - pastPlayer.y) * dt
|
|
|
|
player.angle = pastPlayer.angle + (nextPlayer.angle - pastPlayer.angle) * dt
|
|
player.targetAngle = pastPlayer.targetAngle + (nextPlayer.targetAngle - pastPlayer.targetAngle) * dt
|
|
|
|
return player
|
|
},
|
|
setCanvasSize () {
|
|
this.canvas.width = window.innerWidth
|
|
this.canvas.height = window.innerHeight
|
|
},
|
|
respawn () {
|
|
send({ type: 'respawn' })
|
|
},
|
|
quit () {
|
|
send({ type: 'logout' })
|
|
this.$store.dispatch('game/logout')
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.titleDed {
|
|
display: inline-block;
|
|
font-family: TRON;
|
|
font-size: 70px;
|
|
color: #cf0cb4ff;
|
|
margin-bottom: 25px;
|
|
}
|
|
</style>
|