From f1c191f61fbe6b0f5b734a30921ad742041c0fa3 Mon Sep 17 00:00:00 2001 From: Thayol Date: Fri, 10 Jan 2025 23:47:58 +0900 Subject: [PATCH] fix waypoints going out of bounds --- src/entity.js | 51 ++++++++++++++++++++++++--------------------------- src/game.js | 8 ++++---- src/index.js | 4 ++-- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/entity.js b/src/entity.js index 2cc0ee9..e1458e3 100644 --- a/src/entity.js +++ b/src/entity.js @@ -2,7 +2,6 @@ import { Vector2 } from 'three' import SAT from 'sat' import SATX from './satx.js' import Pathfind from './pathfind.js' -import Terrain from './terrain.js' export default class Entity { id = crypto.randomUUID() @@ -69,8 +68,19 @@ export default class Entity { return SATX.collideObjects(this.collider, colliders) } + // TODO: calculate convex hulls of collidables because tris handle collisions sequentially moveAction(x, y) { - this.#dest = new Vector2(x, y) + const temp = SATX.fixCollisions(new Vector2(x, y), this.collidables(), this.radius) + // const entity = new Entity() + // entity.teleport(temp.x, temp.y) + // entity.radius = this.radius + // this.game.spawn_entity(entity) + this.#dest = SATX.clamp( + temp, + this.game?.width, + this.game?.height, + this.radius, + ) } state() { @@ -87,9 +97,8 @@ export default class Entity { this.position.set(x, y) } - // TODO: waypoints go out of bounds // TODO: pathfinding stops if wall is clicked (did you forget to fix the destination?) - async takeStep(distanceTraveled = 0) { + takeStep(distanceTraveled = 0) { const speed = (this.speed / (this.game?.tickBudget ?? 1000)) - distanceTraveled const collidables = this.collidables() if (this.#dest != null) { @@ -97,29 +106,12 @@ export default class Entity { if (this.#path.length < 1 || !this.#path.at(-1).equals(fixedDest)) { console.time('pathfinding') - console.time('waypoints') const start = SATX.vectorToFloat32Array(this.position) const goal = SATX.vectorToFloat32Array(fixedDest) const nonUniqueWaypoints = this.waypoints().map((w) => SATX.vectorToFloat32Array(w)).concat([start, goal]) const waypoints = Pathfind.uniqueWaypoints(nonUniqueWaypoints) - - console.timeEnd('waypoints') - console.time('graph') const graph = Pathfind.buildGraph(waypoints, collidables, this.radius) - - // const tunnels = [] - // for (let i = 0; i < graph.length; i += 5) { - // tunnels.push(SATX.entityTunnel(graph[i], graph[i + 1], graph[i + 2], graph[i + 3], 1)) - // } - - // tunnels.map((t) => SATX.satPolygonToVectors(t)).forEach((t) => this.#game.add_terrain(new Terrain(t))) - // this.#dest = null - - console.timeEnd('graph') - console.time('path') this.#path = Pathfind.shortestPath(graph, start, goal).map((waypoint) => new Vector2(waypoint[0], waypoint[1])) - console.log(this.#path) - console.timeEnd('path') console.timeEnd('pathfinding') } @@ -140,7 +132,7 @@ export default class Entity { if (this.position.equals(destination)) { this.#path = this.#path.slice(1) if (this.#path.length > 0) { - await this.takeStep(distance) + this.takeStep(distance) } else { this.#dest = null @@ -150,10 +142,8 @@ export default class Entity { } } - async update() { - await Promise.allSettled([ - this.takeStep(), - ]) + update() { + this.takeStep() } waypoints() { @@ -161,6 +151,13 @@ export default class Entity { const terrainColliders = (this.game?.terrains ?? []) const unadjustedWaypoints = entityColliders.concat(terrainColliders).map((e) => e.unadjustedWaypoints).flat() - return unadjustedWaypoints.map(([waypoint, direction]) => waypoint.clone().add(direction.clone().multiplyScalar(this.radius))) ?? [] + return unadjustedWaypoints.map(([waypoint, direction]) => { + return SATX.clamp( + waypoint.clone().add(direction.clone().multiplyScalar(this.radius)), + this.game?.width, + this.game?.height, + this.radius, + ) + }) ?? [] } } diff --git a/src/game.js b/src/game.js index 8888d80..79128ef 100644 --- a/src/game.js +++ b/src/game.js @@ -42,14 +42,14 @@ export default class Game { } } - async start() { + start() { const start = performance.now() - await this.update() + this.update() setTimeout(() => this.start(), Math.max(0, this.#tickBudget - (performance.now() - start))) } - async update() { - Promise.allSettled(this.#entities.map((e) => e.update())) + update() { + this.#entities.map((e) => e.update()) this.currentTick++ this.eventEmitter.emit('tick') } diff --git a/src/index.js b/src/index.js index afa3fdc..97fbbbb 100644 --- a/src/index.js +++ b/src/index.js @@ -115,9 +115,9 @@ app.listen(port, () => { pole.id = 'pole' game.add_terrain(pole) - entity1.moveAction(1000, 500) + // entity1.moveAction(1000, 500) - setTimeout(() => entity1.moveAction(100, 400), 10) + // setTimeout(() => entity1.moveAction(100, 400), 10) game.start() })