Adding a GameMap class that helps tracking when the properties of the tiles the user is changes (when the user moves)

This commit is contained in:
David Négrier 2020-08-30 15:44:22 +02:00
parent 4d90d4b50b
commit 168697eb46
2 changed files with 107 additions and 0 deletions

View file

@ -0,0 +1,97 @@
import {ITiledMap} from "../Map/ITiledMap";
export type PropertyChangeCallback = (oldValue: string | number | boolean | undefined, newValue: string | number | boolean | undefined) => void;
/**
* A wrapper around a ITiledMap interface to provide additional capabilities.
* It is used to handle layer properties.
*/
export class GameMap {
private key: number|undefined;
private lastProperties = new Map<string, string|boolean|number>();
private callbacks = new Map<string, Array<PropertyChangeCallback>>();
public constructor(private map: ITiledMap) {
}
/**
* Sets the position of the current player (in pixels)
* This will trigger events if properties are changing.
*/
public setPosition(x: number, y: number) {
const xMap = Math.floor(x / this.map.tilewidth);
const yMap = Math.floor(y / this.map.tileheight);
const key = xMap + yMap * this.map.width;
if (key === this.key) {
return;
}
this.key = key;
const newProps = this.getProperties(key);
const oldProps = this.lastProperties;
// Let's compare the 2 maps:
// First new properties vs oldProperties
for (const [newPropName, newPropValue] of newProps.entries()) {
const oldPropValue = oldProps.get(newPropName);
if (oldPropValue !== newPropValue) {
this.trigger(newPropName, oldPropValue, newPropValue);
}
}
for (const [oldPropName, oldPropValue] of oldProps.entries()) {
if (!newProps.has(oldPropName)) {
// We found a property that disappeared
this.trigger(oldPropName, oldPropValue, undefined);
}
}
this.lastProperties = newProps;
}
private getProperties(key: number): Map<string, string|boolean|number> {
const properties = new Map<string, string|boolean|number>();
for (const layer of this.map.layers) {
if (layer.type !== 'tilelayer') {
continue;
}
const tiles = layer.data as number[];
if (tiles[key] == 0) {
continue;
}
// There is a tile in this layer, let's embed the properties
if (layer.properties !== undefined) {
for (const layerProperty of layer.properties) {
if (layerProperty.value === undefined) {
continue;
}
properties.set(layerProperty.name, layerProperty.value);
}
}
}
return properties;
}
private trigger(propName: string, oldValue: string | number | boolean | undefined, newValue: string | number | boolean | undefined) {
let callbacksArray = this.callbacks.get(propName);
if (callbacksArray !== undefined) {
for (const callback of callbacksArray) {
callback(oldValue, newValue);
}
}
}
/**
* Registers a callback called when the user moves to a tile where the property propName is different from the last tile the user was on.
*/
public onPropertyChange(propName: string, callback: PropertyChangeCallback) {
let callbacksArray = this.callbacks.get(propName);
if (callbacksArray === undefined) {
callbacksArray = new Array<PropertyChangeCallback>();
this.callbacks.set(propName, callbacksArray);
}
callbacksArray.push(callback);
}
}

View file

@ -28,6 +28,7 @@ import Sprite = Phaser.GameObjects.Sprite;
import CanvasTexture = Phaser.Textures.CanvasTexture;
import GameObject = Phaser.GameObjects.GameObject;
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
import {GameMap} from "./GameMap";
export enum Textures {
@ -109,6 +110,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
private presentationModeSprite!: Sprite;
private chatModeSprite!: Sprite;
private repositionCallback!: (this: Window, ev: UIEvent) => void;
private gameMap!: GameMap;
static createFromUrl(mapUrlFile: string, instance: string, key: string|null = null): GameScene {
const mapKey = GameScene.getMapKeyByUrl(mapUrlFile);
@ -278,6 +280,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
create(): void {
//initalise map
this.Map = this.add.tilemap(this.MapKey);
this.gameMap = new GameMap(this.mapFile);
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
this.Terrains.push(this.Map.addTilesetImage(tileset.name, `${mapDirUrl}/${tileset.image}`, tileset.tilewidth, tileset.tileheight, tileset.margin, tileset.spacing/*, tileset.firstgid*/));
@ -411,6 +414,10 @@ export class GameScene extends Phaser.Scene implements CenterListener {
// From now, this game scene will be notified of reposition events
layoutManager.setListener(this);
this.gameMap.onPropertyChange('startLayer', (oldValue, newValue) => {
console.log('startLayer', oldValue, newValue);
});
}
private switchLayoutMode(): void {
@ -589,6 +596,9 @@ export class GameScene extends Phaser.Scene implements CenterListener {
//listen event to share position of user
this.CurrentPlayer.on(hasMovedEventName, this.pushPlayerPosition.bind(this))
this.CurrentPlayer.on(hasMovedEventName, (event: HasMovedEvent) => {
this.gameMap.setPosition(event.x, event.y);
})
});
}