hook-miner/src/game.js

209 lines
5.2 KiB
JavaScript

import { canvas, ctx } from './canvas'
import { Level, Rock, Gold, Diamond, Lootbag, BarrelPiece } from './level'
import { randomi } from './utils'
const MAP_CLEARANCE_PERCENTAGE = 90
const REWARD_TABLE = {
rock: 16,
gold: [229, 843, 1299],
diamond: 1000,
lootbag: [5, 5000]
}
export class Game {
constructor (time, player, oh, gw, gh) {
this.currentLevel = 0
this.player = player
this.roundTime = time
this.time = time
this.score = 0
this.lastGoal = 0
this.goal = 0
this.level = null
this.oh = oh
this.gh = gh
this.gw = gw
this.message = null
this.state = 0
this.wait = 0
}
static calculateScore (obj) {
if (obj instanceof Rock) {
return REWARD_TABLE.rock * obj.size
}
if (obj instanceof Gold) {
return REWARD_TABLE.gold[obj.size - 1]
}
if (obj instanceof Diamond) {
return REWARD_TABLE.diamond
}
if (obj instanceof BarrelPiece) {
return 1
}
if (obj instanceof Lootbag) {
let ssChance = randomi(0, 3)
if (ssChance === 1) {
return 'special'
}
return randomi(REWARD_TABLE.lootbag[0], REWARD_TABLE.lootbag[1])
}
return 0
}
static calculateLevelScore (level) {
let total = 0
for (let i in level.objects) {
let obj = level.objects[i]
if (obj instanceof Gold) {
total += REWARD_TABLE.gold[obj.size - 1]
}
}
return total
}
nextLevel () {
this.player.superStrength = false
this.currentLevel++
this.time = this.roundTime
this.level = Level.create(this.currentLevel, this.oh, this.gw, this.gh)
this.lastGoal = this.goal
this.goal = Math.floor(this.lastGoal + Game.calculateLevelScore(this.level) * (MAP_CLEARANCE_PERCENTAGE / 100))
this.player.hook.clear()
}
displayMessage (msg, time = 60) {
this.message = { text: msg, time: time, duration: time }
}
scoredItem (obj) {
let scored = Game.calculateScore(obj)
if (scored === 'special') {
this.displayMessage('SUPER STRENGTH!')
this.player.superStrength = true
return
}
this.displayMessage('$' + scored)
this.score += scored
}
update () {
ctx.oX = (canvas.width - this.gw) / 2
ctx.oY = (canvas.height - this.gh) / 2
if (this.state === 0 && this.time === 0) {
if (this.score > this.goal) {
this.state = 1
this.wait = 160
this.nextLevel()
} else {
this.state = 2
}
}
if (this.state === 1) {
if (this.wait > 0) {
this.wait--
} else {
this.state = 0
}
return
}
if (this.state !== 0) return
if (this.message) {
if (this.message.time > 0) {
this.message.time--
} else {
this.message = null
}
return
}
this.level.update()
this.player.update(this.level)
}
tick () {
if (this.state === 0 && this.time > 0) {
this.time -= 1
}
}
draw () {
if (this.state === 2) {
ctx.fillStyle = '#ff1111'
ctx.font = '20px sans-serif'
let t = 'Game Over!'
let s = 'Score: $' + this.score
ctx.fillText(t, ctx.oX + this.gw / 2 - ctx.measureText(t).width / 2, ctx.oY + this.gh / 2 - 15)
ctx.fillText(s, ctx.oX + this.gw / 2 - ctx.measureText(s).width / 2, ctx.oY + this.gh / 2 + 15)
if (ctx.mouse['btn0']) {
setTimeout(() => {
this.currentLevel = 0
this.score = 0
this.goal = 0
this.lastGoal = 0
this.nextLevel()
this.state = 0
}, 500)
}
return
}
if (this.state === 1) {
ctx.fillStyle = '#05ff05'
ctx.font = '20px sans-serif'
let t = 'Level Cleared!'
let s = 'Next Goal: $' + this.goal
ctx.fillText(t, ctx.oX + this.gw / 2 - ctx.measureText(t).width / 2, ctx.oY + this.gh / 2 - 15)
ctx.fillText(s, ctx.oX + this.gw / 2 - ctx.measureText(s).width / 2, ctx.oY + this.gh / 2 + 15)
return
}
// Underground
ctx.fillStyle = '#3a2201'
ctx.fillRect(ctx.oX, ctx.oY, this.gw, this.gh)
// Room
ctx.fillStyle = '#b26b08'
ctx.fillRect(ctx.oX, ctx.oY, this.gw, 25 + this.player.h)
// Floor
ctx.fillStyle = '#2b1a02'
ctx.fillRect(ctx.oX, ctx.oY + 25 + this.player.h, this.gw, 15)
if (this.level) this.level.draw()
this.player.draw()
ctx.fillStyle = '#05ff05'
ctx.font = '20px sans-serif'
ctx.fillText('Money: $' + this.score, ctx.oX + 20, ctx.oY + 30)
ctx.fillStyle = '#eabb4d'
ctx.fillText('Goal: $' + this.goal, ctx.oX + 20, ctx.oY + 62)
ctx.fillStyle = '#05ff05'
let time = 'Time: ' + this.time
let ftsize = ctx.measureText(time)
ctx.fillText(time, ctx.oX + this.gw - ftsize.width - 5, ctx.oY + 30)
let round = 'Level ' + this.currentLevel
let frsize = ctx.measureText(round)
ctx.fillText(round, ctx.oX + this.gw - frsize.width - 5, ctx.oY + 62)
if (this.message && this.message.time > 0) {
let tfloat = this.message.duration - this.message.time
ctx.fillStyle = '#05ff05'
ctx.font = '20px sans-serif'
ctx.fillText(this.message.text, ctx.oX + this.player.x - this.player.w - tfloat, ctx.oY + this.player.y + this.player.h / 2 - tfloat / 2)
}
}
}