Merge branch 'develop' of github.com:thecodingmachine/workadventure
This commit is contained in:
commit
e62fc4beed
@ -173,6 +173,37 @@ Example:
|
||||
WA.player.state.toto //will retrieve the variable
|
||||
```
|
||||
|
||||
### Move player to position
|
||||
```typescript
|
||||
WA.player.moveTo(x: number, y: number, speed?: number): Promise<{ x: number, y: number, cancelled: boolean }>;
|
||||
```
|
||||
Player will try to find shortest path to the destination point and proceed to move there.
|
||||
```typescript
|
||||
// Let's move player to x: 250 y: 250 with speed of 10
|
||||
WA.player.moveTo(250, 250, 10);
|
||||
```
|
||||
You can also chain movement like this:
|
||||
```typescript
|
||||
// Player will move to the next point after reaching first one
|
||||
await WA.player.moveTo(250, 250, 10);
|
||||
await WA.player.moveTo(500, 0, 10);
|
||||
```
|
||||
Or like this:
|
||||
```typescript
|
||||
// Player will move to the next point after reaching first one or stop if the movement was cancelled
|
||||
WA.player.moveTo(250, 250, 10).then((result) => {
|
||||
if (!result.cancelled) {
|
||||
WA.player.moveTo(500, 0, 10);
|
||||
}
|
||||
});
|
||||
```
|
||||
It is possible to get the information about current player's position on stop and if the movement was interrupted
|
||||
```typescript
|
||||
// Result will store x and y of Player at the moment of movement's end and information if the movement was interrupted
|
||||
const result = await WA.player.moveTo(250, 250, 10);
|
||||
// result: { x: number, y: number, cancelled: boolean }
|
||||
```
|
||||
|
||||
### Set the outline color of the player
|
||||
```
|
||||
WA.player.setOutlineColor(red: number, green: number, blue: number): Promise<void>;
|
||||
|
@ -8,6 +8,7 @@ If you use group layers in your map, to reference a layer in a group you will ne
|
||||
together.
|
||||
|
||||
Example :
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<img src="images/groupLayer.png" class="figure-img img-fluid rounded" alt="" />
|
||||
@ -16,10 +17,10 @@ Example :
|
||||
|
||||
The name of the layers of this map are :
|
||||
|
||||
* `entries/start`
|
||||
* `bottom/ground/under`
|
||||
* `bottom/build/carpet`
|
||||
* `wall`
|
||||
- `entries/start`
|
||||
- `bottom/ground/under`
|
||||
- `bottom/build/carpet`
|
||||
- `wall`
|
||||
|
||||
### Detecting when the user enters/leaves a layer
|
||||
|
||||
@ -30,17 +31,18 @@ WA.room.onLeaveLayer(name: string): Subscription
|
||||
|
||||
Listens to the position of the current user. The event is triggered when the user enters or leaves a given layer.
|
||||
|
||||
* **name**: the name of the layer who as defined in Tiled.
|
||||
- **name**: the name of the layer who as defined in Tiled.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
WA.room.onEnterLayer('myLayer').subscribe(() => {
|
||||
WA.chat.sendChatMessage("Hello!", 'Mr Robot');
|
||||
```ts
|
||||
const myLayerSubscriber = WA.room.onEnterLayer("myLayer").subscribe(() => {
|
||||
WA.chat.sendChatMessage("Hello!", "Mr Robot");
|
||||
});
|
||||
|
||||
WA.room.onLeaveLayer('myLayer').subscribe(() => {
|
||||
WA.chat.sendChatMessage("Goodbye!", 'Mr Robot');
|
||||
WA.room.onLeaveLayer("myLayer").subscribe(() => {
|
||||
WA.chat.sendChatMessage("Goodbye!", "Mr Robot");
|
||||
myLayerSubscriber.unsubscribe();
|
||||
});
|
||||
```
|
||||
|
||||
@ -56,10 +58,10 @@ layer in that group layer.
|
||||
|
||||
Example :
|
||||
|
||||
```javascript
|
||||
WA.room.showLayer('bottom');
|
||||
```ts
|
||||
WA.room.showLayer("bottom");
|
||||
//...
|
||||
WA.room.hideLayer('bottom');
|
||||
WA.room.hideLayer("bottom");
|
||||
```
|
||||
|
||||
### Set/Create properties in a layer
|
||||
@ -76,8 +78,8 @@ To unset a property from a layer, use `setProperty` with `propertyValue` set to
|
||||
|
||||
Example :
|
||||
|
||||
```javascript
|
||||
WA.room.setProperty('wikiLayer', 'openWebsite', 'https://www.wikipedia.org/');
|
||||
```ts
|
||||
WA.room.setProperty("wikiLayer", "openWebsite", "https://www.wikipedia.org/");
|
||||
```
|
||||
|
||||
### Get the room id
|
||||
@ -92,9 +94,9 @@ The ID of the current room is available from the `WA.room.id` property.
|
||||
|
||||
```typescript
|
||||
WA.onInit().then(() => {
|
||||
console.log('Room id: ', WA.room.id);
|
||||
console.log("Room id: ", WA.room.id);
|
||||
// Will output something like: 'https://play.workadventu.re/@/myorg/myworld/myroom', or 'https://play.workadventu.re/_/global/mymap.org/map.json"
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
### Get the map URL
|
||||
@ -109,9 +111,9 @@ The URL of the map is available from the `WA.room.mapURL` property.
|
||||
|
||||
```typescript
|
||||
WA.onInit().then(() => {
|
||||
console.log('Map URL: ', WA.room.mapURL);
|
||||
console.log("Map URL: ", WA.room.mapURL);
|
||||
// Will output something like: 'https://mymap.org/map.json"
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
### Getting map data
|
||||
@ -122,7 +124,7 @@ WA.room.getTiledMap(): Promise<ITiledMap>
|
||||
|
||||
Returns a promise that resolves to the JSON map file.
|
||||
|
||||
```javascript
|
||||
```ts
|
||||
const map = await WA.room.getTiledMap();
|
||||
console.log("Map generated with Tiled version ", map.tiledversion);
|
||||
```
|
||||
@ -140,6 +142,7 @@ WA.room.setTiles(tiles: TileDescriptor[]): void
|
||||
Replace the tile at the `x` and `y` coordinates in the layer named `layer` by the tile with the id `tile`.
|
||||
|
||||
If `tile` is a string, it's not the id of the tile but the value of the property `name`.
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<img src="images/nameIndexProperty.png" class="figure-img img-fluid rounded" alt="" />
|
||||
@ -148,10 +151,10 @@ If `tile` is a string, it's not the id of the tile but the value of the property
|
||||
|
||||
`TileDescriptor` has the following attributes :
|
||||
|
||||
* **x (number) :** The coordinate x of the tile that you want to replace.
|
||||
* **y (number) :** The coordinate y of the tile that you want to replace.
|
||||
* **tile (number | string) :** The id of the tile that will be placed in the map.
|
||||
* **layer (string) :** The name of the layer where the tile will be placed.
|
||||
- **x (number) :** The coordinate x of the tile that you want to replace.
|
||||
- **y (number) :** The coordinate y of the tile that you want to replace.
|
||||
- **tile (number | string) :** The id of the tile that will be placed in the map.
|
||||
- **layer (string) :** The name of the layer where the tile will be placed.
|
||||
|
||||
**Important !** : If you use `tile` as a number, be sure to add the `firstgid` of the tileset of the tile that you want
|
||||
to the id of the tile in Tiled Editor.
|
||||
@ -160,12 +163,12 @@ Note: If you want to unset a tile, use `setTiles` with `tile` set to `null`.
|
||||
|
||||
Example :
|
||||
|
||||
```javascript
|
||||
```ts
|
||||
WA.room.setTiles([
|
||||
{ x: 6, y: 4, tile: 'blue', layer: 'setTiles' },
|
||||
{ x: 7, y: 4, tile: 109, layer: 'setTiles' },
|
||||
{ x: 8, y: 4, tile: 109, layer: 'setTiles' },
|
||||
{ x: 9, y: 4, tile: 'blue', layer: 'setTiles' }
|
||||
{ x: 6, y: 4, tile: "blue", layer: "setTiles" },
|
||||
{ x: 7, y: 4, tile: 109, layer: "setTiles" },
|
||||
{ x: 8, y: 4, tile: 109, layer: "setTiles" },
|
||||
{ x: 9, y: 4, tile: "blue", layer: "setTiles" },
|
||||
]);
|
||||
```
|
||||
|
||||
@ -179,10 +182,10 @@ Load a tileset in JSON format from an url and return the id of the first tile of
|
||||
|
||||
You can create a tileset file in Tile Editor.
|
||||
|
||||
```javascript
|
||||
```ts
|
||||
WA.room.loadTileset("Assets/Tileset.json").then((firstId) => {
|
||||
WA.room.setTiles([{ x: 4, y: 4, tile: firstId, layer: 'bottom' }]);
|
||||
})
|
||||
WA.room.setTiles([{ x: 4, y: 4, tile: firstId, layer: "bottom" }]);
|
||||
});
|
||||
```
|
||||
|
||||
## Embedding websites in a map
|
||||
@ -199,10 +202,10 @@ WA.room.website.get(objectName: string): Promise<EmbeddedWebsite>
|
||||
You can get an instance of an embedded website by using the `WA.room.website.get()` method. It returns a promise of
|
||||
an `EmbeddedWebsite` instance.
|
||||
|
||||
```javascript
|
||||
```ts
|
||||
// Get an existing website object where 'my_website' is the name of the object (on any layer object of the map)
|
||||
const website = await WA.room.website.get('my_website');
|
||||
website.url = 'https://example.com';
|
||||
const website = await WA.room.website.get("my_website");
|
||||
website.url = "https://example.com";
|
||||
website.visible = true;
|
||||
```
|
||||
|
||||
@ -231,7 +234,7 @@ interface CreateEmbeddedWebsiteEvent {
|
||||
You can create an instance of an embedded website by using the `WA.room.website.create()` method. It returns
|
||||
an `EmbeddedWebsite` instance.
|
||||
|
||||
```javascript
|
||||
```ts
|
||||
// Create a new website object
|
||||
const website = WA.room.website.create({
|
||||
name: "my_website",
|
||||
@ -269,10 +272,10 @@ class EmbeddedWebsite {
|
||||
visible: boolean;
|
||||
allow: string;
|
||||
allowApi: boolean;
|
||||
x: number; // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||
y: number; // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||
width: number; // In "game" pixels
|
||||
height: number; // In "game" pixels
|
||||
x: number; // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||
y: number; // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||
width: number; // In "game" pixels
|
||||
height: number; // In "game" pixels
|
||||
origin: "player" | "map";
|
||||
scale: number;
|
||||
}
|
||||
@ -282,4 +285,3 @@ When you modify a property of an `EmbeddedWebsite` instance, the iframe is autom
|
||||
|
||||
{.alert.alert-warning} The websites you add/edit/delete via the scripting API are only shown locally. If you want them
|
||||
to be displayed for every player, you can use [variables](api-start.md) to share a common state between all users.
|
||||
|
||||
|
@ -34,6 +34,8 @@ import type { ChangeZoneEvent } from "./ChangeZoneEvent";
|
||||
import type { CameraSetEvent } from "./CameraSetEvent";
|
||||
import type { CameraFollowPlayerEvent } from "./CameraFollowPlayerEvent";
|
||||
import { isColorEvent } from "./ColorEvent";
|
||||
import { isMovePlayerToEventConfig } from "./MovePlayerToEvent";
|
||||
import { isMovePlayerToEventAnswer } from "./MovePlayerToEventAnswer";
|
||||
import { isGetPropertyEvent } from "./GetPropertyEvent";
|
||||
|
||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||
@ -178,6 +180,10 @@ export const iframeQueryMapTypeGuards = {
|
||||
query: tg.isUndefined,
|
||||
answer: isPlayerPosition,
|
||||
},
|
||||
movePlayerTo: {
|
||||
query: isMovePlayerToEventConfig,
|
||||
answer: isMovePlayerToEventAnswer,
|
||||
},
|
||||
};
|
||||
|
||||
type GuardedType<T> = T extends (x: unknown) => x is infer T ? T : never;
|
||||
|
11
front/src/Api/Events/MovePlayerToEvent.ts
Normal file
11
front/src/Api/Events/MovePlayerToEvent.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
export const isMovePlayerToEventConfig = new tg.IsInterface()
|
||||
.withProperties({
|
||||
x: tg.isNumber,
|
||||
y: tg.isNumber,
|
||||
speed: tg.isOptional(tg.isNumber),
|
||||
})
|
||||
.get();
|
||||
|
||||
export type MovePlayerToEvent = tg.GuardedType<typeof isMovePlayerToEventConfig>;
|
11
front/src/Api/Events/MovePlayerToEventAnswer.ts
Normal file
11
front/src/Api/Events/MovePlayerToEventAnswer.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
export const isMovePlayerToEventAnswer = new tg.IsInterface()
|
||||
.withProperties({
|
||||
x: tg.isNumber,
|
||||
y: tg.isNumber,
|
||||
cancelled: tg.isBoolean,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type MovePlayerToEventAnswer = tg.GuardedType<typeof isMovePlayerToEventAnswer>;
|
@ -84,6 +84,13 @@ export class WorkadventurePlayerCommands extends IframeApiContribution<Workadven
|
||||
});
|
||||
}
|
||||
|
||||
public async moveTo(x: number, y: number, speed?: number): Promise<{ x: number; y: number; cancelled: boolean }> {
|
||||
return await queryWorkadventure({
|
||||
type: "movePlayerTo",
|
||||
data: { x, y, speed },
|
||||
});
|
||||
}
|
||||
|
||||
get userRoomToken(): string | undefined {
|
||||
if (userRoomToken === undefined) {
|
||||
throw new Error(
|
||||
|
@ -586,7 +586,11 @@ export class GameScene extends DirtyScene {
|
||||
waScaleManager
|
||||
);
|
||||
|
||||
this.pathfindingManager = new PathfindingManager(this, this.gameMap.getCollisionsGrid());
|
||||
this.pathfindingManager = new PathfindingManager(
|
||||
this,
|
||||
this.gameMap.getCollisionsGrid(),
|
||||
this.gameMap.getTileDimensions()
|
||||
);
|
||||
biggestAvailableAreaStore.recompute();
|
||||
this.cameraManager.startFollowPlayer(this.CurrentPlayer);
|
||||
|
||||
@ -1489,6 +1493,17 @@ export class GameScene extends DirtyScene {
|
||||
y: this.CurrentPlayer.y,
|
||||
};
|
||||
});
|
||||
|
||||
iframeListener.registerAnswerer("movePlayerTo", async (message) => {
|
||||
const index = this.getGameMap().getTileIndexAt(message.x, message.y);
|
||||
const startTile = this.getGameMap().getTileIndexAt(this.CurrentPlayer.x, this.CurrentPlayer.y);
|
||||
const path = await this.getPathfindingManager().findPath(startTile, index, true, true);
|
||||
path.shift();
|
||||
if (path.length === 0) {
|
||||
throw new Error("no path available");
|
||||
}
|
||||
return this.CurrentPlayer.setPathToFollow(path, message.speed);
|
||||
});
|
||||
}
|
||||
|
||||
private setPropertyLayer(
|
||||
|
@ -12,6 +12,8 @@ export const requestEmoteEventName = "requestEmote";
|
||||
|
||||
export class Player extends Character {
|
||||
private pathToFollow?: { x: number; y: number }[];
|
||||
private followingPathPromiseResolve?: (result: { x: number; y: number; cancelled: boolean }) => void;
|
||||
private pathWalkingSpeed?: number;
|
||||
|
||||
constructor(
|
||||
Scene: GameScene,
|
||||
@ -43,7 +45,7 @@ export class Player extends Character {
|
||||
}
|
||||
|
||||
if (this.pathToFollow && activeUserInputEvents.anyExcept(UserInputEvent.SpeedUp)) {
|
||||
this.pathToFollow = undefined;
|
||||
this.finishFollowingPath(true);
|
||||
}
|
||||
|
||||
let x = 0;
|
||||
@ -68,9 +70,22 @@ export class Player extends Character {
|
||||
this.scene.connection?.emitFollowConfirmation();
|
||||
}
|
||||
|
||||
public setPathToFollow(path: { x: number; y: number }[]): void {
|
||||
public async setPathToFollow(
|
||||
path: { x: number; y: number }[],
|
||||
speed?: number
|
||||
): Promise<{ x: number; y: number; cancelled: boolean }> {
|
||||
const isPreviousPathInProgress = this.pathToFollow !== undefined && this.pathToFollow.length > 0;
|
||||
// take collider offset into consideraton
|
||||
this.pathToFollow = this.adjustPathToFollowToColliderBounds(path);
|
||||
this.pathWalkingSpeed = speed;
|
||||
return new Promise((resolve) => {
|
||||
this.followingPathPromiseResolve?.call(this, { x: this.x, y: this.y, cancelled: isPreviousPathInProgress });
|
||||
this.followingPathPromiseResolve = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
private deduceSpeed(speedUp: boolean, followMode: boolean): number {
|
||||
return this.pathWalkingSpeed ? this.pathWalkingSpeed : speedUp && !followMode ? 25 : 9;
|
||||
}
|
||||
|
||||
private adjustPathToFollowToColliderBounds(path: { x: number; y: number }[]): { x: number; y: number }[] {
|
||||
@ -95,8 +110,8 @@ export class Player extends Character {
|
||||
|
||||
// Compute movement deltas
|
||||
const followMode = get(followStateStore) !== "off";
|
||||
const speedup = activeEvents.get(UserInputEvent.SpeedUp) && !followMode ? 25 : 9;
|
||||
const moveAmount = speedup * 20;
|
||||
const speed = this.deduceSpeed(activeEvents.get(UserInputEvent.SpeedUp), followMode);
|
||||
const moveAmount = speed * 20;
|
||||
x = x * moveAmount;
|
||||
y = y * moveAmount;
|
||||
|
||||
@ -148,8 +163,8 @@ export class Player extends Character {
|
||||
}
|
||||
|
||||
private computeFollowPathMovement(): number[] {
|
||||
if (this.pathToFollow?.length === 0) {
|
||||
this.pathToFollow = undefined;
|
||||
if (this.pathToFollow !== undefined && this.pathToFollow.length === 0) {
|
||||
this.finishFollowingPath();
|
||||
}
|
||||
if (!this.pathToFollow) {
|
||||
return [0, 0];
|
||||
@ -166,6 +181,12 @@ export class Player extends Character {
|
||||
return this.getMovementDirection(xDistance, yDistance, distance);
|
||||
}
|
||||
|
||||
private finishFollowingPath(cancelled: boolean = false): void {
|
||||
this.pathToFollow = undefined;
|
||||
this.pathWalkingSpeed = undefined;
|
||||
this.followingPathPromiseResolve?.call(this, { x: this.x, y: this.y, cancelled });
|
||||
}
|
||||
|
||||
private getMovementDirection(xDistance: number, yDistance: number, distance: number): [number, number] {
|
||||
return [xDistance / Math.sqrt(distance), yDistance / Math.sqrt(distance)];
|
||||
}
|
||||
|
@ -31,18 +31,11 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface {
|
||||
.getTileIndexAt(this.gameScene.CurrentPlayer.x, this.gameScene.CurrentPlayer.y);
|
||||
this.gameScene
|
||||
.getPathfindingManager()
|
||||
.findPath(startTile, index, true)
|
||||
.findPath(startTile, index, true, true)
|
||||
.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
|
||||
pixelPath.shift();
|
||||
this.gameScene.CurrentPlayer.setPathToFollow(pixelPath);
|
||||
path.shift();
|
||||
this.gameScene.CurrentPlayer.setPathToFollow(path).catch((reason) => {});
|
||||
})
|
||||
.catch((reason) => {
|
||||
console.warn(reason);
|
||||
|
@ -54,7 +54,7 @@ export class UserInputManager {
|
||||
private scene: Phaser.Scene;
|
||||
private isInputDisabled: boolean;
|
||||
|
||||
private joystick!: MobileJoystick;
|
||||
private joystick?: MobileJoystick;
|
||||
private joystickEvents = new ActiveEventList();
|
||||
private joystickForceThreshold = 60;
|
||||
private joystickForceAccuX = 0;
|
||||
@ -81,9 +81,9 @@ export class UserInputManager {
|
||||
initVirtualJoystick() {
|
||||
this.joystick = new MobileJoystick(this.scene);
|
||||
this.joystick.on("update", () => {
|
||||
this.joystickForceAccuX = this.joystick.forceX ? this.joystickForceAccuX : 0;
|
||||
this.joystickForceAccuY = this.joystick.forceY ? this.joystickForceAccuY : 0;
|
||||
const cursorKeys = this.joystick.createCursorKeys();
|
||||
this.joystickForceAccuX = this.joystick?.forceX ? this.joystickForceAccuX : 0;
|
||||
this.joystickForceAccuY = this.joystick?.forceY ? this.joystickForceAccuY : 0;
|
||||
const cursorKeys = this.joystick?.createCursorKeys();
|
||||
for (const name in cursorKeys) {
|
||||
const key = cursorKeys[name as Direction];
|
||||
switch (name) {
|
||||
@ -192,7 +192,7 @@ export class UserInputManager {
|
||||
return eventsMap;
|
||||
}
|
||||
this.joystickEvents.forEach((value, key) => {
|
||||
if (value) {
|
||||
if (value && this.joystick) {
|
||||
switch (key) {
|
||||
case UserInputEvent.MoveUp:
|
||||
case UserInputEvent.MoveDown:
|
||||
@ -253,7 +253,7 @@ export class UserInputManager {
|
||||
this.scene.input.on(
|
||||
Phaser.Input.Events.POINTER_UP,
|
||||
(pointer: Phaser.Input.Pointer, gameObjects: Phaser.GameObjects.GameObject[]) => {
|
||||
this.joystick.hide();
|
||||
this.joystick?.hide();
|
||||
this.userInputHandler.handlePointerUpEvent(pointer, gameObjects);
|
||||
}
|
||||
);
|
||||
@ -267,9 +267,9 @@ export class UserInputManager {
|
||||
this.userInputHandler.handlePointerDownEvent(pointer, gameObjects);
|
||||
// Let's only display the joystick if there is one finger on the screen
|
||||
if ((pointer.event as TouchEvent).touches.length === 1) {
|
||||
this.joystick.showAt(pointer.x, pointer.y);
|
||||
this.joystick?.showAt(pointer.x, pointer.y);
|
||||
} else {
|
||||
this.joystick.hide();
|
||||
this.joystick?.hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -6,20 +6,23 @@ export class PathfindingManager {
|
||||
|
||||
private easyStar;
|
||||
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.easyStar = new EasyStar.js();
|
||||
this.easyStar.enableDiagonals();
|
||||
|
||||
this.grid = collisionsGrid;
|
||||
this.tileDimensions = tileDimensions;
|
||||
this.setEasyStarGrid(collisionsGrid);
|
||||
}
|
||||
|
||||
public async findPath(
|
||||
start: { x: number; y: number },
|
||||
end: { x: number; y: number },
|
||||
measuredInPixels: boolean = true,
|
||||
tryFindingNearestAvailable: boolean = false
|
||||
): Promise<{ x: number; y: number }[]> {
|
||||
let endPoints: { x: number; y: number }[] = [end];
|
||||
@ -48,12 +51,21 @@ export class PathfindingManager {
|
||||
// rejected Promise will return undefined for path
|
||||
path = await this.getPath(start, endPoint).catch();
|
||||
if (path && path.length > 0) {
|
||||
return path;
|
||||
return measuredInPixels ? this.mapTileUnitsToPixels(path) : path;
|
||||
}
|
||||
}
|
||||
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 }[] {
|
||||
const xOffsets = [-1, 0, 1, 1, 1, 0, -1, -1];
|
||||
const yOffsets = [-1, -1, -1, 0, 1, 1, 1, 0];
|
||||
|
207
maps/tests/MovePlayer/move_player_api_test.json
Normal file
207
maps/tests/MovePlayer/move_player_api_test.json
Normal file
@ -0,0 +1,207 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":30,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":30,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"openWebsite",
|
||||
"type":"string",
|
||||
"value":"script.php"
|
||||
},
|
||||
{
|
||||
"name":"openWebsiteAllowApi",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":30,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 28, 29, 28, 29, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 0, 0, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 0, 0, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 7, 6, 7, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 7, 6, 7, 0, 17, 18, 17, 18, 17, 18, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 17, 18, 17, 18, 0, 28, 29, 28, 29, 28, 29, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 28, 29, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":30,
|
||||
"id":6,
|
||||
"name":"furnitures",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":30,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":30,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":30,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":159.371714951095,
|
||||
"id":4,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"MS Shell Dlg 2",
|
||||
"pixelsize":21,
|
||||
"text":"Set position of where you want the player character to move to. On movement's end or interruption, player's current position will be logged into the console",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":315.438,
|
||||
"x":64.7309301350722,
|
||||
"y":95.2559217512811
|
||||
},
|
||||
{
|
||||
"height":30.8202477876106,
|
||||
"id":8,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"MS Shell Dlg 2",
|
||||
"pixelsize":21,
|
||||
"text":"x: 16 y: 16",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":111.991330228225,
|
||||
"x":39.0206367023754,
|
||||
"y":2.47529762459247
|
||||
},
|
||||
{
|
||||
"height":30.8202,
|
||||
"id":9,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"MS Shell Dlg 2",
|
||||
"pixelsize":21,
|
||||
"text":"x: 464 y: 432",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":149.997520726595,
|
||||
"x":483.920662086633,
|
||||
"y":417.193532976246
|
||||
},
|
||||
{
|
||||
"height":113.333333333333,
|
||||
"id":10,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"MS Shell Dlg 2",
|
||||
"pixelsize":21,
|
||||
"text":"Top: 256\/512 Center: 496\/655 Width: 480 Height: 286",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":172,
|
||||
"x":256,
|
||||
"y":512
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":7,
|
||||
"nextobjectid":11,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"openWebsite",
|
||||
"type":"string",
|
||||
"value":"script.php"
|
||||
},
|
||||
{
|
||||
"name":"openWebsiteAllowApi",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.7.2",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"..\/tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tiles":[
|
||||
{
|
||||
"id":16,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":17,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":27,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":28,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
}],
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":"1.6",
|
||||
"width":30
|
||||
}
|
48
maps/tests/MovePlayer/script.php
Normal file
48
maps/tests/MovePlayer/script.php
Normal file
@ -0,0 +1,48 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="<?php echo $_SERVER["FRONT_URL"] ?>/iframe_api.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', () => {
|
||||
//@ts-ignore
|
||||
WA.onInit().then(() => {
|
||||
console.log('After WA init');
|
||||
const movePlayerButton = document.getElementById('movePlayerButton');
|
||||
const randomChainedMovementButton = document.getElementById('randomChainedMovementButton');
|
||||
const xField = document.getElementById('x');
|
||||
const yField = document.getElementById('y');
|
||||
const speedField = document.getElementById('speed');
|
||||
|
||||
randomChainedMovementButton.addEventListener('click', async () => {
|
||||
WA.player.moveTo(500, 500, 10)
|
||||
const result = await WA.player.moveTo(100, 100, 10).then((result) => {
|
||||
if (result.completed)
|
||||
if (result.cancelled) {
|
||||
return;
|
||||
}
|
||||
WA.player.moveTo(500, 100, 20);
|
||||
});
|
||||
});
|
||||
|
||||
movePlayerButton.addEventListener('click', async () => {
|
||||
const position = await WA.player.moveTo(
|
||||
parseInt(xField.value),
|
||||
parseInt(yField.value),
|
||||
parseInt(speedField.value),
|
||||
);
|
||||
console.log(position);
|
||||
});
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
X: <input type="text" id="x" value="496" /><br/>
|
||||
Y: <input type="text" id="y" value="655" /><br/>
|
||||
Speed: <input type="text" id="speed" value="20" /><br/>
|
||||
|
||||
<button id="movePlayerButton">Move Player</button>
|
||||
<button id="randomChainedMovementButton">Do random chained movement</button>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -227,6 +227,14 @@
|
||||
<a href="#" class="testLink" data-testmap="CameraApi/camera_api_test.json" target="_blank">Test camera API</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-set-tiles"> Success <input type="radio" name="test-set-tiles"> Failure <input type="radio" name="test-set-tiles" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="MovePlayer/move_player_api_test.json" target="_blank">Test Player Movement API</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-variables"> Success <input type="radio" name="test-variables"> Failure <input type="radio" name="test-variables" checked> Pending
|
||||
|
Loading…
Reference in New Issue
Block a user