fix vision logic and game tick timer

This commit is contained in:
2025-01-20 11:17:35 +09:00
parent bf38f69071
commit 6b8a220f39
7 changed files with 89 additions and 32 deletions
+18 -7
View File
@@ -7,6 +7,8 @@ import Projectile from './projectile.js'
import Terrain from './terrain.js'
export default class Game {
id = crypto.randomUUID()
abilities = Object.values({...Ability})
buffs = Object.values({...Buff})
averageTick = 0
@@ -16,6 +18,7 @@ export default class Game {
height = 0
projectiles = []
secondToSlowestTick = 0
startTimestamp = 0
terrains = []
tickRate = 30
width = 0
@@ -100,7 +103,9 @@ export default class Game {
start() {
if (this.gameLoopIntervalId != null) { return }
this.gameLoopIntervalId = setInterval(this.#gameLoopCall.bind(this), 1)
this.startTimestamp = performance.now() + (this.currentTick * this.tickBudget)
console.log(`Started game ${this.id} with ${this.tickRate} tps. Starting on tick ${this.currentTick}.`)
this.gameLoopIntervalId = setInterval(this.#gameLoopCall.bind(this), this.tickBudget / 5)
}
stop() {
@@ -108,6 +113,7 @@ export default class Game {
clearInterval(this.gameLoopIntervalId)
this.gameLoopIntervalId = null
console.log(`Stopped game ${this.id}. Stopped on tick ${this.currentTick}.`)
}
subscription(websocket, id) {
@@ -123,8 +129,9 @@ export default class Game {
}
update() {
this.entities.forEach((e) => e.update())
this.projectiles.forEach((p) => p.update())
const callUpdate = function callUpdate(object) { object.update() }
this.entities.forEach(callUpdate)
this.projectiles.forEach(callUpdate)
if (this.#logic != null) {
this.#logic()
}
@@ -151,6 +158,7 @@ export default class Game {
return entityVisionSources.concat(projectileVisionSources)
}
// TODO: castingVision should not reveal casting in non-lanes (= only spawn castingVision if slightly outside regular vision [or obstructeed])
visionByTeam(team) {
const visionSources = this.visionSources(team)
const visibleEntities = new Set(visionSources.map((it) => it.entitiesInVision()).flat())
@@ -180,9 +188,11 @@ export default class Game {
this.update()
const after = performance.now()
const taken = (after - before)
const prevBehind = this.#behindMs
this.#behindMs = Math.max(0, this.#behindMs + taken - tickBudget)
this.#nextTickAt = start + tickBudget - prevBehind
const useAbsoluteBehind = true
const absoluteBehind = Math.max(0, (start - this.startTimestamp) - ((this.currentTick) * tickBudget))
this.#behindMs = absoluteBehind
this.#nextTickAt = start + tickBudget - (useAbsoluteBehind ? absoluteBehind : prevBehind)
this.#timings[this.#currentTiming] = taken
if (this.#currentTiming++ > this.#timings.length) {
@@ -190,7 +200,8 @@ export default class Game {
}
if (after - before > tickBudget) {
console.warn(`Can't keep up! A tick took ${taken.toFixed(1)} ms / ${tickBudget.toFixed(1)} ms. (Behind ${this.#behindMs.toFixed(1)} ms)`)
const behindNotice = absoluteBehind > 0.1 ? `(Was already behind ${absoluteBehind.toFixed(1)} ms)` : ``
console.warn(`Can't keep up! A tick took ${taken.toFixed(1)} ms / ${tickBudget.toFixed(1)} ms. ${behindNotice}`)
}
}
}