1
0
forked from noxious/server

A* and move logic improvements

This commit is contained in:
Dennis Postma 2024-08-20 21:33:57 +02:00
parent 079d9408a8
commit acc9eaae9e
3 changed files with 29 additions and 15 deletions

View File

@ -40,21 +40,32 @@ async function moveAlongPath(socket: TSocket, io: Server, path: Array<{ x: numbe
for (let i = 0; i < path.length - 1; i++) { for (let i = 0; i < path.length - 1; i++) {
const startTime = Date.now() const startTime = Date.now()
const start = path[i]
const end = path[i + 1]
while (Date.now() - startTime < stepDuration) { while (Date.now() - startTime < stepDuration) {
if (moveTokens.get(character.id) !== moveToken) return if (moveTokens.get(character.id) !== moveToken) return
const progress = (Date.now() - startTime) / stepDuration const progress = (Date.now() - startTime) / stepDuration
const current = interpolatePosition(path[i], path[i + 1], progress) const current = interpolatePosition(start, end, progress)
if (isObstacle(current, grid)) break if (isObstacle(current, grid)) {
// If obstacle encountered, stop at the last valid position
await updateCharacter(character, start, Rotation.calculate(start.x, start.y, end.x, end.y))
io.in(character.zoneId.toString()).emit('character:moved', character)
return
}
await updateCharacter(character, current, Rotation.calculate(path[i].x, path[i].y, path[i + 1].x, path[i + 1].y)) await updateCharacter(character, current, Rotation.calculate(start.x, start.y, end.x, end.y))
io.in(character.zoneId.toString()).emit('character:moved', character) io.in(character.zoneId.toString()).emit('character:moved', character)
await new Promise((resolve) => setTimeout(resolve, updateInterval)) await new Promise((resolve) => setTimeout(resolve, updateInterval))
} }
} }
// Ensure the character reaches the exact final position
if (moveTokens.get(character.id) === moveToken) { if (moveTokens.get(character.id) === moveToken) {
const finalPosition = path[path.length - 1]
await updateCharacter(character, finalPosition, character.rotation)
character.isMoving = false character.isMoving = false
moveTokens.delete(character.id) moveTokens.delete(character.id)
io.in(character.zoneId.toString()).emit('character:moved', character) io.in(character.zoneId.toString()).emit('character:moved', character)
@ -66,7 +77,14 @@ const interpolatePosition = (start: { x: number; y: number }, end: { x: number;
y: start.y + (end.y - start.y) * progress y: start.y + (end.y - start.y) * progress
}) })
const isObstacle = ({ x, y }: { x: number; y: number }, grid: number[][]) => grid[Math.floor(y)]?.[Math.floor(x)] === 1 const isObstacle = ({ x, y }: { x: number; y: number }, grid: number[][]) => {
const gridX = Math.floor(x)
const gridY = Math.floor(y)
return grid[gridY]?.[gridX] === 1 ||
grid[gridY]?.[Math.ceil(x)] === 1 ||
grid[Math.ceil(y)]?.[gridX] === 1 ||
grid[Math.ceil(y)]?.[Math.ceil(x)] === 1
}
async function updateCharacter(character: ExtendedCharacter, { x, y }: { x: number; y: number }, rotation: number) { async function updateCharacter(character: ExtendedCharacter, { x, y }: { x: number; y: number }, rotation: number) {
Object.assign(character, { position_x: x, position_y: y, rotation }) Object.assign(character, { position_x: x, position_y: y, rotation })

View File

@ -19,12 +19,7 @@ export default function (socket: TSocket, io: Server) {
const character = await CharacterRepository.getByUserAndId(socket.user?.id as number, socket.character?.id as number) const character = await CharacterRepository.getByUserAndId(socket.user?.id as number, socket.character?.id as number)
if (!character) return if (!character) return
// When 1 arg is provided, only send message. 2 includes a title io.emit('notification', { title: 'Message from GM', message: args.join(' ') })
if (args.length === 1) {
return io.emit('notification', { message: args[0] })
}
io.emit('notification', { title: args[0], message: args.slice(1).join(' ') })
callback(true) callback(true)
} catch (error: any) { } catch (error: any) {
console.log(`---Error sending message: ${error.message}`) console.log(`---Error sending message: ${error.message}`)

View File

@ -3,10 +3,10 @@ export type Node = Position & { parent?: Node; g: number; h: number; f: number }
export class AStar { export class AStar {
private static readonly DIRECTIONS = [ private static readonly DIRECTIONS = [
{ x: 0, y: -1 }, { x: 0, y: -1 }, // Up
{ x: 0, y: 1 }, { x: 0, y: 1 }, // Down
{ x: -1, y: 0 }, { x: -1, y: 0 }, // Left
{ x: 1, y: 0 }, { x: 1, y: 0 }, // Right
{ x: -1, y: -1 }, { x: -1, y: -1 },
{ x: -1, y: 1 }, { x: -1, y: 1 },
{ x: 1, y: -1 }, { x: 1, y: -1 },
@ -54,7 +54,8 @@ export class AStar {
private static getDistance(a: Position, b: Position): number { private static getDistance(a: Position, b: Position): number {
const dx = Math.abs(a.x - b.x), const dx = Math.abs(a.x - b.x),
dy = Math.abs(a.y - b.y) dy = Math.abs(a.y - b.y)
return Math.sqrt(dx * dx + dy * dy) // Manhattan distance for straight paths, then Euclidean for diagonals
return dx + dy + (Math.sqrt(2) - 2) * Math.min(dx, dy)
} }
private static reconstructPath(endNode: Node): Node[] { private static reconstructPath(endNode: Node): Node[] {