From 916bc313560277300202d54a9439a119a30a8bff Mon Sep 17 00:00:00 2001 From: Thayol Date: Wed, 22 Jan 2025 00:16:07 +0900 Subject: [PATCH] fix ghostable entities being pushed by ghosted entities --- src/entity.js | 8 ++++---- src/game.js | 2 +- src/level.js | 45 ++++++++------------------------------------- src/template.js | 9 +-------- 4 files changed, 14 insertions(+), 50 deletions(-) diff --git a/src/entity.js b/src/entity.js index 2327fc6..7f896cd 100644 --- a/src/entity.js +++ b/src/entity.js @@ -289,7 +289,7 @@ export default class Entity { customBboxCollidables(bbox) { const entitiesAndTerrains = (this.game?.entities ?? []).filter((it) => it.id != this.id).concat(this.game?.terrains ?? []) - return entitiesAndTerrains.filter((it) => it.collision && !(this.ghosting && it.ghostable) && SATX.bboxCheck(bbox, it.bbox)) + return entitiesAndTerrains.filter((it) => it.collision && !((this.ghosting && it.ghostable) || (this.ghostable && it.ghosting)) && SATX.bboxCheck(bbox, it.bbox)) } damage(amount, source = null) { @@ -313,6 +313,7 @@ export default class Entity { return this.position.distanceTo(cursor) } + // TODO: cache vision because linear per player connected is better than exponential entitiesInVision() { const entities = this.game?.entities if (entities == null) { return } @@ -350,7 +351,6 @@ export default class Entity { this.health = Math.min(Math.max(0, this.health + amount), this.maxHealth) } - // TODO: something is pushing ghostables out of ghosted entities' way fixPosition() { const fixedPosition = this.fixFuturePosition(this.position) if (this.position.equals(fixedPosition)) { return } @@ -402,7 +402,7 @@ export default class Entity { isInLineOfSight(destination, position = this.position) { const bbox = Entity.tunnelBbox(position.x, position.y, destination.x, destination.y, this.radius) const entitiesAndTerrains = (this.game?.entities ?? []).filter((it) => it.id != this.id).concat(this.game?.terrains ?? []) - const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => it.collision && !(this.ghosting && it.ghostable) && SATX.bboxCheck(bbox, it.bbox)) + const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => it.collision && !((this.ghosting && it.ghostable) || (this.ghostable && it.ghosting)) && SATX.bboxCheck(bbox, it.bbox)) if (bboxCheckedObstacles.length < 1) { return true } const colliders = bboxCheckedObstacles.map((it) => it.colliders()).flat() @@ -428,7 +428,7 @@ export default class Entity { obstaclesInStraightPath(destination, position = this.position) { const bbox = Entity.tunnelBbox(position.x, position.y, destination.x, destination.y, this.radius) const entitiesAndTerrains = (this.game?.entities ?? []).filter((it) => it.id != this.id).concat(this.game?.terrains ?? []) - const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => it.collision && !(this.ghosting && it.ghostable) && SATX.bboxCheck(bbox, it.bbox)) + const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => it.collision && !((this.ghosting && it.ghostable) || (this.ghostable && it.ghosting)) && SATX.bboxCheck(bbox, it.bbox)) if (bboxCheckedObstacles.length < 1) { return [] } const collider = Entity.tunnelCollider(position.x, position.y, destination.x, destination.y, this.radius) diff --git a/src/game.js b/src/game.js index 20d6789..9205057 100644 --- a/src/game.js +++ b/src/game.js @@ -126,7 +126,7 @@ export default class Game { update() { const callUpdate = function callUpdate(object) { object.update() } - this.entities.forEach(callUpdate) + this.entities.forEach(callUpdate) // TODO: entity with lower ID has unfair collision advantage (regular loop + until it fully loops around with an offset?) this.projectiles.forEach(callUpdate) if (this.#logic != null) { this.#logic() diff --git a/src/level.js b/src/level.js index 8b7ca75..e06e3ed 100644 --- a/src/level.js +++ b/src/level.js @@ -9,37 +9,6 @@ export class Dungeon { game.width = 3000 game.height = 3000 - // const playerSpawn = new Vector2(game.width / 2, game.height / 2) - // game.spawnEntity(new Entity(Template.player({ id: '1', spawnPosition: playerSpawn, position: new Vector2(playerSpawn.x - 1300, playerSpawn.y - 500), team: Team.blue }))) - // const dummyLogic = function dummyLogic() { - // const entity = this - // if (entity.position.x > 1250) { - // entity.moveAction(new Vector2(500, entity.position.y)) - // } - // else if (entity.position.x < 550 || entity.destination == null) { - // entity.moveAction(new Vector2(1300, entity.position.y)) - // } - - // if (game.currentTick > 0 && game.currentTick % (6 * game.tickRate) == 0) { - // entity.castAction('q', playerSpawn) - // } - // } - // const dummy = { radius: 100, visualRadius: 50, abilities: { q: Ability.straightShot.id }, logic: dummyLogic } - // game.spawnEntity(new Entity({ ...dummy, position: new Vector2(1 * (game.width / 5), 1 * (game.height / 4)) })) - // game.spawnEntity(new Entity({ ...dummy, position: new Vector2(1 * (game.width / 5), 3 * (game.height / 4)) })) - // game.addTerrain(new Terrain([ - // new Vector2(3.5 * (game.width / 10), 1.6 * (game.height / 5)), - // new Vector2(3.5 * (game.width / 10), 1.4 * (game.height / 5)), - // new Vector2(4 * (game.width / 10), 1.4 * (game.height / 5)), - // new Vector2(4 * (game.width / 10), 1.6 * (game.height / 5)), - // ])) - // game.addTerrain(new Terrain([ - // new Vector2(3 * (game.width / 10), 2 * (game.height / 5)), - // new Vector2(3 * (game.width / 10), 1 * (game.height / 5)), - // new Vector2(4 * (game.width / 10), 1 * (game.height / 5)), - // new Vector2(4 * (game.width / 10), 2 * (game.height / 5)), - // ], false)) - const from = new Vector2(100, 100) game.height = 2000 game.spawnEntity(new Entity(Template.player({ id: '1', spawnPosition: from, pathfindingObstacleLimit: 1, pathfindingCooldown: 0 }))) @@ -66,12 +35,14 @@ export class Ravine { this.terrains.map((points) => new Terrain(points.map((p) => p.multiplyScalar(1.6)))).forEach((terrain) => game.addTerrain(terrain)) game.logic = this.logic.bind(game) - const player1 = new Entity(Template.player({ - id: '1', - spawnPosition: new Vector2(500, 150), - team: Team.blue, - })) - game.spawnEntity(player1) + for (let i = 1; i <= 10; i++) { + const team = i > 5 ? Team.blue : Team.red + game.spawnEntity(new Entity(Template.player({ + id: `${i}`, + spawnPosition: new Vector2(500, 150), + team, + }))) + } game.start() } diff --git a/src/template.js b/src/template.js index d7b2ff7..61caac0 100644 --- a/src/template.js +++ b/src/template.js @@ -42,7 +42,6 @@ export default class Template { static #minionLogic(route = [], odd = false) { const checkpointSize = 300 - const maxDestDistance = 100 const recalculateDestRadius = 50 const aggroRadius = 500 @@ -62,7 +61,7 @@ export default class Template { entity.attackAction(target.position) } - if (route.length > 0 && target == null) { + if ((route.length > 0 || entity.attacking) && target == null) { const routeIndex = entity.memory.routeCheckpoint ?? 0 const goal = route[routeIndex].clone() if (goal instanceof Vector2) { @@ -73,12 +72,6 @@ export default class Template { } if ((entity.destination?.distanceTo(entity.position) ?? 0) < recalculateDestRadius) { - // const distanceToGoal = entity.distanceTo(goal) - // if (distanceToGoal > maxDestDistance) { - // const direction = goal.clone().sub(entity.position).normalize().multiplyScalar(maxDestDistance) - // goal.copy(entity.position.clone().add(direction)) - // } - entity.ghosting = true entity.moveAction(goal) }