Pathfinding manager will now return path steps in pixel units by default

This commit is contained in:
Hanusiak Piotr 2022-01-19 12:30:08 +01:00
parent f96eac4737
commit f78392ceab
7 changed files with 50 additions and 45 deletions

View File

@ -34,7 +34,7 @@ import type { ChangeZoneEvent } from "./ChangeZoneEvent";
import type { CameraSetEvent } from "./CameraSetEvent"; import type { CameraSetEvent } from "./CameraSetEvent";
import type { CameraFollowPlayerEvent } from "./CameraFollowPlayerEvent"; import type { CameraFollowPlayerEvent } from "./CameraFollowPlayerEvent";
import { isColorEvent } from "./ColorEvent"; import { isColorEvent } from "./ColorEvent";
import { isWalkPlayerToEventConfig } from "./WalkPlayerToEvent"; import { isMovePlayerToEventConfig } from "./MovePlayerToEvent";
export interface TypedMessageEvent<T> extends MessageEvent { export interface TypedMessageEvent<T> extends MessageEvent {
data: T; data: T;
@ -174,8 +174,8 @@ export const iframeQueryMapTypeGuards = {
query: tg.isUndefined, query: tg.isUndefined,
answer: isPlayerPosition, answer: isPlayerPosition,
}, },
walkPlayerTo: { movePlayerTo: {
query: isWalkPlayerToEventConfig, query: isMovePlayerToEventConfig,
answer: isPlayerPosition, answer: isPlayerPosition,
}, },
}; };

View File

@ -1,6 +1,6 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isWalkPlayerToEventConfig = new tg.IsInterface() export const isMovePlayerToEventConfig = new tg.IsInterface()
.withProperties({ .withProperties({
x: tg.isNumber, x: tg.isNumber,
y: tg.isNumber, y: tg.isNumber,
@ -8,4 +8,4 @@ export const isWalkPlayerToEventConfig = new tg.IsInterface()
}) })
.get(); .get();
export type WalkPlayerToEvent = tg.GuardedType<typeof isWalkPlayerToEventConfig>; export type MovePlayerToEvent = tg.GuardedType<typeof isMovePlayerToEventConfig>;

View File

@ -84,9 +84,9 @@ export class WorkadventurePlayerCommands extends IframeApiContribution<Workadven
}); });
} }
public async walkTo(x: number, y: number, speed: number): Promise<{ x: number; y: number }> { public async moveTo(x: number, y: number, speed: number): Promise<{ x: number; y: number }> {
return await queryWorkadventure({ return await queryWorkadventure({
type: "walkPlayerTo", type: "movePlayerTo",
data: { x, y, speed }, data: { x, y, speed },
}); });
} }

View File

@ -569,7 +569,11 @@ export class GameScene extends DirtyScene {
waScaleManager waScaleManager
); );
this.pathfindingManager = new PathfindingManager(this, this.gameMap.getCollisionsGrid()); this.pathfindingManager = new PathfindingManager(
this,
this.gameMap.getCollisionsGrid(),
this.gameMap.getTileDimensions()
);
biggestAvailableAreaStore.recompute(); biggestAvailableAreaStore.recompute();
this.cameraManager.startFollowPlayer(this.CurrentPlayer); this.cameraManager.startFollowPlayer(this.CurrentPlayer);
@ -1457,9 +1461,20 @@ ${escapedMessage}
}; };
}); });
iframeListener.registerAnswerer("walkPlayerTo", () => { iframeListener.registerAnswerer("movePlayerTo", (message) => {
// TODO: walk player to position, wait for promise to resolve // TODO: walk player to position, wait for promise to resolve
console.log("WALK PLAYER TO ACTION CALLED"); const index = this.getGameMap().getTileIndexAt(message.x, message.y);
const startTile = this.getGameMap().getTileIndexAt(this.CurrentPlayer.x, this.CurrentPlayer.y);
this.getPathfindingManager()
.findPath(startTile, index, true, true)
.then((path) => {
// Remove first step as it is for the tile we are currently standing on
path.shift();
this.CurrentPlayer.setPathToFollow(path);
})
.catch((reason) => {
console.warn(reason);
});
return { return {
x: this.CurrentPlayer.x, x: this.CurrentPlayer.x,
y: this.CurrentPlayer.y, y: this.CurrentPlayer.y,

View File

@ -31,18 +31,11 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface {
.getTileIndexAt(this.gameScene.CurrentPlayer.x, this.gameScene.CurrentPlayer.y); .getTileIndexAt(this.gameScene.CurrentPlayer.x, this.gameScene.CurrentPlayer.y);
this.gameScene this.gameScene
.getPathfindingManager() .getPathfindingManager()
.findPath(startTile, index, true) .findPath(startTile, index, true, true)
.then((path) => { .then((path) => {
const tileDimensions = this.gameScene.getGameMap().getTileDimensions();
const pixelPath = path.map((step) => {
return {
x: step.x * tileDimensions.width + tileDimensions.width * 0.5,
y: step.y * tileDimensions.height + tileDimensions.height * 0.5,
};
});
// Remove first step as it is for the tile we are currently standing on // Remove first step as it is for the tile we are currently standing on
pixelPath.shift(); path.shift();
this.gameScene.CurrentPlayer.setPathToFollow(pixelPath); this.gameScene.CurrentPlayer.setPathToFollow(path);
}) })
.catch((reason) => { .catch((reason) => {
console.warn(reason); console.warn(reason);

View File

@ -6,20 +6,23 @@ export class PathfindingManager {
private easyStar; private easyStar;
private grid: number[][]; private grid: number[][];
private tileDimensions: { width: number; height: number };
constructor(scene: Phaser.Scene, collisionsGrid: number[][]) { constructor(scene: Phaser.Scene, collisionsGrid: number[][], tileDimensions: { width: number; height: number }) {
this.scene = scene; this.scene = scene;
this.easyStar = new EasyStar.js(); this.easyStar = new EasyStar.js();
this.easyStar.enableDiagonals(); this.easyStar.enableDiagonals();
this.grid = collisionsGrid; this.grid = collisionsGrid;
this.tileDimensions = tileDimensions;
this.setEasyStarGrid(collisionsGrid); this.setEasyStarGrid(collisionsGrid);
} }
public async findPath( public async findPath(
start: { x: number; y: number }, start: { x: number; y: number },
end: { x: number; y: number }, end: { x: number; y: number },
measuredInPixels: boolean = true,
tryFindingNearestAvailable: boolean = false tryFindingNearestAvailable: boolean = false
): Promise<{ x: number; y: number }[]> { ): Promise<{ x: number; y: number }[]> {
let endPoints: { x: number; y: number }[] = [end]; let endPoints: { x: number; y: number }[] = [end];
@ -48,12 +51,21 @@ export class PathfindingManager {
// rejected Promise will return undefined for path // rejected Promise will return undefined for path
path = await this.getPath(start, endPoint).catch(); path = await this.getPath(start, endPoint).catch();
if (path && path.length > 0) { if (path && path.length > 0) {
return path; return measuredInPixels ? this.mapTileUnitsToPixels(path) : path;
} }
} }
return []; return [];
} }
private mapTileUnitsToPixels(path: { x: number; y: number }[]): { x: number; y: number }[] {
return path.map((step) => {
return {
x: step.x * this.tileDimensions.width + this.tileDimensions.width * 0.5,
y: step.y * this.tileDimensions.height + this.tileDimensions.height * 0.5,
};
});
}
private getNeighbouringTiles(tile: { x: number; y: number }): { x: number; y: number }[] { private getNeighbouringTiles(tile: { x: number; y: number }): { x: number; y: number }[] {
const xOffsets = [-1, 0, 1, 1, 1, 0, -1, -1]; const xOffsets = [-1, 0, 1, 1, 1, 0, -1, -1];
const yOffsets = [-1, -1, -1, 0, 1, 1, 1, 0]; const yOffsets = [-1, -1, -1, 0, 1, 1, 1, 0];

View File

@ -5,31 +5,20 @@
<script> <script>
window.addEventListener('load', () => { window.addEventListener('load', () => {
//@ts-ignore //@ts-ignore
WA.camera.onCameraUpdate((worldView) => console.log(worldView));
WA.onInit().then(() => { WA.onInit().then(() => {
console.log('After WA init'); console.log('After WA init');
const setCameraButton = document.getElementById('setCameraButton'); const movePlayerButton = document.getElementById('movePlayerButton');
const followPlayerButton = document.getElementById('followPlayerButton');
const xField = document.getElementById('x'); const xField = document.getElementById('x');
const yField = document.getElementById('y'); const yField = document.getElementById('y');
const widthField = document.getElementById('width'); const speedField = document.getElementById('speed');
const heightField = document.getElementById('height');
const smoothField = document.getElementById('smooth');
const lockField = document.getElementById('lock');
setCameraButton.addEventListener('click', () => { movePlayerButton.addEventListener('click', async () => {
WA.camera.set( const position = await WA.player.moveTo(
parseInt(xField.value), parseInt(xField.value),
parseInt(yField.value), parseInt(yField.value),
widthField.value ? parseInt(widthField.value) : undefined, parseInt(speedField.value),
heightField.value ? parseInt(heightField.value) : undefined,
lockField.checked,
smoothField.checked,
); );
}); console.log(position);
followPlayerButton.addEventListener('click', () => {
WA.camera.followPlayer(smoothField.checked);
}); });
}); });
}) })
@ -38,13 +27,9 @@
<body> <body>
X: <input type="text" id="x" value="496" /><br/> X: <input type="text" id="x" value="496" /><br/>
Y: <input type="text" id="y" value="655" /><br/> Y: <input type="text" id="y" value="655" /><br/>
width: <input type="text" id="width" value="480" /><br/> Speed: <input type="text" id="speed" value="20" /><br/>
height: <input type="text" id="height" value="286" /><br/>
Smooth: <input type="checkbox" id="smooth" value=1 /><br/>
Lock: <input type="checkbox" id="lock" value=1 /><br/>
<button id="setCameraButton">Set Camera</button> <button id="movePlayerButton">Move Player</button>
<button id="followPlayerButton">Follow Player</button>
</body> </body>
</html> </html>