Merge pull request #1743 from thecodingmachine/move-to-from-hash-parameter
Move to from hash parameter
This commit is contained in:
commit
ef2f8b141f
@ -65,3 +65,24 @@ How to use entry point :
|
||||
|
||||
* To enter via this entry point, simply add a hash with the entry point name to the URL ("#[_entryPointName_]"). For instance: "`https://workadventu.re/_/global/mymap.com/path/map.json#my-entry-point`".
|
||||
* You can of course use the "#" notation in an exit scene URL (so an exit scene URL will point to a given entry scene URL)
|
||||
|
||||
## Defining destination point with moveTo parameter
|
||||
|
||||
We are able to direct a Woka to the desired place immediately after spawn. To make users spawn on an entry point and then, walk automatically to a meeting room, simply add `moveTo` as an additional parameter of URL:
|
||||
|
||||
*Use default entry point*
|
||||
```
|
||||
.../my_map.json#&moveTo=exit
|
||||
```
|
||||
*Define entry point and moveTo parameter like this...*
|
||||
```
|
||||
.../my_map.json#start&moveTo=meeting-room
|
||||
```
|
||||
*...or like this*
|
||||
```
|
||||
.../my_map.json#moveTo=meeting-room&start
|
||||
```
|
||||
|
||||
For this to work, moveTo must be equal to the layer name of interest. This layer should have at least one tile defined. In case of layer having many tiles, user will go to one of them, randomly selected.
|
||||
|
||||
![](images/moveTo-layer-example.png)
|
BIN
docs/maps/images/moveTo-layer-example.png
Normal file
BIN
docs/maps/images/moveTo-layer-example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -1,4 +1,10 @@
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapObject, ITiledMapProperty } from "../Map/ITiledMap";
|
||||
import type {
|
||||
ITiledMap,
|
||||
ITiledMapLayer,
|
||||
ITiledMapObject,
|
||||
ITiledMapProperty,
|
||||
ITiledMapTileLayer,
|
||||
} from "../Map/ITiledMap";
|
||||
import { flattenGroupLayersMap } from "../Map/LayersFlattener";
|
||||
import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
|
||||
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
|
||||
@ -291,6 +297,31 @@ export class GameMap {
|
||||
}
|
||||
}
|
||||
|
||||
public getRandomPositionFromLayer(layerName: string): { x: number; y: number } {
|
||||
const layer = this.findLayer(layerName) as ITiledMapTileLayer;
|
||||
if (!layer) {
|
||||
throw new Error(`No layer "${layerName}" was found`);
|
||||
}
|
||||
const tiles = layer.data;
|
||||
if (!tiles) {
|
||||
throw new Error(`No tiles in "${layerName}" were found`);
|
||||
}
|
||||
if (typeof tiles === "string") {
|
||||
throw new Error("The content of a JSON map must be filled as a JSON array, not as a string");
|
||||
}
|
||||
const possiblePositions: { x: number; y: number }[] = [];
|
||||
tiles.forEach((objectKey: number, key: number) => {
|
||||
if (objectKey === 0) {
|
||||
return;
|
||||
}
|
||||
possiblePositions.push({ x: key % layer.width, y: Math.floor(key / layer.width) });
|
||||
});
|
||||
if (possiblePositions.length > 0) {
|
||||
return MathUtils.randomFromArray(possiblePositions);
|
||||
}
|
||||
throw new Error("No possible position found");
|
||||
}
|
||||
|
||||
private getLayersByKey(key: number): Array<ITiledMapLayer> {
|
||||
return this.flatLayers.filter((flatLayer) => flatLayer.type === "tilelayer" && flatLayer.data[key] !== 0);
|
||||
}
|
||||
|
@ -560,6 +560,12 @@ export class GameScene extends DirtyScene {
|
||||
.catch((e) => console.error(e));
|
||||
}
|
||||
|
||||
this.pathfindingManager = new PathfindingManager(
|
||||
this,
|
||||
this.gameMap.getCollisionsGrid(),
|
||||
this.gameMap.getTileDimensions()
|
||||
);
|
||||
|
||||
//notify game manager can to create currentUser in map
|
||||
this.createCurrentPlayer();
|
||||
this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted
|
||||
@ -570,11 +576,6 @@ export class GameScene extends DirtyScene {
|
||||
waScaleManager
|
||||
);
|
||||
|
||||
this.pathfindingManager = new PathfindingManager(
|
||||
this,
|
||||
this.gameMap.getCollisionsGrid(),
|
||||
this.gameMap.getTileDimensions()
|
||||
);
|
||||
biggestAvailableAreaStore.recompute();
|
||||
this.cameraManager.startFollowPlayer(this.CurrentPlayer);
|
||||
|
||||
@ -1726,6 +1727,22 @@ ${escapedMessage}
|
||||
this.connection?.emitEmoteEvent(emoteKey);
|
||||
analyticsClient.launchEmote(emoteKey);
|
||||
});
|
||||
const moveToParam = urlManager.getHashParameter("moveTo");
|
||||
if (moveToParam) {
|
||||
try {
|
||||
const endPos = this.gameMap.getRandomPositionFromLayer(moveToParam);
|
||||
this.pathfindingManager
|
||||
.findPath(this.gameMap.getTileIndexAt(this.CurrentPlayer.x, this.CurrentPlayer.y), endPos)
|
||||
.then((path) => {
|
||||
if (path && path.length > 0) {
|
||||
this.CurrentPlayer.setPathToFollow(path).catch((reason) => console.warn(reason));
|
||||
}
|
||||
})
|
||||
.catch((reason) => console.warn(reason));
|
||||
} catch (err) {
|
||||
console.warn(`Cannot proceed with moveTo command:\n\t-> ${err}`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof TextureError) {
|
||||
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
|
||||
|
@ -45,8 +45,28 @@ class UrlManager {
|
||||
}
|
||||
|
||||
public getStartLayerNameFromUrl(): string | null {
|
||||
const hash = window.location.hash;
|
||||
return hash.length > 1 ? hash.substring(1) : null;
|
||||
const parameters = this.getHashParameters();
|
||||
for (const key in parameters) {
|
||||
if (parameters[key] === undefined) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getHashParameter(name: string): string | undefined {
|
||||
return this.getHashParameters()[name];
|
||||
}
|
||||
|
||||
private getHashParameters(): Record<string, string> {
|
||||
return window.location.hash
|
||||
.substring(1)
|
||||
.split("&")
|
||||
.reduce((res: Record<string, string>, item: string) => {
|
||||
const parts = item.split("=");
|
||||
res[parts[0]] = parts[1];
|
||||
return res;
|
||||
}, {});
|
||||
}
|
||||
|
||||
pushStartLayerNameToUrl(startLayerName: string): void {
|
||||
|
@ -31,4 +31,8 @@ export class MathUtils {
|
||||
const distance = Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
|
||||
return squared ? Math.sqrt(distance) : distance;
|
||||
}
|
||||
|
||||
public static randomFromArray<T>(array: T[]): T {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,14 @@
|
||||
<a href="#" class="testLink" data-testmap="start-tile.json#S2" target="_blank">Test start tile (S2)</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-exits"> Success <input type="radio" name="test-exits"> Failure <input type="radio" name="test-exits" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="move_to.json" target="_blank">Test moveTo parameter</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-exits"> Success <input type="radio" name="test-exits"> Failure <input type="radio" name="test-exits" checked> Pending
|
||||
|
275
maps/tests/move_to.json
Normal file
275
maps/tests/move_to.json
Normal file
@ -0,0 +1,275 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":10,
|
||||
"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],
|
||||
"height":10,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"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, 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],
|
||||
"height":10,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
||||
"height":10,
|
||||
"id":7,
|
||||
"name":"walls",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"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, 34, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 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":10,
|
||||
"id":8,
|
||||
"name":"meeting-room",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"startLayer",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"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, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":10,
|
||||
"name":"start2",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"startLayer",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":33.4788210765457,
|
||||
"id":1,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"Add \"moveTo\" parameter to the URL to make character move at game start.",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":249.954975648686,
|
||||
"x":35.2740564642832,
|
||||
"y":34.4372323693377
|
||||
},
|
||||
{
|
||||
"height":19.6921,
|
||||
"id":3,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"...#start2&moveTo=meeting-room",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":223.499265952492,
|
||||
"x":32,
|
||||
"y":114
|
||||
},
|
||||
{
|
||||
"height":19.6921,
|
||||
"id":4,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"start",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":26.7596292501164,
|
||||
"x":3.30880298090358,
|
||||
"y":135.124359571495
|
||||
},
|
||||
{
|
||||
"height":19.6921,
|
||||
"id":5,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"...#start2&moveTo=start",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":158.292,
|
||||
"x":32,
|
||||
"y":132
|
||||
},
|
||||
{
|
||||
"height":19.6921,
|
||||
"id":6,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"...#start&moveTo=meeting-room",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":217.164845831393,
|
||||
"x":32,
|
||||
"y":93.740349627387
|
||||
},
|
||||
{
|
||||
"height":19.6921,
|
||||
"id":7,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"start2",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":33.0940201210992,
|
||||
"x":74.556855798789,
|
||||
"y":245.393819585468
|
||||
},
|
||||
{
|
||||
"height":19.6921,
|
||||
"id":8,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"meeting-room",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":92.7120717279925,
|
||||
"x":233.848901257569,
|
||||
"y":135.845612785282
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":11,
|
||||
"nextobjectid":9,
|
||||
"orientation":"orthogonal",
|
||||
"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":18,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":19,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
}],
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":"1.6",
|
||||
"width":10
|
||||
}
|
Loading…
Reference in New Issue
Block a user