From eecf831ca516ba530d55ebdfb32f1bc57472f4ca Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Wed, 1 Dec 2021 14:48:14 +0100 Subject: [PATCH 1/7] detecting zoe enter and leave events --- back/src/Services/VariablesManager.ts | 1 - front/src/Phaser/Game/GameMap.ts | 118 ++- front/src/Phaser/Game/GameScene.ts | 22 + .../src/Phaser/Game/SharedVariablesManager.ts | 2 +- front/src/Phaser/Items/Computer/computer.ts | 1 - front/src/Utils/MathUtils.ts | 27 + maps/starter/map.json | 702 +++++++++--------- 7 files changed, 526 insertions(+), 347 deletions(-) create mode 100644 front/src/Utils/MathUtils.ts diff --git a/back/src/Services/VariablesManager.ts b/back/src/Services/VariablesManager.ts index 00aac3dc..d11cb26f 100644 --- a/back/src/Services/VariablesManager.ts +++ b/back/src/Services/VariablesManager.ts @@ -5,7 +5,6 @@ import { ITiledMap, ITiledMapLayer, ITiledMapObject, - ITiledMapObjectLayer, } from "@workadventure/tiled-map-type-guard/dist"; import { User } from "_Model/User"; import { variablesRepository } from "./Repository/VariablesRepository"; diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index 8fe0e329..db9b652e 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -1,8 +1,9 @@ -import type { ITiledMap, ITiledMapLayer, ITiledMapProperty } from "../Map/ITiledMap"; +import type { ITiledMap, ITiledMapLayer, ITiledMapObject, ITiledMapObjectLayer, ITiledMapProperty } from "../Map/ITiledMap"; import { flattenGroupLayersMap } from "../Map/LayersFlattener"; import TilemapLayer = Phaser.Tilemaps.TilemapLayer; import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes"; import { GameMapProperties } from "./GameMapProperties"; +import { MathUtils } from '../../Utils/MathUtils'; export type PropertyChangeCallback = ( newValue: string | number | boolean | undefined, @@ -15,23 +16,46 @@ export type layerChangeCallback = ( allLayersOnNewPosition: Array ) => void; +export type zoneChangeCallback = ( + zonesChangedByAction: Array, + allZonesOnNewPosition: Array +) => void; + /** * A wrapper around a ITiledMap interface to provide additional capabilities. * It is used to handle layer properties. */ export class GameMap { - // oldKey is the index of the previous tile. + /** + * oldKey is the index of the previous tile. + */ private oldKey: number | undefined; - // key is the index of the current tile. + /** + * key is the index of the current tile. + */ private key: number | undefined; + /** + * oldPosition is the previous position of the player. + */ + private oldPosition: { x: number, y: number } | undefined; + /** + * position is the current position of the player. + */ + private position: { x: number, y: number } | undefined; + private lastProperties = new Map(); private propertiesChangeCallbacks = new Map>(); + private enterLayerCallbacks = Array(); private leaveLayerCallbacks = Array(); + private enterZoneCallbacks = Array(); + private leaveZoneCallbacks = Array(); + private tileNameMap = new Map(); private tileSetPropertyMap: { [tile_index: number]: Array } = {}; public readonly flatLayers: ITiledMapLayer[]; + public readonly tiledObjects: ITiledMapObject[]; public readonly phaserLayers: TilemapLayer[] = []; public exitUrls: Array = []; @@ -44,6 +68,8 @@ export class GameMap { terrains: Array ) { this.flatLayers = flattenGroupLayersMap(map); + this.tiledObjects = this.getObjectsFromLayers(this.flatLayers); + let depth = -2; for (const layer of this.flatLayers) { if (layer.type === "tilelayer") { @@ -88,6 +114,9 @@ export class GameMap { * This will trigger events if properties are changing. */ public setPosition(x: number, y: number) { + this.oldPosition = this.position; + this.position = { x, y }; + this.oldKey = this.key; const xMap = Math.floor(x / this.map.tilewidth); @@ -102,6 +131,7 @@ export class GameMap { this.triggerAllProperties(); this.triggerLayersChange(); + this.triggerZonesChange(); } private triggerAllProperties(): void { @@ -126,7 +156,7 @@ export class GameMap { } } - private triggerLayersChange() { + private triggerLayersChange(): void { const layersByOldKey = this.oldKey ? this.getLayersByKey(this.oldKey) : []; const layersByNewKey = this.key ? this.getLayersByKey(this.key) : []; @@ -155,6 +185,54 @@ export class GameMap { } } + /** + * We user Tiled Objects with type "zone" as zones with defined x, y, width and height for easier event triggering. + */ + private triggerZonesChange(): void { + const zones = this.tiledObjects.filter(object => object.type === "zone"); + + // P.H. NOTE: We could also get all of the zones and add properties of occupied tiles to them, so we could later on check collision by using tileKeys + const zonesByOldPosition = this.oldPosition ? + zones.filter((zone) => { + if (!this.oldPosition) { + return false; + } + return MathUtils.isOverlappingWithRectangle(this.oldPosition, zone); + }) : []; + + const zonesByNewPosition = this.position ? + zones.filter((zone) => { + if (!this.position) { + return false; + } + return MathUtils.isOverlappingWithRectangle(this.position, zone); + }) : []; + + const enterZones = new Set(zonesByNewPosition); + const leaveZones = new Set(zonesByOldPosition); + + enterZones.forEach((zone) => { + if (leaveZones.has(zone)) { + leaveZones.delete(zone); + enterZones.delete(zone); + } + }); + + if (enterZones.size > 0) { + const zonesArray = Array.from(enterZones); + for (const callback of this.enterZoneCallbacks) { + callback(zonesArray, zonesByNewPosition); + } + } + + if (leaveZones.size > 0) { + const zonesArray = Array.from(leaveZones); + for (const callback of this.leaveZoneCallbacks) { + callback(zonesArray, zonesByNewPosition); + } + } + } + public getCurrentProperties(): Map { return this.lastProperties; } @@ -251,6 +329,20 @@ export class GameMap { this.leaveLayerCallbacks.push(callback); } + /** + * Registers a callback called when the user moves inside another zone. + */ + public onEnterZone(callback: zoneChangeCallback) { + this.enterZoneCallbacks.push(callback); + } + + /** + * Registers a callback called when the user moves outside another zone. + */ + public onLeaveZone(callback: zoneChangeCallback) { + this.leaveZoneCallbacks.push(callback); + } + public findLayer(layerName: string): ITiledMapLayer | undefined { return this.flatLayers.find((layer) => layer.name === layerName); } @@ -362,4 +454,22 @@ export class GameMap { this.trigger(oldPropName, oldPropValue, undefined, emptyProps); } } + + private getObjectsFromLayers(layers: ITiledMapLayer[]): ITiledMapObject[] { + const objects: ITiledMapObject[] = []; + + const objectLayers = layers.filter(layer => layer.type === "objectgroup"); + for (const objectLayer of objectLayers) { + if (this.isOfTypeITiledMapObjectLayer(objectLayer)) { + objects.push(...objectLayer.objects); + } + } + + return objects; + } + + // NOTE: Simple typeguard for Objects Layer. + private isOfTypeITiledMapObjectLayer(obj: ITiledMapLayer): obj is ITiledMapObjectLayer { + return (obj as ITiledMapObjectLayer).objects !== undefined; + } } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d9bb8186..8bf0f13e 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -778,6 +778,28 @@ export class GameScene extends DirtyScene { iframeListener.sendLeaveLayerEvent(layer.name); }); }); + + this.gameMap.onEnterZone((zones) => { + console.log('enter zones'); + console.log(zones); + // zones.forEach((zone) => { + // iframeListener.sendEnterLayerEvent(zone.name); + // }); + }); + + this.gameMap.onLeaveZone((zones) => { + console.log('leave zones'); + console.log(zones); + // zones.forEach((zone) => { + // iframeListener.sendEnterLayerEvent(zone.name); + // }); + }); + + // this.gameMap.onLeaveLayer((layers) => { + // layers.forEach((layer) => { + // iframeListener.sendLeaveLayerEvent(layer.name); + // }); + // }); }); } diff --git a/front/src/Phaser/Game/SharedVariablesManager.ts b/front/src/Phaser/Game/SharedVariablesManager.ts index 8f913765..5b5867dc 100644 --- a/front/src/Phaser/Game/SharedVariablesManager.ts +++ b/front/src/Phaser/Game/SharedVariablesManager.ts @@ -1,7 +1,7 @@ import type { RoomConnection } from "../../Connexion/RoomConnection"; import { iframeListener } from "../../Api/IframeListener"; import type { GameMap } from "./GameMap"; -import type { ITiledMapLayer, ITiledMapObject, ITiledMapObjectLayer } from "../Map/ITiledMap"; +import type { ITiledMapLayer, ITiledMapObject } from "../Map/ITiledMap"; import { GameMapProperties } from "./GameMapProperties"; interface Variable { diff --git a/front/src/Phaser/Items/Computer/computer.ts b/front/src/Phaser/Items/Computer/computer.ts index 4665c546..41fb6fc4 100644 --- a/front/src/Phaser/Items/Computer/computer.ts +++ b/front/src/Phaser/Items/Computer/computer.ts @@ -1,5 +1,4 @@ import * as Phaser from "phaser"; -import { Scene } from "phaser"; import Sprite = Phaser.GameObjects.Sprite; import type { ITiledMapObject } from "../../Map/ITiledMap"; import type { ItemFactoryInterface } from "../ItemFactoryInterface"; diff --git a/front/src/Utils/MathUtils.ts b/front/src/Utils/MathUtils.ts new file mode 100644 index 00000000..098b86b4 --- /dev/null +++ b/front/src/Utils/MathUtils.ts @@ -0,0 +1,27 @@ + +export class MathUtils { + + /** + * + * @param p Position to check. + * @param r Rectangle to check the overlap against. + * @returns true is overlapping + */ + public static isOverlappingWithRectangle( + p: { x: number, y: number}, + r: { x: number, y: number, width: number, height: number}, + ): boolean { + return (this.isBetween(p.x, r.x, r.x + r.width) && this.isBetween(p.y, r.y, r.y + r.height)); + } + + /** + * + * @param value Value to check + * @param min inclusive min value + * @param max inclusive max value + * @returns true if value is in + */ + public static isBetween(value: number, min: number, max: number): boolean { + return (value >= min) && (value <= max); + } +} \ No newline at end of file diff --git a/maps/starter/map.json b/maps/starter/map.json index 8d93c66e..31d81b19 100644 --- a/maps/starter/map.json +++ b/maps/starter/map.json @@ -1,341 +1,363 @@ -{ "compressionlevel":-1, - "height":17, - "infinite":false, - "layers":[ - { - "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":6, - "name":"start", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "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, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 443, 443, 443, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":7, - "name":"collisions", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "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, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":29, - "name":"jitsiMeetingRoom", - "opacity":1, - "properties":[ - { - "name":"jitsiRoom", - "type":"string", - "value":"MeetingRoom" - }], - "type":"tilelayer", - "visible":true, - "width":31, - "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, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":38, - "name":"jitsiChillzone", - "opacity":1, - "properties":[ - { - "name":"jitsiRoom", - "type":"string", - "value":"ChillZone" - }, - { - "name":"jitsiTrigger", - "type":"string", - "value":"onaction" - }], - "type":"tilelayer", - "visible":true, - "width":31, - "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, 446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":23, - "name":"clockZone", - "opacity":1, - "properties":[ - { - "name":"zone", - "type":"string", - "value":"clock" - }], - "type":"tilelayer", - "visible":true, - "width":31, - "x":0, - "y":0 - }, - { - "data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201], - "height":17, - "id":4, - "name":"floor", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "x":0, - "y":0 - }, - { - "data":[49, 58, 58, 58, 58, 58, 58, 42, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 42, 57, 57, 57, 57, 57, 57, 57, 50, 45, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 45, 45, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 45, 45, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 32, 58, 58, 58, 58, 58, 58, 58, 60, 83, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 84, 93, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 94], - "height":17, - "id":9, - "name":"walls", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "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, 293, 0, 0, 0, 0, 293, 0, 107, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 107, 0, 0, 128, 1, 2, 3, 0, 0, 0, 0, 304, 296, 297, 296, 297, 304, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 11, 12, 13, 0, 0, 0, 0, 315, 307, 308, 307, 308, 315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 243, 0, 0, 0, 0, 2147483943, 0, 0, 0, 325, 340, 340, 326, 0, 0, 325, 340, 340, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 0, 283, 283, 0, 2147483954, 0, 0, 0, 0, 340, 340, 0, 0, 0, 0, 340, 340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, 294, 0, 0, 0, 0, 0, 325, 340, 340, 326, 0, 0, 325, 340, 340, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 351, 351, 0, 0, 0, 0, 351, 351, 0, 0, 0, 0, 0, 0, 325, 273, 275, 326, 0, 0, 0, 394, 395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 405, 406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, 333, 334, 333, 334, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 344, 345, 344, 345, 344, 345, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 220, 220, 220, 220, 218, 0, 0, 0, 0, 0, 0, 0, 0, 284, 286, 0, 0, 0, 0, 438, 439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, 336, 335, 336, 335, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, 347, 346, 347, 346, 347, 0, 2147483811, 2147483810, 2147483809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":1, - "name":"furniture", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "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, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 231, 231, 231, 231, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":33, - "name":"aboveFurniture", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "x":0, - "y":0 - }, - { - "draworder":"topdown", - "id":2, - "name":"floorLayer", - "objects":[ - { - "height":64, - "id":4, - "name":"clockPopup", - "rotation":0, - "type":"", - "visible":true, - "width":128, - "x":512, - "y":0 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "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, 329, 329, 0, 0, 0, 0, 329, 329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 209, 209, 209, 209, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483801, 2147483800, 2147483799, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":3, - "name":"abovePlayer1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 399, 400, 399, 400, 399, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 410, 411, 410, 411, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":27, - "name":"abovePlayer2", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 401, 402, 401, 402, 401, 402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 412, 413, 412, 413, 412, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, - "id":28, - "name":"abovePlayer3", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":31, - "x":0, - "y":0 - }], - "nextlayerid":39, - "nextobjectid":9, - "orientation":"orthogonal", - "properties":[ - { - "name":"mapCopyright", - "type":"string", - "value":"Credits: Valdo Romao https:\/\/www.linkedin.com\/in\/valdo-romao\/ \nLicense: CC-BY-SA 3.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/)" - }, - { - "name":"mapDescription", - "type":"string", - "value":"A perfect virtual office to get started with WorkAdventure!" - }, - { - "name":"mapImage", - "type":"string", - "value":"map.png" - }, - { - "name":"mapLink", - "type":"string", - "value":"https:\/\/thecodingmachine.github.io\/workadventure-map-starter-kit\/map.json" - }, - { - "name":"mapName", - "type":"string", - "value":"Starter kit" - }, - { - "name":"script", - "type":"string", - "value":"..\/dist\/script.js" - }], - "renderorder":"right-down", - "tiledversion":"1.7.0", - "tileheight":32, - "tilesets":[ - { - "columns":10, - "firstgid":1, - "image":"..\/assets\/tileset5_export.png", - "imageheight":320, - "imagewidth":320, - "margin":0, - "name":"tileset5_export", - "properties":[ - { - "name":"tilesetCopyright", - "type":"string", - "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" - }], - "spacing":0, - "tilecount":100, - "tileheight":32, - "tilewidth":32 - }, - { - "columns":10, - "firstgid":101, - "image":"..\/assets\/tileset6_export.png", - "imageheight":320, - "imagewidth":320, - "margin":0, - "name":"tileset6_export", - "properties":[ - { - "name":"tilesetCopyright", - "type":"string", - "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" - }], - "spacing":0, - "tilecount":100, - "tileheight":32, - "tilewidth":32 - }, - { - "columns":11, - "firstgid":201, - "image":"..\/assets\/tileset1.png", - "imageheight":352, - "imagewidth":352, - "margin":0, - "name":"tileset1", - "properties":[ - { - "name":"tilesetCopyright", - "type":"string", - "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" - }], - "spacing":0, - "tilecount":121, - "tileheight":32, - "tilewidth":32 - }, - { - "columns":11, - "firstgid":322, - "image":"..\/assets\/tileset1-repositioning.png", - "imageheight":352, - "imagewidth":352, - "margin":0, - "name":"tileset1-repositioning", - "properties":[ - { - "name":"tilesetCopyright", - "type":"string", - "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" - }], - "spacing":0, - "tilecount":121, - "tileheight":32, - "tilewidth":32 - }, - { - "columns":6, - "firstgid":443, - "image":"..\/assets\/Special_Zones.png", - "imageheight":64, - "imagewidth":192, - "margin":0, - "name":"Special_Zones", - "properties":[ - { - "name":"tilesetCopyright", - "type":"string", - "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" - }], - "spacing":0, - "tilecount":12, - "tileheight":32, - "tiles":[ - { - "id":0, - "properties":[ - { - "name":"collides", - "type":"bool", - "value":true - }] - }], - "tilewidth":32 - }], - "tilewidth":32, - "type":"map", - "version":"1.6", - "width":31 +{ "compressionlevel":-1, + "height":17, + "infinite":false, + "layers":[ + { + "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":6, + "name":"start", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "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, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 443, 443, 443, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":7, + "name":"collisions", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "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, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":29, + "name":"jitsiMeetingRoom", + "opacity":1, + "properties":[ + { + "name":"jitsiRoom", + "type":"string", + "value":"MeetingRoom" + }], + "type":"tilelayer", + "visible":true, + "width":31, + "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, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":38, + "name":"jitsiChillzone", + "opacity":1, + "properties":[ + { + "name":"jitsiRoom", + "type":"string", + "value":"ChillZone" + }, + { + "name":"jitsiTrigger", + "type":"string", + "value":"onaction" + }], + "type":"tilelayer", + "visible":true, + "width":31, + "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, 446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":23, + "name":"clockZone", + "opacity":1, + "properties":[ + { + "name":"zone", + "type":"string", + "value":"clock" + }], + "type":"tilelayer", + "visible":true, + "width":31, + "x":0, + "y":0 + }, + { + "data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201], + "height":17, + "id":4, + "name":"floor", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "x":0, + "y":0 + }, + { + "data":[49, 58, 58, 58, 58, 58, 58, 42, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 42, 57, 57, 57, 57, 57, 57, 57, 50, 45, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 45, 45, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 45, 45, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 32, 58, 58, 58, 58, 58, 58, 58, 60, 83, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 84, 93, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 94], + "height":17, + "id":9, + "name":"walls", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "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, 293, 0, 0, 0, 0, 293, 0, 107, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 107, 0, 0, 128, 1, 2, 3, 0, 0, 0, 0, 304, 296, 297, 296, 297, 304, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 11, 12, 13, 0, 0, 0, 0, 315, 307, 308, 307, 308, 315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 243, 0, 0, 0, 0, 2147483943, 0, 0, 0, 325, 340, 340, 326, 0, 0, 325, 340, 340, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 0, 283, 283, 0, 2147483954, 0, 0, 0, 0, 340, 340, 0, 0, 0, 0, 340, 340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, 294, 0, 0, 0, 0, 0, 325, 340, 340, 326, 0, 0, 325, 340, 340, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 351, 351, 0, 0, 0, 0, 351, 351, 0, 0, 0, 0, 0, 0, 325, 273, 275, 326, 0, 0, 0, 394, 395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 405, 406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, 333, 334, 333, 334, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 344, 345, 344, 345, 344, 345, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 220, 220, 220, 220, 218, 0, 0, 0, 0, 0, 0, 0, 0, 284, 286, 0, 0, 0, 0, 438, 439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, 336, 335, 336, 335, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, 347, 346, 347, 346, 347, 0, 2147483811, 2147483810, 2147483809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":1, + "name":"furniture", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "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, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 231, 231, 231, 231, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":33, + "name":"aboveFurniture", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"floorLayer", + "objects":[ + { + "height":64, + "id":4, + "name":"clockPopup", + "rotation":0, + "type":"", + "visible":true, + "width":128, + "x":512, + "y":0 + }, + { + "height":128, + "id":9, + "name":"chillZone", + "properties":[ + { + "name":"display_name", + "type":"string", + "value":"Chilling Room" + }, + { + "name":"focusable", + "type":"bool", + "value":true + }], + "rotation":0, + "type":"zone", + "visible":true, + "width":192, + "x":32, + "y":96 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "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, 329, 329, 0, 0, 0, 0, 329, 329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 209, 209, 209, 209, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483801, 2147483800, 2147483799, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":3, + "name":"abovePlayer1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 399, 400, 399, 400, 399, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 410, 411, 410, 411, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":27, + "name":"abovePlayer2", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 401, 402, 401, 402, 401, 402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 412, 413, 412, 413, 412, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":17, + "id":28, + "name":"abovePlayer3", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":31, + "x":0, + "y":0 + }], + "nextlayerid":39, + "nextobjectid":11, + "orientation":"orthogonal", + "properties":[ + { + "name":"mapCopyright", + "type":"string", + "value":"Credits: Valdo Romao https:\/\/www.linkedin.com\/in\/valdo-romao\/ \nLicense: CC-BY-SA 3.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/)" + }, + { + "name":"mapDescription", + "type":"string", + "value":"A perfect virtual office to get started with WorkAdventure!" + }, + { + "name":"mapImage", + "type":"string", + "value":"map.png" + }, + { + "name":"mapLink", + "type":"string", + "value":"https:\/\/thecodingmachine.github.io\/workadventure-map-starter-kit\/map.json" + }, + { + "name":"mapName", + "type":"string", + "value":"Starter kit" + }, + { + "name":"script", + "type":"string", + "value":"..\/dist\/script.js" + }], + "renderorder":"right-down", + "tiledversion":"1.7.2", + "tileheight":32, + "tilesets":[ + { + "columns":10, + "firstgid":1, + "image":"..\/assets\/tileset5_export.png", + "imageheight":320, + "imagewidth":320, + "margin":0, + "name":"tileset5_export", + "properties":[ + { + "name":"tilesetCopyright", + "type":"string", + "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" + }], + "spacing":0, + "tilecount":100, + "tileheight":32, + "tilewidth":32 + }, + { + "columns":10, + "firstgid":101, + "image":"..\/assets\/tileset6_export.png", + "imageheight":320, + "imagewidth":320, + "margin":0, + "name":"tileset6_export", + "properties":[ + { + "name":"tilesetCopyright", + "type":"string", + "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" + }], + "spacing":0, + "tilecount":100, + "tileheight":32, + "tilewidth":32 + }, + { + "columns":11, + "firstgid":201, + "image":"..\/assets\/tileset1.png", + "imageheight":352, + "imagewidth":352, + "margin":0, + "name":"tileset1", + "properties":[ + { + "name":"tilesetCopyright", + "type":"string", + "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" + }], + "spacing":0, + "tilecount":121, + "tileheight":32, + "tilewidth":32 + }, + { + "columns":11, + "firstgid":322, + "image":"..\/assets\/tileset1-repositioning.png", + "imageheight":352, + "imagewidth":352, + "margin":0, + "name":"tileset1-repositioning", + "properties":[ + { + "name":"tilesetCopyright", + "type":"string", + "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" + }], + "spacing":0, + "tilecount":121, + "tileheight":32, + "tilewidth":32 + }, + { + "columns":6, + "firstgid":443, + "image":"..\/assets\/Special_Zones.png", + "imageheight":64, + "imagewidth":192, + "margin":0, + "name":"Special_Zones", + "properties":[ + { + "name":"tilesetCopyright", + "type":"string", + "value":"\u00a9 2021 WorkAdventure \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)" + }], + "spacing":0, + "tilecount":12, + "tileheight":32, + "tiles":[ + { + "id":0, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }], + "tilewidth":32 + }], + "tilewidth":32, + "type":"map", + "version":"1.6", + "width":31 } \ No newline at end of file From 85bf2fe70d55f17f9dae011119a78021d6be26d3 Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Thu, 2 Dec 2021 13:20:40 +0100 Subject: [PATCH 2/7] camera zoom using scaleManager zooming. WIP --- front/src/Phaser/Game/CameraManager.ts | 70 +++++++++++++++++++++ front/src/Phaser/Game/GameMap.ts | 1 + front/src/Phaser/Game/GameScene.ts | 59 +++++++++-------- front/src/Phaser/Services/WaScaleManager.ts | 2 +- front/src/types.ts | 31 +++++++++ maps/starter/map.json | 26 +++++++- 6 files changed, 155 insertions(+), 34 deletions(-) create mode 100644 front/src/Phaser/Game/CameraManager.ts diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts new file mode 100644 index 00000000..595867be --- /dev/null +++ b/front/src/Phaser/Game/CameraManager.ts @@ -0,0 +1,70 @@ +import { Easing } from '../../types'; +import { HtmlUtils } from '../../WebRtc/HtmlUtils'; +import type { Box } from '../../WebRtc/LayoutManager'; +import type { WaScaleManager } from '../Services/WaScaleManager'; +import type { GameScene } from './GameScene'; + +export class CameraManager extends Phaser.Events.EventEmitter { + + private scene: GameScene; + private camera: Phaser.Cameras.Scene2D.Camera; + private waScaleManager: WaScaleManager; + + private cameraBounds: { x: number, y: number }; + + constructor(scene: GameScene, cameraBounds: { x: number, y: number }, waScaleManager: WaScaleManager) { + super(); + this.scene = scene; + + this.camera = scene.cameras.main; + this.cameraBounds = cameraBounds; + + this.waScaleManager = waScaleManager; + + this.initCamera(); + } + + public getCamera(): Phaser.Cameras.Scene2D.Camera { + return this.camera; + } + + public changeCameraFocus(focusOn: { x: number, y: number, width: number, height: number }, duration: number = 1000): void { + const maxZoomModifier = 2.84; // How to get max zoom value? + const currentZoomModifier = this.waScaleManager.zoomModifier; + const zoomModifierChange = maxZoomModifier - currentZoomModifier; + this.camera.stopFollow(); + this.camera.pan( + focusOn.x + focusOn.width * 0.5, + focusOn.y + focusOn.height * 0.5, + duration, + Easing.SineEaseOut, false, (camera, progress, x, y) => { + this.scene.setZoomModifierTo(currentZoomModifier + progress * zoomModifierChange); + }); + } + + public startFollow(target: object | Phaser.GameObjects.GameObject): void { + this.camera.startFollow(target, true); + } + + /** + * Updates the offset of the character compared to the center of the screen according to the layout manager + * (tries to put the character in the center of the remaining space if there is a discussion going on. + */ + public updateCameraOffset(array: Box): void { + const xCenter = (array.xEnd - array.xStart) / 2 + array.xStart; + const yCenter = (array.yEnd - array.yStart) / 2 + array.yStart; + + const game = HtmlUtils.querySelectorOrFail("#game canvas"); + // Let's put this in Game coordinates by applying the zoom level: + + this.camera.setFollowOffset( + ((xCenter - game.offsetWidth / 2) * window.devicePixelRatio) / this.scene.scale.zoom, + ((yCenter - game.offsetHeight / 2) * window.devicePixelRatio) / this.scene.scale.zoom + ); + } + + private initCamera() { + this.camera = this.scene.cameras.main; + this.camera.setBounds(0, 0, this.cameraBounds.x, this.cameraBounds.y); + } +} \ No newline at end of file diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index db9b652e..85a1a0e0 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -192,6 +192,7 @@ export class GameMap { const zones = this.tiledObjects.filter(object => object.type === "zone"); // P.H. NOTE: We could also get all of the zones and add properties of occupied tiles to them, so we could later on check collision by using tileKeys + // TODO: Change this to an array with currently occupied sone instead of doing elimination process const zonesByOldPosition = this.oldPosition ? zones.filter((zone) => { if (!this.oldPosition) { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 8bf0f13e..d596fa56 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -60,6 +60,7 @@ import { PinchManager } from "../UserInput/PinchManager"; import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick"; import { waScaleManager } from "../Services/WaScaleManager"; import { EmoteManager } from "./EmoteManager"; +import { CameraManager } from './CameraManager'; import EVENT_TYPE = Phaser.Scenes.Events; import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent"; @@ -198,6 +199,7 @@ export class GameScene extends DirtyScene { private pinchManager: PinchManager | undefined; private mapTransitioning: boolean = false; //used to prevent transitions happening at the same time. private emoteManager!: EmoteManager; + private cameraManager!: CameraManager; private preloading: boolean = true; private startPositionCalculator!: StartPositionCalculator; private sharedVariablesManager!: SharedVariablesManager; @@ -549,7 +551,9 @@ export class GameScene extends DirtyScene { this.createCurrentPlayer(); this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted - this.initCamera(); + this.cameraManager = new CameraManager(this, { x: this.Map.widthInPixels, y: this.Map.heightInPixels }, waScaleManager); + biggestAvailableAreaStore.recompute(); + this.cameraManager.startFollow(this.CurrentPlayer); this.animatedTiles.init(this.Map); this.events.on("tileanimationupdate", () => (this.dirty = true)); @@ -590,7 +594,7 @@ export class GameScene extends DirtyScene { // From now, this game scene will be notified of reposition events this.biggestAvailableAreaStoreUnsubscribe = biggestAvailableAreaStore.subscribe((box) => - this.updateCameraOffset(box) + this.cameraManager.updateCameraOffset(box) ); new GameMapPropertiesListener(this, this.gameMap).register(); @@ -643,7 +647,7 @@ export class GameScene extends DirtyScene { * Initializes the connection to Pusher. */ private connect(): void { - const camera = this.cameras.main; + const camera = this.cameraManager.getCamera(); connectionManager .connectToRoomSocket( @@ -779,17 +783,30 @@ export class GameScene extends DirtyScene { }); }); + // P.H. TODO: Send those events to the iframe? this.gameMap.onEnterZone((zones) => { - console.log('enter zones'); - console.log(zones); + for (const zone of zones) { + for (const property of zone.properties ?? []) { + if (property.name === 'focusable' && property.value === true) { + this.cameraManager.changeCameraFocus(zone); + break; + } + } + } // zones.forEach((zone) => { // iframeListener.sendEnterLayerEvent(zone.name); // }); }); this.gameMap.onLeaveZone((zones) => { - console.log('leave zones'); - console.log(zones); + for (const zone of zones) { + for (const property of zone.properties ?? []) { + if (property.name === 'focusable' && property.value === true) { + this.cameraManager.startFollow(this.CurrentPlayer); + break; + } + } + } // zones.forEach((zone) => { // iframeListener.sendEnterLayerEvent(zone.name); // }); @@ -1478,13 +1495,6 @@ ${escapedMessage} } } - //todo: in a dedicated class/function? - initCamera() { - this.cameras.main.setBounds(0, 0, this.Map.widthInPixels, this.Map.heightInPixels); - this.cameras.main.startFollow(this.CurrentPlayer, true); - biggestAvailableAreaStore.recompute(); - } - createCollisionWithPlayer() { //add collision layer for (const phaserLayer of this.gameMap.phaserLayers) { @@ -1876,23 +1886,6 @@ ${escapedMessage} biggestAvailableAreaStore.recompute(); } - /** - * Updates the offset of the character compared to the center of the screen according to the layout manager - * (tries to put the character in the center of the remaining space if there is a discussion going on. - */ - private updateCameraOffset(array: Box): void { - const xCenter = (array.xEnd - array.xStart) / 2 + array.xStart; - const yCenter = (array.yEnd - array.yStart) / 2 + array.yStart; - - const game = HtmlUtils.querySelectorOrFail("#game canvas"); - // Let's put this in Game coordinates by applying the zoom level: - - this.cameras.main.setFollowOffset( - ((xCenter - game.offsetWidth / 2) * window.devicePixelRatio) / this.scale.zoom, - ((yCenter - game.offsetHeight / 2) * window.devicePixelRatio) / this.scale.zoom - ); - } - public startJitsi(roomName: string, jwt?: string): void { const allProps = this.gameMap.getCurrentProperties(); const jitsiConfig = this.safeParseJSONstring( @@ -1965,6 +1958,10 @@ ${escapedMessage} biggestAvailableAreaStore.recompute(); } + public setZoomModifierTo(value: number): void { + waScaleManager.zoomModifier = value; + } + public createSuccessorGameScene(autostart: boolean, reconnecting: boolean) { const gameSceneKey = "somekey" + Math.round(Math.random() * 10000); const game = new GameScene(this.room, this.MapUrlFile, gameSceneKey); diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index 5ceaeb71..3fb1d29b 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -5,7 +5,7 @@ import type { Game } from "../Game/Game"; import { ResizableScene } from "../Login/ResizableScene"; import { HtmlUtils } from "../../WebRtc/HtmlUtils"; -class WaScaleManager { +export class WaScaleManager { private hdpiManager: HdpiManager; private scaleManager!: ScaleManager; private game!: Game; diff --git a/front/src/types.ts b/front/src/types.ts index d957a2c2..409070e5 100644 --- a/front/src/types.ts +++ b/front/src/types.ts @@ -21,3 +21,34 @@ export interface IVirtualJoystick extends Phaser.GameObjects.GameObject { visible: boolean; createCursorKeys: () => CursorKeys; } + +export enum Easing { + Linear = "Linear", + QuadEaseIn = "Quad.easeIn", + CubicEaseIn = "Cubic.easeIn", + QuartEaseIn = "Quart.easeIn", + QuintEaseIn = "Quint.easeIn", + SineEaseIn = "Sine.easeIn", + ExpoEaseIn = "Expo.easeIn", + CircEaseIn = "Circ.easeIn", + BackEaseIn = "Back.easeIn", + BounceEaseIn = "Bounce.easeIn", + QuadEaseOut = "Quad.easeOut", + CubicEaseOut = "Cubic.easeOut", + QuartEaseOut = "Quart.easeOut", + QuintEaseOut = "Quint.easeOut", + SineEaseOut = "Sine.easeOut", + ExpoEaseOut = "Expo.easeOut", + CircEaseOut = "Circ.easeOut", + BackEaseOut = "Back.easeOut", + BounceEaseOut = "Bounce.easeOut", + QuadEaseInOut = "Quad.easeInOut", + CubicEaseInOut = "Cubic.easeInOut", + QuartEaseInOut = "Quart.easeInOut", + QuintEaseInOut = "Quint.easeInOut", + SineEaseInOut = "Sine.easeInOut", + ExpoEaseInOut = "Expo.easeInOut", + CircEaseInOut = "Circ.easeInOut", + BackEaseInOut = "Back.easeInOut", + BounceEaseInOut = "Bounce.easeInOut" +} diff --git a/maps/starter/map.json b/maps/starter/map.json index 31d81b19..2ef0516d 100644 --- a/maps/starter/map.json +++ b/maps/starter/map.json @@ -86,7 +86,7 @@ "y":0 }, { - "data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201], + "data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 212, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201], "height":17, "id":4, "name":"floor", @@ -170,6 +170,28 @@ "width":192, "x":32, "y":96 + }, + { + "height":64, + "id":11, + "name":"coffeeZone", + "properties":[ + { + "name":"display_name", + "type":"string", + "value":"Coffee Time!" + }, + { + "name":"focusable", + "type":"bool", + "value":true + }], + "rotation":0, + "type":"zone", + "visible":true, + "width":64, + "x":64, + "y":288 }], "opacity":1, "type":"objectgroup", @@ -214,7 +236,7 @@ "y":0 }], "nextlayerid":39, - "nextobjectid":11, + "nextobjectid":12, "orientation":"orthogonal", "properties":[ { From d0cd7b08067024941907af7711abc6cb6100d318 Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Thu, 2 Dec 2021 13:41:52 +0100 Subject: [PATCH 3/7] locking zooming via player input --- front/src/Phaser/Game/CameraManager.ts | 8 +++++++- front/src/Phaser/Game/GameScene.ts | 3 +++ front/src/Phaser/Services/WaScaleManager.ts | 10 ++++++++++ maps/starter/map.json | 12 ++++++------ 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts index 595867be..e900a059 100644 --- a/front/src/Phaser/Game/CameraManager.ts +++ b/front/src/Phaser/Game/CameraManager.ts @@ -28,7 +28,11 @@ export class CameraManager extends Phaser.Events.EventEmitter { return this.camera; } - public changeCameraFocus(focusOn: { x: number, y: number, width: number, height: number }, duration: number = 1000): void { + public changeCameraFocus( + focusOn: { x: number, y: number, width: number, height: number }, duration: number = 1000, + ): void { + this.waScaleManager.saveZoom(); + this.waScaleManager.lockZoomingViaPlayerInput(); const maxZoomModifier = 2.84; // How to get max zoom value? const currentZoomModifier = this.waScaleManager.zoomModifier; const zoomModifierChange = maxZoomModifier - currentZoomModifier; @@ -43,6 +47,8 @@ export class CameraManager extends Phaser.Events.EventEmitter { } public startFollow(target: object | Phaser.GameObjects.GameObject): void { + this.waScaleManager.lockZoomingViaPlayerInput(false); + this.waScaleManager.restoreZoom(); this.camera.startFollow(target, true); } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d596fa56..4afd0383 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1954,6 +1954,9 @@ ${escapedMessage} } zoomByFactor(zoomFactor: number) { + if (waScaleManager.isZoomingViaPlayerInputLocked()) { + return; + } waScaleManager.zoomModifier *= zoomFactor; biggestAvailableAreaStore.recompute(); } diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index 3fb1d29b..f8aeba2d 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -12,6 +12,8 @@ export class WaScaleManager { private actualZoom: number = 1; private _saveZoom: number = 1; + private zoomingViaPlayerInputLocked: boolean = false; + public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) { this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber); } @@ -21,6 +23,14 @@ export class WaScaleManager { this.game = game; } + public isZoomingViaPlayerInputLocked(): boolean { + return this.zoomingViaPlayerInputLocked; + } + + public lockZoomingViaPlayerInput(lock: boolean = true): void { + this.zoomingViaPlayerInputLocked = lock; + } + public applyNewSize() { const { width, height } = coWebsiteManager.getGameSize(); diff --git a/maps/starter/map.json b/maps/starter/map.json index 2ef0516d..2627a79e 100644 --- a/maps/starter/map.json +++ b/maps/starter/map.json @@ -172,14 +172,14 @@ "y":96 }, { - "height":64, + "height":352, "id":11, - "name":"coffeeZone", + "name":"meetingZone", "properties":[ { "name":"display_name", "type":"string", - "value":"Coffee Time!" + "value":"Brainstorm Zone!" }, { "name":"focusable", @@ -189,9 +189,9 @@ "rotation":0, "type":"zone", "visible":true, - "width":64, - "x":64, - "y":288 + "width":224, + "x":736, + "y":96 }], "opacity":1, "type":"objectgroup", From c09609f70c2cfa51cfabfb3028212f2637d22761 Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Thu, 2 Dec 2021 14:44:13 +0100 Subject: [PATCH 4/7] some more tweaks with smooth zooming control --- front/src/Phaser/Game/CameraManager.ts | 52 +++++++++++++++++++-- front/src/Phaser/Game/GameScene.ts | 6 +-- front/src/Phaser/Services/WaScaleManager.ts | 14 ++---- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts index e900a059..45621e1c 100644 --- a/front/src/Phaser/Game/CameraManager.ts +++ b/front/src/Phaser/Game/CameraManager.ts @@ -1,16 +1,26 @@ import { Easing } from '../../types'; import { HtmlUtils } from '../../WebRtc/HtmlUtils'; import type { Box } from '../../WebRtc/LayoutManager'; +import type { Player } from '../Player/Player'; import type { WaScaleManager } from '../Services/WaScaleManager'; import type { GameScene } from './GameScene'; +export enum CameraMode { + Free = 'Free', + Follow = 'Follow', + Focus = 'Focus', +} + export class CameraManager extends Phaser.Events.EventEmitter { private scene: GameScene; private camera: Phaser.Cameras.Scene2D.Camera; + private cameraBounds: { x: number, y: number }; private waScaleManager: WaScaleManager; - private cameraBounds: { x: number, y: number }; + private cameraMode: CameraMode = CameraMode.Free; + + private restoreZoomTween?: Phaser.Tweens.Tween; constructor(scene: GameScene, cameraBounds: { x: number, y: number }, waScaleManager: WaScaleManager) { super(); @@ -28,11 +38,13 @@ export class CameraManager extends Phaser.Events.EventEmitter { return this.camera; } - public changeCameraFocus( + public enterFocusMode( focusOn: { x: number, y: number, width: number, height: number }, duration: number = 1000, ): void { + this.setCameraMode(CameraMode.Focus); this.waScaleManager.saveZoom(); - this.waScaleManager.lockZoomingViaPlayerInput(); + + this.restoreZoomTween?.stop(); const maxZoomModifier = 2.84; // How to get max zoom value? const currentZoomModifier = this.waScaleManager.zoomModifier; const zoomModifierChange = maxZoomModifier - currentZoomModifier; @@ -46,9 +58,15 @@ export class CameraManager extends Phaser.Events.EventEmitter { }); } + public leaveFocusMode(player: Player): void { + // We are forcing camera.pan to kill previous pan animation on EnterFocusMode + this.camera.pan(player.x, player.y, 1, Easing.SineEaseOut, true); + this.startFollow(player); + this.restoreZoom(); + } + public startFollow(target: object | Phaser.GameObjects.GameObject): void { - this.waScaleManager.lockZoomingViaPlayerInput(false); - this.waScaleManager.restoreZoom(); + this.setCameraMode(CameraMode.Follow); this.camera.startFollow(target, true); } @@ -69,6 +87,30 @@ export class CameraManager extends Phaser.Events.EventEmitter { ); } + public isCameraLocked(): boolean { + return this.cameraMode === CameraMode.Focus; + } + + private setCameraMode(mode: CameraMode): void { + if (this.cameraMode === mode) { + return; + } + this.cameraMode = mode; + } + + private restoreZoom(): void { + this.restoreZoomTween?.stop(); + this.restoreZoomTween = this.scene.tweens.addCounter({ + from: this.waScaleManager.zoomModifier, + to: this.waScaleManager.getSaveZoom(), + duration: 1000, + ease: Easing.SineEaseOut, + onUpdate: (tween: Phaser.Tweens.Tween) => { + this.waScaleManager.zoomModifier = tween.getValue(); + } + }); + } + private initCamera() { this.camera = this.scene.cameras.main; this.camera.setBounds(0, 0, this.cameraBounds.x, this.cameraBounds.y); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 4afd0383..90297272 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -788,7 +788,7 @@ export class GameScene extends DirtyScene { for (const zone of zones) { for (const property of zone.properties ?? []) { if (property.name === 'focusable' && property.value === true) { - this.cameraManager.changeCameraFocus(zone); + this.cameraManager.enterFocusMode(zone); break; } } @@ -802,7 +802,7 @@ export class GameScene extends DirtyScene { for (const zone of zones) { for (const property of zone.properties ?? []) { if (property.name === 'focusable' && property.value === true) { - this.cameraManager.startFollow(this.CurrentPlayer); + this.cameraManager.leaveFocusMode(this.CurrentPlayer); break; } } @@ -1954,7 +1954,7 @@ ${escapedMessage} } zoomByFactor(zoomFactor: number) { - if (waScaleManager.isZoomingViaPlayerInputLocked()) { + if (this.cameraManager.isCameraLocked()) { return; } waScaleManager.zoomModifier *= zoomFactor; diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index f8aeba2d..ee2ca9ea 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -12,8 +12,6 @@ export class WaScaleManager { private actualZoom: number = 1; private _saveZoom: number = 1; - private zoomingViaPlayerInputLocked: boolean = false; - public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) { this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber); } @@ -23,14 +21,6 @@ export class WaScaleManager { this.game = game; } - public isZoomingViaPlayerInputLocked(): boolean { - return this.zoomingViaPlayerInputLocked; - } - - public lockZoomingViaPlayerInput(lock: boolean = true): void { - this.zoomingViaPlayerInputLocked = lock; - } - public applyNewSize() { const { width, height } = coWebsiteManager.getGameSize(); @@ -82,6 +72,10 @@ export class WaScaleManager { this._saveZoom = this.hdpiManager.zoomModifier; } + public getSaveZoom(): number { + return this._saveZoom; + } + public restoreZoom(): void { this.hdpiManager.zoomModifier = this._saveZoom; this.applyNewSize(); From 3e3a04d50ed0da07489a226fbdc77cac15d13648 Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Thu, 2 Dec 2021 17:46:09 +0100 Subject: [PATCH 5/7] working with zoom modifier calculating per zone --- front/src/Phaser/Game/CameraManager.ts | 6 +++--- front/src/Phaser/Game/GameScene.ts | 4 ---- front/src/Phaser/Services/WaScaleManager.ts | 18 ++++++++++++++---- maps/starter/map.json | 6 +++--- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts index 45621e1c..d8c385e6 100644 --- a/front/src/Phaser/Game/CameraManager.ts +++ b/front/src/Phaser/Game/CameraManager.ts @@ -45,16 +45,16 @@ export class CameraManager extends Phaser.Events.EventEmitter { this.waScaleManager.saveZoom(); this.restoreZoomTween?.stop(); - const maxZoomModifier = 2.84; // How to get max zoom value? + const targetZoomModifier = this.waScaleManager.getTargetZoomModifierFor(focusOn.width, focusOn.height); const currentZoomModifier = this.waScaleManager.zoomModifier; - const zoomModifierChange = maxZoomModifier - currentZoomModifier; + const zoomModifierChange = targetZoomModifier - currentZoomModifier; this.camera.stopFollow(); this.camera.pan( focusOn.x + focusOn.width * 0.5, focusOn.y + focusOn.height * 0.5, duration, Easing.SineEaseOut, false, (camera, progress, x, y) => { - this.scene.setZoomModifierTo(currentZoomModifier + progress * zoomModifierChange); + this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange; }); } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 90297272..b04788e3 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1961,10 +1961,6 @@ ${escapedMessage} biggestAvailableAreaStore.recompute(); } - public setZoomModifierTo(value: number): void { - waScaleManager.zoomModifier = value; - } - public createSuccessorGameScene(autostart: boolean, reconnecting: boolean) { const gameSceneKey = "somekey" + Math.round(Math.random() * 10000); const game = new GameScene(this.room, this.MapUrlFile, gameSceneKey); diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index ee2ca9ea..838f82d2 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -24,10 +24,7 @@ export class WaScaleManager { public applyNewSize() { const { width, height } = coWebsiteManager.getGameSize(); - let devicePixelRatio = 1; - if (window.devicePixelRatio) { - devicePixelRatio = window.devicePixelRatio; - } + const devicePixelRatio = window.devicePixelRatio ?? 1; const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({ width: width * devicePixelRatio, @@ -59,6 +56,19 @@ export class WaScaleManager { this.game.markDirty(); } + public getTargetZoomModifierFor(viewportWidth: number, viewportHeight: number) { + const { width: gameWidth, height: gameHeight } = coWebsiteManager.getGameSize(); + const devicePixelRatio = window.devicePixelRatio ?? 1; + + const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({ + width: gameWidth * devicePixelRatio, + height: gameHeight * devicePixelRatio, + }); + // P.H. Note: Dunno where this magic 2 comes from + // Always return lowest possible value. Need to add MAX ZOOM MODIFIER value into this. + return Math.min(realSize.width / viewportWidth / 2, realSize.height / viewportHeight / 2); + } + public get zoomModifier(): number { return this.hdpiManager.zoomModifier; } diff --git a/maps/starter/map.json b/maps/starter/map.json index 2627a79e..fd0b984e 100644 --- a/maps/starter/map.json +++ b/maps/starter/map.json @@ -86,7 +86,7 @@ "y":0 }, { - "data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 212, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201], + "data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201], "height":17, "id":4, "name":"floor", @@ -172,7 +172,7 @@ "y":96 }, { - "height":352, + "height":416, "id":11, "name":"meetingZone", "properties":[ @@ -191,7 +191,7 @@ "visible":true, "width":224, "x":736, - "y":96 + "y":32 }], "opacity":1, "type":"objectgroup", From e792b75ad35e97080605cc0db4e40f43b28cecd0 Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Thu, 2 Dec 2021 18:11:22 +0100 Subject: [PATCH 6/7] issues with zone triggering fixed --- front/src/Phaser/Game/GameMap.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index 85a1a0e0..b2fab07d 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -116,22 +116,22 @@ export class GameMap { public setPosition(x: number, y: number) { this.oldPosition = this.position; this.position = { x, y }; - + this.triggerZonesChange(); + this.oldKey = this.key; - + 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; - + this.triggerAllProperties(); this.triggerLayersChange(); - this.triggerZonesChange(); } private triggerAllProperties(): void { From 831d238be7982c896073d85867f8fbb04599a73d Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Fri, 3 Dec 2021 10:11:16 +0100 Subject: [PATCH 7/7] ran prettier --- front/src/Phaser/Game/CameraManager.ts | 37 ++++++++------- front/src/Phaser/Game/GameMap.ts | 62 +++++++++++++++----------- front/src/Phaser/Game/GameScene.ts | 12 +++-- front/src/Utils/MathUtils.ts | 16 +++---- front/src/types.ts | 2 +- 5 files changed, 71 insertions(+), 58 deletions(-) diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts index d8c385e6..00006a7d 100644 --- a/front/src/Phaser/Game/CameraManager.ts +++ b/front/src/Phaser/Game/CameraManager.ts @@ -1,28 +1,27 @@ -import { Easing } from '../../types'; -import { HtmlUtils } from '../../WebRtc/HtmlUtils'; -import type { Box } from '../../WebRtc/LayoutManager'; -import type { Player } from '../Player/Player'; -import type { WaScaleManager } from '../Services/WaScaleManager'; -import type { GameScene } from './GameScene'; +import { Easing } from "../../types"; +import { HtmlUtils } from "../../WebRtc/HtmlUtils"; +import type { Box } from "../../WebRtc/LayoutManager"; +import type { Player } from "../Player/Player"; +import type { WaScaleManager } from "../Services/WaScaleManager"; +import type { GameScene } from "./GameScene"; export enum CameraMode { - Free = 'Free', - Follow = 'Follow', - Focus = 'Focus', + Free = "Free", + Follow = "Follow", + Focus = "Focus", } export class CameraManager extends Phaser.Events.EventEmitter { - private scene: GameScene; private camera: Phaser.Cameras.Scene2D.Camera; - private cameraBounds: { x: number, y: number }; + private cameraBounds: { x: number; y: number }; private waScaleManager: WaScaleManager; private cameraMode: CameraMode = CameraMode.Free; private restoreZoomTween?: Phaser.Tweens.Tween; - constructor(scene: GameScene, cameraBounds: { x: number, y: number }, waScaleManager: WaScaleManager) { + constructor(scene: GameScene, cameraBounds: { x: number; y: number }, waScaleManager: WaScaleManager) { super(); this.scene = scene; @@ -39,7 +38,8 @@ export class CameraManager extends Phaser.Events.EventEmitter { } public enterFocusMode( - focusOn: { x: number, y: number, width: number, height: number }, duration: number = 1000, + focusOn: { x: number; y: number; width: number; height: number }, + duration: number = 1000 ): void { this.setCameraMode(CameraMode.Focus); this.waScaleManager.saveZoom(); @@ -53,9 +53,12 @@ export class CameraManager extends Phaser.Events.EventEmitter { focusOn.x + focusOn.width * 0.5, focusOn.y + focusOn.height * 0.5, duration, - Easing.SineEaseOut, false, (camera, progress, x, y) => { + Easing.SineEaseOut, + false, + (camera, progress, x, y) => { this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange; - }); + } + ); } public leaveFocusMode(player: Player): void { @@ -107,7 +110,7 @@ export class CameraManager extends Phaser.Events.EventEmitter { ease: Easing.SineEaseOut, onUpdate: (tween: Phaser.Tweens.Tween) => { this.waScaleManager.zoomModifier = tween.getValue(); - } + }, }); } @@ -115,4 +118,4 @@ export class CameraManager extends Phaser.Events.EventEmitter { this.camera = this.scene.cameras.main; this.camera.setBounds(0, 0, this.cameraBounds.x, this.cameraBounds.y); } -} \ No newline at end of file +} diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index b2fab07d..40588923 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -1,9 +1,15 @@ -import type { ITiledMap, ITiledMapLayer, ITiledMapObject, ITiledMapObjectLayer, ITiledMapProperty } from "../Map/ITiledMap"; +import type { + ITiledMap, + ITiledMapLayer, + ITiledMapObject, + ITiledMapObjectLayer, + ITiledMapProperty, +} from "../Map/ITiledMap"; import { flattenGroupLayersMap } from "../Map/LayersFlattener"; import TilemapLayer = Phaser.Tilemaps.TilemapLayer; import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes"; import { GameMapProperties } from "./GameMapProperties"; -import { MathUtils } from '../../Utils/MathUtils'; +import { MathUtils } from "../../Utils/MathUtils"; export type PropertyChangeCallback = ( newValue: string | number | boolean | undefined, @@ -28,20 +34,20 @@ export type zoneChangeCallback = ( export class GameMap { /** * oldKey is the index of the previous tile. - */ + */ private oldKey: number | undefined; /** * key is the index of the current tile. - */ + */ private key: number | undefined; /** * oldPosition is the previous position of the player. */ - private oldPosition: { x: number, y: number } | undefined; + private oldPosition: { x: number; y: number } | undefined; /** * position is the current position of the player. */ - private position: { x: number, y: number } | undefined; + private position: { x: number; y: number } | undefined; private lastProperties = new Map(); private propertiesChangeCallbacks = new Map>(); @@ -117,19 +123,19 @@ export class GameMap { this.oldPosition = this.position; this.position = { x, y }; this.triggerZonesChange(); - + this.oldKey = this.key; - + 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; - + this.triggerAllProperties(); this.triggerLayersChange(); } @@ -189,25 +195,27 @@ export class GameMap { * We user Tiled Objects with type "zone" as zones with defined x, y, width and height for easier event triggering. */ private triggerZonesChange(): void { - const zones = this.tiledObjects.filter(object => object.type === "zone"); + const zones = this.tiledObjects.filter((object) => object.type === "zone"); // P.H. NOTE: We could also get all of the zones and add properties of occupied tiles to them, so we could later on check collision by using tileKeys // TODO: Change this to an array with currently occupied sone instead of doing elimination process - const zonesByOldPosition = this.oldPosition ? - zones.filter((zone) => { - if (!this.oldPosition) { - return false; - } - return MathUtils.isOverlappingWithRectangle(this.oldPosition, zone); - }) : []; + const zonesByOldPosition = this.oldPosition + ? zones.filter((zone) => { + if (!this.oldPosition) { + return false; + } + return MathUtils.isOverlappingWithRectangle(this.oldPosition, zone); + }) + : []; - const zonesByNewPosition = this.position ? - zones.filter((zone) => { - if (!this.position) { - return false; - } - return MathUtils.isOverlappingWithRectangle(this.position, zone); - }) : []; + const zonesByNewPosition = this.position + ? zones.filter((zone) => { + if (!this.position) { + return false; + } + return MathUtils.isOverlappingWithRectangle(this.position, zone); + }) + : []; const enterZones = new Set(zonesByNewPosition); const leaveZones = new Set(zonesByOldPosition); @@ -459,7 +467,7 @@ export class GameMap { private getObjectsFromLayers(layers: ITiledMapLayer[]): ITiledMapObject[] { const objects: ITiledMapObject[] = []; - const objectLayers = layers.filter(layer => layer.type === "objectgroup"); + const objectLayers = layers.filter((layer) => layer.type === "objectgroup"); for (const objectLayer of objectLayers) { if (this.isOfTypeITiledMapObjectLayer(objectLayer)) { objects.push(...objectLayer.objects); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index b04788e3..78b56327 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -60,7 +60,7 @@ import { PinchManager } from "../UserInput/PinchManager"; import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick"; import { waScaleManager } from "../Services/WaScaleManager"; import { EmoteManager } from "./EmoteManager"; -import { CameraManager } from './CameraManager'; +import { CameraManager } from "./CameraManager"; import EVENT_TYPE = Phaser.Scenes.Events; import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent"; @@ -551,7 +551,11 @@ export class GameScene extends DirtyScene { this.createCurrentPlayer(); this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted - this.cameraManager = new CameraManager(this, { x: this.Map.widthInPixels, y: this.Map.heightInPixels }, waScaleManager); + this.cameraManager = new CameraManager( + this, + { x: this.Map.widthInPixels, y: this.Map.heightInPixels }, + waScaleManager + ); biggestAvailableAreaStore.recompute(); this.cameraManager.startFollow(this.CurrentPlayer); @@ -787,7 +791,7 @@ export class GameScene extends DirtyScene { this.gameMap.onEnterZone((zones) => { for (const zone of zones) { for (const property of zone.properties ?? []) { - if (property.name === 'focusable' && property.value === true) { + if (property.name === "focusable" && property.value === true) { this.cameraManager.enterFocusMode(zone); break; } @@ -801,7 +805,7 @@ export class GameScene extends DirtyScene { this.gameMap.onLeaveZone((zones) => { for (const zone of zones) { for (const property of zone.properties ?? []) { - if (property.name === 'focusable' && property.value === true) { + if (property.name === "focusable" && property.value === true) { this.cameraManager.leaveFocusMode(this.CurrentPlayer); break; } diff --git a/front/src/Utils/MathUtils.ts b/front/src/Utils/MathUtils.ts index 098b86b4..aea3bb11 100644 --- a/front/src/Utils/MathUtils.ts +++ b/front/src/Utils/MathUtils.ts @@ -1,27 +1,25 @@ - export class MathUtils { - /** - * + * * @param p Position to check. * @param r Rectangle to check the overlap against. * @returns true is overlapping */ public static isOverlappingWithRectangle( - p: { x: number, y: number}, - r: { x: number, y: number, width: number, height: number}, + p: { x: number; y: number }, + r: { x: number; y: number; width: number; height: number } ): boolean { - return (this.isBetween(p.x, r.x, r.x + r.width) && this.isBetween(p.y, r.y, r.y + r.height)); + return this.isBetween(p.x, r.x, r.x + r.width) && this.isBetween(p.y, r.y, r.y + r.height); } /** - * + * * @param value Value to check * @param min inclusive min value * @param max inclusive max value * @returns true if value is in */ public static isBetween(value: number, min: number, max: number): boolean { - return (value >= min) && (value <= max); + return value >= min && value <= max; } -} \ No newline at end of file +} diff --git a/front/src/types.ts b/front/src/types.ts index 409070e5..d1ff3475 100644 --- a/front/src/types.ts +++ b/front/src/types.ts @@ -50,5 +50,5 @@ export enum Easing { ExpoEaseInOut = "Expo.easeInOut", CircEaseInOut = "Circ.easeInOut", BackEaseInOut = "Back.easeInOut", - BounceEaseInOut = "Bounce.easeInOut" + BounceEaseInOut = "Bounce.easeInOut", }