190 lines
3.8 KiB
JavaScript
190 lines
3.8 KiB
JavaScript
import { ctx } from './canvas'
|
|
import { GameObject } from './level'
|
|
import { deg2rad, rad2vec, intersectRect } from './utils'
|
|
import RES from './resource'
|
|
|
|
const FULL_ROTATION = -85
|
|
const FULL_ROTATION_EDGE = -FULL_ROTATION
|
|
|
|
class Hook extends GameObject {
|
|
constructor (player, x, y, w, h, len) {
|
|
super(x, y, w, h)
|
|
this.player = player
|
|
|
|
// Return position
|
|
this.rx = x
|
|
this.ry = y
|
|
|
|
// Hook rotation
|
|
// Hook rotation direction
|
|
this.r = 0
|
|
this.rd = 1
|
|
|
|
// Distance from center
|
|
// Moving direction
|
|
this.d = 0
|
|
this.md = -1
|
|
|
|
// Travel length
|
|
this.len = len
|
|
|
|
// Attached object
|
|
this.obj = null
|
|
}
|
|
|
|
draw () {
|
|
if (this.md !== -1) {
|
|
// Draw line
|
|
ctx.beginPath()
|
|
ctx.moveTo(ctx.oX + this.rx, ctx.oY + this.ry)
|
|
ctx.lineTo(ctx.oX + this.x, ctx.oY + this.y)
|
|
ctx.stroke()
|
|
ctx.closePath()
|
|
}
|
|
|
|
let hookr = deg2rad(360 - this.r)
|
|
ctx.save()
|
|
ctx.translate(ctx.oX + this.x, ctx.oY + this.y)
|
|
ctx.rotate(hookr)
|
|
ctx.drawImage(RES.loadImage('static/hook_open.png', true), -this.w / 2, -this.h / 2, this.w, this.h)
|
|
ctx.restore()
|
|
}
|
|
|
|
clear () {
|
|
this.obj = null
|
|
this.d = 0
|
|
this.md = -1
|
|
this.x = this.rx
|
|
this.y = this.ry
|
|
}
|
|
|
|
update (level) {
|
|
if (this.d === 0 && this.r < FULL_ROTATION_EDGE && this.rd === 1) {
|
|
this.r += 1
|
|
}
|
|
|
|
if (this.d === 0 && this.r > FULL_ROTATION && this.rd === 0) {
|
|
this.r -= 1
|
|
}
|
|
|
|
if (this.r >= FULL_ROTATION_EDGE && this.rd === 1) {
|
|
this.r = FULL_ROTATION_EDGE
|
|
this.rd = 0
|
|
}
|
|
|
|
if (this.r <= FULL_ROTATION && this.rd === 0) {
|
|
this.r = FULL_ROTATION
|
|
this.rd = 1
|
|
}
|
|
|
|
if (ctx.mouse.down['btn0'] && this.d === 0 && !this.obj) {
|
|
this.d = 0
|
|
this.md = 1
|
|
}
|
|
|
|
if (this.md > -1) {
|
|
if (this.d > this.len && this.md === 1) {
|
|
this.md = 0
|
|
}
|
|
|
|
if (this.d <= 2 && this.md === 0) {
|
|
this.d = 0
|
|
this.md = -1
|
|
this.x = this.rx
|
|
this.y = this.ry
|
|
|
|
// Score
|
|
if (this.obj) {
|
|
this.player.score(this.obj)
|
|
this.obj.destroy()
|
|
this.obj = null
|
|
}
|
|
return
|
|
}
|
|
|
|
let dir = rad2vec(deg2rad(90 - this.r))
|
|
dir.x *= this.d
|
|
dir.y *= this.d
|
|
|
|
this.x = this.rx + dir.x
|
|
this.y = this.ry + dir.y
|
|
|
|
if (this.obj) {
|
|
this.obj.x = this.x - this.obj.w / 2
|
|
this.obj.y = this.y
|
|
}
|
|
|
|
// Detect intersection
|
|
if (this.md === 1) {
|
|
if (!this.obj) {
|
|
let firstIntersect
|
|
for (let i in level.objects) {
|
|
let obj = level.objects[i]
|
|
if (obj.physical && intersectRect(obj, this)) {
|
|
firstIntersect = obj
|
|
break
|
|
}
|
|
}
|
|
|
|
if (firstIntersect) {
|
|
if (firstIntersect.explode) {
|
|
let obj = firstIntersect.explode(level)
|
|
this.obj = obj
|
|
this.md = 0
|
|
return
|
|
}
|
|
|
|
this.obj = firstIntersect
|
|
this.md = 0
|
|
return
|
|
}
|
|
}
|
|
|
|
if (this.player.superStrength) {
|
|
this.d += 10
|
|
} else {
|
|
this.d += 5
|
|
}
|
|
} else {
|
|
if (this.player.superStrength) {
|
|
this.d -= 10
|
|
} else {
|
|
this.d -= this.obj ? 5 * (1 - this.obj.weight) : 10
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export class Player extends GameObject {
|
|
constructor (x, y, mh) {
|
|
super(x, y, 60, 55, '#4d4b4f')
|
|
this.x = x
|
|
this.y = y
|
|
|
|
this.hook = new Hook(this, this.x + this.w / 2, this.y + this.h, 20, 20, mh)
|
|
this.hook.r = FULL_ROTATION
|
|
|
|
this.superStrength = false
|
|
}
|
|
|
|
score (object) {
|
|
console.log('Scored', object)
|
|
}
|
|
|
|
draw () {
|
|
// Draw player
|
|
super.draw()
|
|
|
|
// Draw hook
|
|
this.hook.draw()
|
|
|
|
//
|
|
}
|
|
|
|
update (level) {
|
|
if (!level) return
|
|
this.hook.update(level)
|
|
}
|
|
}
|