fix pathfinding for real
This commit is contained in:
+3
-1
@@ -87,6 +87,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) {
|
||||
const speed = (this.speed / (this.game?.tickBudget ?? 1000)) - distanceTraveled
|
||||
const collidables = this.collidables()
|
||||
@@ -100,11 +102,11 @@ export default class Entity {
|
||||
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)
|
||||
|
||||
// console.log(Pathfind.formatFloat32Array(graph, 5, true))
|
||||
// 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))
|
||||
|
||||
+60
-60
@@ -46,78 +46,78 @@ app.listen(port, () => {
|
||||
entity1.radius = 50
|
||||
game.spawn_entity(entity1)
|
||||
|
||||
// const entity2 = new Entity()
|
||||
// entity2.id = '2'
|
||||
// entity2.teleport(110, 110)
|
||||
// entity2.radius = 50
|
||||
// game.spawn_entity(entity2)
|
||||
const entity2 = new Entity()
|
||||
entity2.id = '2'
|
||||
entity2.teleport(110, 110)
|
||||
entity2.radius = 50
|
||||
game.spawn_entity(entity2)
|
||||
|
||||
const triangle = new Terrain([
|
||||
{ x: 400, y: 200 },
|
||||
{ x: 400, y: 600 },
|
||||
{ x: 600, y: 300 },
|
||||
])
|
||||
triangle.id = 'triangle'
|
||||
game.add_terrain(triangle)
|
||||
|
||||
// const horseshoe = new Terrain([
|
||||
// const triangle = new Terrain([
|
||||
// { x: 400, y: 200 },
|
||||
// { x: 600, y: 200 },
|
||||
// { x: 700, y: 300 },
|
||||
// { x: 650, y: 600 },
|
||||
// { x: 400, y: 600 },
|
||||
// { x: 400, y: 450 },
|
||||
// { x: 600, y: 500 },
|
||||
// { x: 600, y: 300 },
|
||||
// { x: 400, y: 300 },
|
||||
// ])
|
||||
// horseshoe.id = 'horseshoe'
|
||||
// game.add_terrain(horseshoe)
|
||||
// triangle.id = 'triangle'
|
||||
// game.add_terrain(triangle)
|
||||
|
||||
// const stopsign = new Terrain([
|
||||
// { x: 800, y: 800 },
|
||||
// { x: 900, y: 900 },
|
||||
// { x: 900, y: 1000 },
|
||||
// { x: 800, y: 1100 },
|
||||
// { x: 800, y: 1100 },
|
||||
// { x: 700, y: 1100 },
|
||||
// { x: 600, y: 1000 },
|
||||
// { x: 600, y: 900 },
|
||||
// { x: 700, y: 800 },
|
||||
// ])
|
||||
// stopsign.id = 'stopsign'
|
||||
// game.add_terrain(stopsign)
|
||||
const horseshoe = new Terrain([
|
||||
{ x: 400, y: 200 },
|
||||
{ x: 600, y: 200 },
|
||||
{ x: 700, y: 300 },
|
||||
{ x: 650, y: 600 },
|
||||
{ x: 400, y: 600 },
|
||||
{ x: 400, y: 450 },
|
||||
{ x: 600, y: 500 },
|
||||
{ x: 600, y: 300 },
|
||||
{ x: 400, y: 300 },
|
||||
])
|
||||
horseshoe.id = 'horseshoe'
|
||||
game.add_terrain(horseshoe)
|
||||
|
||||
// const box = new Terrain([
|
||||
// { x: 1200, y: 700 },
|
||||
// { x: 1200, y: 800 },
|
||||
// { x: 1300, y: 800 },
|
||||
// { x: 1300, y: 700 },
|
||||
// ])
|
||||
// box.id = 'box'
|
||||
// game.add_terrain(box)
|
||||
const stopsign = new Terrain([
|
||||
{ x: 800, y: 800 },
|
||||
{ x: 900, y: 900 },
|
||||
{ x: 900, y: 1000 },
|
||||
{ x: 800, y: 1100 },
|
||||
{ x: 800, y: 1100 },
|
||||
{ x: 700, y: 1100 },
|
||||
{ x: 600, y: 1000 },
|
||||
{ x: 600, y: 900 },
|
||||
{ x: 700, y: 800 },
|
||||
])
|
||||
stopsign.id = 'stopsign'
|
||||
game.add_terrain(stopsign)
|
||||
|
||||
// const diamond = new Terrain([
|
||||
// { x: 1000, y: 300 },
|
||||
// { x: 1100, y: 400 },
|
||||
// { x: 1000, y: 500 },
|
||||
// { x: 900, y: 400 },
|
||||
// ])
|
||||
// diamond.id = 'diamond'
|
||||
// game.add_terrain(diamond)
|
||||
const box = new Terrain([
|
||||
{ x: 1200, y: 700 },
|
||||
{ x: 1200, y: 800 },
|
||||
{ x: 1300, y: 800 },
|
||||
{ x: 1300, y: 700 },
|
||||
])
|
||||
box.id = 'box'
|
||||
game.add_terrain(box)
|
||||
|
||||
// const pole = new Terrain([
|
||||
// { x: 400, y: 1000 },
|
||||
// { x: 410, y: 1000 },
|
||||
// { x: 410, y: 1010 },
|
||||
// { x: 400, y: 1010 },
|
||||
// ])
|
||||
// pole.id = 'pole'
|
||||
// game.add_terrain(pole)
|
||||
const diamond = new Terrain([
|
||||
{ x: 1000, y: 300 },
|
||||
{ x: 1100, y: 400 },
|
||||
{ x: 1000, y: 500 },
|
||||
{ x: 900, y: 400 },
|
||||
])
|
||||
diamond.id = 'diamond'
|
||||
game.add_terrain(diamond)
|
||||
|
||||
const pole = new Terrain([
|
||||
{ x: 400, y: 1000 },
|
||||
{ x: 410, y: 1000 },
|
||||
{ x: 410, y: 1010 },
|
||||
{ x: 400, y: 1010 },
|
||||
])
|
||||
pole.id = 'pole'
|
||||
game.add_terrain(pole)
|
||||
|
||||
entity1.moveAction(1000, 500)
|
||||
|
||||
// setTimeout(() => entity1.moveAction(100, 400), 10)
|
||||
setTimeout(() => entity1.moveAction(100, 400), 10)
|
||||
|
||||
game.start()
|
||||
})
|
||||
|
||||
+8
-12
@@ -7,10 +7,11 @@ export default class Pathfind {
|
||||
static precision = 0.001
|
||||
static multiplier = 1000 // (1 / this.precision)
|
||||
|
||||
static key(pos) {
|
||||
return `${pos.x},${pos.y}`
|
||||
static key2(a, b) {
|
||||
return `${a},${b}`
|
||||
}
|
||||
|
||||
// TODO: Value exceeds safe integer limit: collisions cause waypointing anomalies
|
||||
static floatKey4(a, b, c, d) {
|
||||
return Math.floor(a * Pathfind.multiplier) +
|
||||
Math.floor(b * Pathfind.multiplier) * Pathfind.multiplier +
|
||||
@@ -18,16 +19,11 @@ export default class Pathfind {
|
||||
Math.floor(d * Pathfind.multiplier) * Pathfind.multiplier ** 3
|
||||
}
|
||||
|
||||
static floatKey2(a, b) {
|
||||
return Math.floor(a * Pathfind.multiplier) +
|
||||
Math.floor(b * Pathfind.multiplier) * Pathfind.multiplier
|
||||
}
|
||||
|
||||
static uniqueWaypoints(waypoints) {
|
||||
const included = new Set()
|
||||
const uniqueWaypoints = []
|
||||
for (const waypoint of waypoints) {
|
||||
const key = Pathfind.floatKey2(waypoint[0], waypoint[1])
|
||||
const key = Pathfind.key2(waypoint[0], waypoint[1])
|
||||
if (!included.has(key)) {
|
||||
included.add(key)
|
||||
uniqueWaypoints.push(waypoint)
|
||||
@@ -52,16 +48,16 @@ export default class Pathfind {
|
||||
return path
|
||||
}
|
||||
|
||||
const waypointKey = Pathfind.floatKey2(waypoint)
|
||||
const waypointKey = Pathfind.key2(waypoint[0], waypoint[1])
|
||||
if (!visited.has(waypointKey) || visited.get(waypointKey) > cost) {
|
||||
visited.set(waypointKey, cost)
|
||||
|
||||
for (let i = 0; i < graph.length; i += 5) {
|
||||
if (Math.abs(waypoint[0] - graph[i]) < Pathfind.precision && Math.abs(waypoint[1] - graph[i + 1]) < Pathfind.precision) {
|
||||
continue
|
||||
if (Math.abs(waypoint[0] - graph[i]) > Pathfind.precision || Math.abs(waypoint[1] - graph[i + 1]) > Pathfind.precision) {
|
||||
continue // waypoint and graph.from aren't the same (so graph.to isn't a neighbor)
|
||||
}
|
||||
|
||||
const nextKey = `${graph[i + 2]},${graph[i + 3]}`
|
||||
const nextKey = Pathfind.key2(graph[i + 2], graph[i + 3])
|
||||
if (!visited.has(nextKey) || visited.get(nextKey) > cost + graph[i + 4]) {
|
||||
const next = new Float32Array(2)
|
||||
next[0] = graph[i + 2]
|
||||
|
||||
Reference in New Issue
Block a user