fix projectile colliders in movement

This commit is contained in:
2025-01-19 20:55:16 +09:00
parent 072204b902
commit e4f1fe19f4
6 changed files with 30 additions and 21 deletions
+10 -10
View File
@@ -415,17 +415,17 @@ function connectWebSocket() {
scene.add(terrain) scene.add(terrain)
terrains[t.id] = terrain terrains[t.id] = terrain
// TODO: bboxes aren't tracked and can leak memory // // TODO: bboxes aren't tracked and can leak memory
const bboxValues = Object.values(t.bbox) // const bboxValues = Object.values(t.bbox)
if (bboxValues.length >= 4) { // if (bboxValues.length >= 4) {
const width = (bboxValues[1] - bboxValues[3]) / 100 // const width = (bboxValues[1] - bboxValues[3]) / 100
const height = (bboxValues[0] - bboxValues[2]) / 100 // const height = (bboxValues[0] - bboxValues[2]) / 100
const bbox = new THREE.Mesh(new THREE.BoxGeometry(width, height, 0.2), bboxMaterial) // 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.position.set((bboxValues[3] / 100) + (width / 2), (bboxValues[2] / 100) + (height / 2), 0)
bbox.layers.set(1) // bbox.layers.set(1)
scene.add(bbox) // scene.add(bbox)
} // }
} }
terrain.position.set(t.position.x / 100, t.position.y / 100, 0) terrain.position.set(t.position.x / 100, t.position.y / 100, 0)
+3 -1
View File
@@ -37,6 +37,7 @@ export default class Ability {
effect: function straightShotEffect(caster, cursor) { effect: function straightShotEffect(caster, cursor) {
const ability = this const ability = this
const straightShotCollision = function straightShotCollision(projectile, collidingEntity) { const straightShotCollision = function straightShotCollision(projectile, collidingEntity) {
if (projectile.game == null) { return }
if (collidingEntity == null) { return } if (collidingEntity == null) { return }
if (collidingEntity.id == caster.id) { return } if (collidingEntity.id == caster.id) { return }
if (collidingEntity.team == (caster.team ?? 'unknown')) { return } if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
@@ -173,7 +174,7 @@ export default class Ability {
id: 'expose', id: 'expose',
name: 'Expose', name: 'Expose',
castTime: 0.25, castTime: 0.25,
cooldown: 8, cooldown: 6,
radius: 80, radius: 80,
range: 1200, range: 1200,
speed: 1700, speed: 1700,
@@ -181,6 +182,7 @@ export default class Ability {
effect: function exposeEffect(caster, cursor) { effect: function exposeEffect(caster, cursor) {
const ability = this const ability = this
const exposeCollision = function exposeCollision(projectile, collidingEntity) { const exposeCollision = function exposeCollision(projectile, collidingEntity) {
if (projectile.game == null) { return }
if (collidingEntity == null) { return } if (collidingEntity == null) { return }
if (collidingEntity.team == caster.id) { return } if (collidingEntity.team == caster.id) { return }
if (collidingEntity.team == (caster.team ?? 'unknown')) { return } if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
+3 -2
View File
@@ -23,6 +23,7 @@ export default class Entity {
rotation = 0 rotation = 0
speed = 400 speed = 400
team = Team.neutral team = Team.neutral
visionRange = 900
visualRadius = null visualRadius = null
#attacking = false #attacking = false
@@ -326,7 +327,7 @@ export default class Entity {
} }
hasBuff(id) { 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) { heal(amount) {
@@ -582,7 +583,7 @@ export default class Entity {
} }
if (this.#path.length > 0) { 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 destination = this.#path.at(0)
const difference = destination.clone().sub(this.position) const difference = destination.clone().sub(this.position)
const distance = difference.length() const distance = difference.length()
+5 -1
View File
@@ -98,6 +98,10 @@ export default class Game {
this.currentTick++ this.currentTick++
} }
visionByTeam() {
return null // TODO: vision
}
#calculateTickMetrics() { #calculateTickMetrics() {
this.averageTick = Math.floor(10 * this.#timings.reduce((sum, t) => sum += t, 0) / this.#timings.length) / 10 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 this.secondToSlowestTick = Math.floor(10 * this.#timings.toSorted().at(-2)) / 10
@@ -126,7 +130,7 @@ export default class Game {
} }
if (after - before > tickBudget) { 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)`)
} }
} }
} }
+6 -6
View File
@@ -93,16 +93,16 @@ export default class Projectile {
const entitiesAndTerrains = this.game?.entities ?? [] const entitiesAndTerrains = this.game?.entities ?? []
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox)) const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox))
if (bboxCheckedObstacles.length > 0) { if (bboxCheckedObstacles.length > 0) {
const colliders = bboxCheckedObstacles.map((it) => it.colliders()).flat()
const collider = this.collider() 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() { #move() {
if (this.destination == null) { return } 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() const prevPos = this.position.clone()
if (this.position.distanceTo(this.destination) < speed) { if (this.position.distanceTo(this.destination) < speed) {
this.setPosition(this.destination) this.setPosition(this.destination)
@@ -113,13 +113,13 @@ export default class Projectile {
} }
if (this.#onCollide != null) { 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 entitiesAndTerrains = this.game?.entities ?? []
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox)) const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox))
if (bboxCheckedObstacles.length > 0) { 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) 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))
} }
} }
} }
+3 -1
View File
@@ -9,10 +9,11 @@ export default class Template {
logic: this.#minionLogic(options.route), logic: this.#minionLogic(options.route),
maxHealth: options.ranged ? 300 : 450, maxHealth: options.ranged ? 300 : 450,
pathfindingCooldown: 0.2, 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, radius: 48,
speed: 325, speed: 325,
team, team,
visionRange: 1200,
visualRadius: options.ranged ? 36 : 38, visualRadius: options.ranged ? 36 : 38,
} }
} }
@@ -30,6 +31,7 @@ export default class Template {
maxHealth: 600, maxHealth: 600,
spawnPosition: new Vector2(500, 150), spawnPosition: new Vector2(500, 150),
radius: 65, radius: 65,
visionRange: 1350,
visualRadius: 40, visualRadius: 40,
...overrides, ...overrides,
} }