From 168697eb461e94078a7b8fb2c75cf51b412ce603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 30 Aug 2020 15:44:22 +0200 Subject: [PATCH] Adding a GameMap class that helps tracking when the properties of the tiles the user is changes (when the user moves) --- front/src/Phaser/Game/GameMap.ts | 97 ++++++++++++++++++++++++++++++ front/src/Phaser/Game/GameScene.ts | 10 +++ 2 files changed, 107 insertions(+) create mode 100644 front/src/Phaser/Game/GameMap.ts diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts new file mode 100644 index 00000000..0e99159b --- /dev/null +++ b/front/src/Phaser/Game/GameMap.ts @@ -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(); + private callbacks = new Map>(); + + 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 { + const properties = new Map(); + + 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(); + this.callbacks.set(propName, callbacksArray); + } + callbacksArray.push(callback); + } +} diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 431bd3db..1e394b96 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -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); + }) }); }