From e4f1fe19f4ab1512c6662d5c9c1653810a4983cb Mon Sep 17 00:00:00 2001 From: Thayol Date: Sun, 19 Jan 2025 20:55:16 +0900 Subject: [PATCH] fix projectile colliders in movement --- public/client.js | 20 ++++++++++---------- src/ability.js | 4 +++- src/entity.js | 5 +++-- src/game.js | 6 +++++- src/projectile.js | 12 ++++++------ src/template.js | 4 +++- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/public/client.js b/public/client.js index f528885..2042003 100644 --- a/public/client.js +++ b/public/client.js @@ -415,17 +415,17 @@ function connectWebSocket() { scene.add(terrain) terrains[t.id] = terrain - // TODO: bboxes aren't tracked and can leak memory - const bboxValues = Object.values(t.bbox) - if (bboxValues.length >= 4) { - const width = (bboxValues[1] - bboxValues[3]) / 100 - const height = (bboxValues[0] - bboxValues[2]) / 100 + // // TODO: bboxes aren't tracked and can leak memory + // const bboxValues = Object.values(t.bbox) + // if (bboxValues.length >= 4) { + // const width = (bboxValues[1] - bboxValues[3]) / 100 + // const height = (bboxValues[0] - bboxValues[2]) / 100 - const bbox = new THREE.Mesh(new THREE.BoxGeometry(width, height, 0.2), bboxMaterial) - bbox.position.set((bboxValues[3] / 100) + (width / 2), (bboxValues[2] / 100) + (height / 2), 0) - bbox.layers.set(1) - scene.add(bbox) - } + // const bbox = new THREE.Mesh(new THREE.BoxGeometry(width, height, 0.2), bboxMaterial) + // bbox.position.set((bboxValues[3] / 100) + (width / 2), (bboxValues[2] / 100) + (height / 2), 0) + // bbox.layers.set(1) + // scene.add(bbox) + // } } terrain.position.set(t.position.x / 100, t.position.y / 100, 0) diff --git a/src/ability.js b/src/ability.js index 894e973..9823fb5 100644 --- a/src/ability.js +++ b/src/ability.js @@ -37,6 +37,7 @@ export default class Ability { effect: function straightShotEffect(caster, cursor) { const ability = this const straightShotCollision = function straightShotCollision(projectile, collidingEntity) { + if (projectile.game == null) { return } if (collidingEntity == null) { return } if (collidingEntity.id == caster.id) { return } if (collidingEntity.team == (caster.team ?? 'unknown')) { return } @@ -173,7 +174,7 @@ export default class Ability { id: 'expose', name: 'Expose', castTime: 0.25, - cooldown: 8, + cooldown: 6, radius: 80, range: 1200, speed: 1700, @@ -181,6 +182,7 @@ export default class Ability { effect: function exposeEffect(caster, cursor) { const ability = this const exposeCollision = function exposeCollision(projectile, collidingEntity) { + if (projectile.game == null) { return } if (collidingEntity == null) { return } if (collidingEntity.team == caster.id) { return } if (collidingEntity.team == (caster.team ?? 'unknown')) { return } diff --git a/src/entity.js b/src/entity.js index 20b2a65..dbe6e60 100644 --- a/src/entity.js +++ b/src/entity.js @@ -23,6 +23,7 @@ export default class Entity { rotation = 0 speed = 400 team = Team.neutral + visionRange = 900 visualRadius = null #attacking = false @@ -326,7 +327,7 @@ export default class Entity { } hasBuff(id) { - return this.buffs.some((it) => it.id == id) + return this.buffs.some((it) => it.id == id) && this.game?.buffs.some((it) => it.id == id) } heal(amount) { @@ -582,7 +583,7 @@ export default class Entity { } if (this.#path.length > 0) { - const speed = (this.speed / (this.game?.tickBudget ?? 1000)) - distanceTraveled + const speed = (this.speed / (this.game?.tickRate ?? 1)) - distanceTraveled const destination = this.#path.at(0) const difference = destination.clone().sub(this.position) const distance = difference.length() diff --git a/src/game.js b/src/game.js index dba85ab..3e63bfc 100644 --- a/src/game.js +++ b/src/game.js @@ -98,6 +98,10 @@ export default class Game { this.currentTick++ } + visionByTeam() { + return null // TODO: vision + } + #calculateTickMetrics() { this.averageTick = Math.floor(10 * this.#timings.reduce((sum, t) => sum += t, 0) / this.#timings.length) / 10 this.secondToSlowestTick = Math.floor(10 * this.#timings.toSorted().at(-2)) / 10 @@ -126,7 +130,7 @@ export default class Game { } if (after - before > tickBudget) { - console.warn(`Can't keep up! A tick took ${taken.toFixed(1)} ms / ${tickBudget} ms. (Behind ${this.#behindMs} ms)`) + console.warn(`Can't keep up! A tick took ${taken.toFixed(1)} ms / ${tickBudget.toFixed(1)} ms. (Behind ${this.#behindMs.toFixed(1)} ms)`) } } } diff --git a/src/projectile.js b/src/projectile.js index 8107c49..6a09eeb 100644 --- a/src/projectile.js +++ b/src/projectile.js @@ -93,16 +93,16 @@ export default class Projectile { const entitiesAndTerrains = this.game?.entities ?? [] const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox)) if (bboxCheckedObstacles.length > 0) { - const colliders = bboxCheckedObstacles.map((it) => it.colliders()).flat() const collider = this.collider() - colliders.filter((it) => SATX.collideObject(collider, it)).forEach((it) => this.#onCollide(this, it)) + const colliding = bboxCheckedObstacles.filter((it) => it.colliders().some((c) => SATX.collideObject(collider, c))) + colliding.forEach((it) => this.#onCollide(this, it)) } } #move() { if (this.destination == null) { return } - const speed = (this.speed / (this.game?.tickBudget ?? 1000)) + const speed = (this.speed / (this.game?.tickRate ?? 1)) const prevPos = this.position.clone() if (this.position.distanceTo(this.destination) < speed) { this.setPosition(this.destination) @@ -113,13 +113,13 @@ export default class Projectile { } if (this.#onCollide != null) { - const bbox = Entity.tunnelBbox(position.x, position.y, destination.x, destination.y, this.radius) + const bbox = Entity.tunnelBbox(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius) const entitiesAndTerrains = this.game?.entities ?? [] const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox)) if (bboxCheckedObstacles.length > 0) { - const colliders = bboxCheckedObstacles.map((it) => it.colliders()).flat() const collider = Entity.tunnelCollider(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius) - colliders.filter((it) => SATX.collideObject(collider, it)).forEach((it) => this.#onCollide(this, it)) + const colliding = bboxCheckedObstacles.filter((it) => it.colliders().some((c) => SATX.collideObject(collider, c))) + colliding.sort((a, b) => a.distanceTo(prevPos) > b.distanceTo(prevPos)).forEach((it) => this.#onCollide(this, it)) } } } diff --git a/src/template.js b/src/template.js index 5e2926e..b200f2c 100644 --- a/src/template.js +++ b/src/template.js @@ -9,10 +9,11 @@ export default class Template { logic: this.#minionLogic(options.route), maxHealth: options.ranged ? 300 : 450, pathfindingCooldown: 0.2, - position: options.route?.at(0) ?? new Vector2(0, 0), + position: options.route?.at(0) ?? options.position ?? new Vector2(0, 0), radius: 48, speed: 325, team, + visionRange: 1200, visualRadius: options.ranged ? 36 : 38, } } @@ -30,6 +31,7 @@ export default class Template { maxHealth: 600, spawnPosition: new Vector2(500, 150), radius: 65, + visionRange: 1350, visualRadius: 40, ...overrides, }