You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.7 KiB
193 lines
4.7 KiB
export class StickFigure { |
|
constructor(x, facing, id, canvas) { |
|
this.canvas = canvas; |
|
this.id = id; |
|
this.x = x; |
|
this.y = canvas.height - 60; |
|
this.facing = facing; |
|
this._lastTx = x; |
|
this._lastTy = this.y; |
|
this._lastUpdateTime = 0; |
|
this._walkTTL = 0; |
|
this.action = "idle"; |
|
this.hitFrame = 0; |
|
this.speed = 2; |
|
this.vx = 0; |
|
this.vy = 0; |
|
this.gravity = 0.5; |
|
this.jumpStrength = -10; |
|
this.onGround = true; |
|
this.talking = false; |
|
this.talkTimer = 0; |
|
this.message = ""; |
|
this.keys = { |
|
a: false, |
|
d: false, |
|
} |
|
this.crouching = false; |
|
this.isPunching = false; |
|
this.punchHasHit = false; |
|
this.sentJoin = false; |
|
this.hp = 100; |
|
this.maxHp = 100; |
|
this.isAlive = true; |
|
this._tx = x; |
|
this._ty = canvas.height - 60; |
|
this._lastTs = 0; |
|
this._tFacing = undefined; |
|
this._lastUpdateTime = Date.now(); |
|
this._updateInterval = 10; |
|
this.baseAttackPower = 14; |
|
this.baseDefense = 14; |
|
} |
|
|
|
update() { |
|
const prevX = this.x; |
|
this._prevY = this.y; |
|
this.vx = 0; |
|
|
|
if (this.keys.a) { |
|
this.vx = -this.speed; |
|
this.facing = -1; |
|
} |
|
|
|
if (this.crouching && this.keys.d) { |
|
this.speed = 0.5; |
|
this.vx = this.speed; |
|
} |
|
if (this.crouching && this.keys.a) { |
|
this.vx = -this.speed; |
|
} |
|
|
|
if (this.keys.d) { |
|
this.vx = this.speed; |
|
this.facing = 1; |
|
} |
|
|
|
this.x += this.vx; |
|
|
|
if (this.isLocal) { |
|
this.vy += this.gravity; |
|
this.y += this.vy; |
|
} |
|
|
|
this.x = Math.max(20, Math.min(this.canvas.width - 20, this.x)); |
|
|
|
if (this.action === "punch") { |
|
this.hitFrame++; |
|
if (this.hitFrame > 15) { |
|
this.action = 'idle'; |
|
this.hitFrame = 0; |
|
this.isPunching = false; |
|
this.punchHasHit = false; |
|
} |
|
} |
|
|
|
if (this.talking) { |
|
this.talkTimer--; |
|
if (this.talkTimer <= 0) { |
|
this.talking = false; |
|
} |
|
} |
|
|
|
if (!this.isLocal |
|
&& typeof this._tx === "number" |
|
&& typeof this._ty === "number") { |
|
const now = Date.now(); |
|
const timeSinceUpdate = now - this._lastUpdateTime; |
|
|
|
const targetLerpTime = 200; |
|
const deltaTime = 16.67; |
|
const lerpFactor = Math.min(1, deltaTime / targetLerpTime); |
|
const stalenessFactor = Math.min(2, timeSinceUpdate / this._updateInterval); |
|
const adjustedLerpFactor = lerpFactor * stalenessFactor; |
|
|
|
const deltaY = Math.abs(this.y - this._ty); |
|
|
|
if (deltaY > 8 || !this.onGround) { |
|
this.x = this._tx; |
|
this.y = this._ty; |
|
} else { |
|
this.x = this.lerp(this.x, this._tx, adjustedLerpFactor); |
|
this.y = this.lerp(this.y, this._ty, adjustedLerpFactor); |
|
} |
|
this.facing = this._tFacing ?? this.facing; |
|
|
|
this.vx = this.x - prevX; |
|
if (Math.abs(this.vx) < 0.5) { |
|
this.vx = 0; |
|
} |
|
} |
|
} |
|
|
|
lerp(a, b, t) { |
|
return a + (b - a) * Math.min(1, t); |
|
} |
|
|
|
applyBuff(type, amount) { |
|
if (type === 'atk') { |
|
this.baseAttackPower += amount; |
|
} |
|
|
|
if (type === 'def') { |
|
this.baseDefense += amount; |
|
} |
|
} |
|
|
|
punch() { |
|
this.isPunching = true; |
|
this.punchHasHit = false; |
|
|
|
if (this.action === 'idle') { |
|
this.action = 'punch'; |
|
this.hitFrame = 0; |
|
} |
|
} |
|
|
|
talk(message) { |
|
this.talking = true; |
|
this.talkTimer = 120; |
|
this.message = message; |
|
} |
|
|
|
jump() { |
|
if (this.onGround) { |
|
this.vy = this.jumpStrength; |
|
this.onGround = false; |
|
} |
|
} |
|
|
|
|
|
|
|
getBodyHitbox() { |
|
const w = 24; |
|
const h = 60 - (this.crouching ? 10 : 0); |
|
return { |
|
x: this.x - w / 2, |
|
y: this.y - 10, |
|
w, |
|
h |
|
}; |
|
} |
|
|
|
getPunchHitbox() { |
|
if (this.action === 'punch' && this.hitFrame < 10) { |
|
const w = 18; |
|
const h = 14; |
|
const frontX = this.x + this.facing * 22; |
|
const x = this.facing === 1 ? frontX : frontX - w; |
|
const y = this.y + (this.crouching ? 18 : 10); |
|
return { |
|
x, |
|
y, |
|
w, |
|
h |
|
}; |
|
} |
|
|
|
return null; |
|
} |
|
|
|
|
|
} |
|
|
|
|