Merge pull request #1743 from thecodingmachine/move-to-from-hash-parameter

Move to from hash parameter
This commit is contained in:
David Négrier 2022-01-25 14:12:26 +01:00 committed by GitHub
commit ef2f8b141f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 384 additions and 8 deletions

View File

@ -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`". * 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) * 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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -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 { flattenGroupLayersMap } from "../Map/LayersFlattener";
import TilemapLayer = Phaser.Tilemaps.TilemapLayer; import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes"; 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> { private getLayersByKey(key: number): Array<ITiledMapLayer> {
return this.flatLayers.filter((flatLayer) => flatLayer.type === "tilelayer" && flatLayer.data[key] !== 0); return this.flatLayers.filter((flatLayer) => flatLayer.type === "tilelayer" && flatLayer.data[key] !== 0);
} }

View File

@ -560,6 +560,12 @@ export class GameScene extends DirtyScene {
.catch((e) => console.error(e)); .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 //notify game manager can to create currentUser in map
this.createCurrentPlayer(); this.createCurrentPlayer();
this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted
@ -570,11 +576,6 @@ export class GameScene extends DirtyScene {
waScaleManager waScaleManager
); );
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);
@ -1726,6 +1727,22 @@ ${escapedMessage}
this.connection?.emitEmoteEvent(emoteKey); this.connection?.emitEmoteEvent(emoteKey);
analyticsClient.launchEmote(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) { } catch (err) {
if (err instanceof TextureError) { if (err instanceof TextureError) {
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene()); gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());

View File

@ -45,8 +45,28 @@ class UrlManager {
} }
public getStartLayerNameFromUrl(): string | null { public getStartLayerNameFromUrl(): string | null {
const hash = window.location.hash; const parameters = this.getHashParameters();
return hash.length > 1 ? hash.substring(1) : null; 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 { pushStartLayerNameToUrl(startLayerName: string): void {

View File

@ -31,4 +31,8 @@ export class MathUtils {
const distance = Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2); const distance = Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
return squared ? Math.sqrt(distance) : distance; return squared ? Math.sqrt(distance) : distance;
} }
public static randomFromArray<T>(array: T[]): T {
return array[Math.floor(Math.random() * array.length)];
}
} }

View File

@ -56,6 +56,14 @@
<a href="#" class="testLink" data-testmap="start-tile.json#S2" target="_blank">Test start tile (S2)</a> <a href="#" class="testLink" data-testmap="start-tile.json#S2" target="_blank">Test start tile (S2)</a>
</td> </td>
</tr> </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> <tr>
<td> <td>
<input type="radio" name="test-exits"> Success <input type="radio" name="test-exits"> Failure <input type="radio" name="test-exits" checked> Pending <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
View 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
}