From c7fa5cab8bf5651eeb59f70e92bf730a9873ba92 Mon Sep 17 00:00:00 2001 From: jonny Date: Fri, 25 Jun 2021 17:57:09 +0200 Subject: [PATCH] cleanup --- front/src/Phaser/Game/GameScene.ts | 94 ++------------ .../Phaser/Game/StartPositionCalculator.ts | 117 ++++++++++++++++++ 2 files changed, 129 insertions(+), 82 deletions(-) create mode 100644 front/src/Phaser/Game/StartPositionCalculator.ts diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 98e990ef..458e5f96 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -96,6 +96,7 @@ import { peerStore } from "../../Stores/PeerStore"; import { EmoteManager } from "./EmoteManager"; import AnimatedTiles from "phaser-animated-tiles"; +import { StartPositionCalculator } from './StartPositionCalculator'; export interface GameSceneInitInterface { initPosition: PointInterface | null, @@ -132,7 +133,6 @@ interface DeleteGroupEventInterface { groupId: number } -const defaultStartLayerName = 'start'; export class GameScene extends DirtyScene implements CenterListener { Terrains: Array; @@ -145,8 +145,6 @@ export class GameScene extends DirtyScene implements CenterListener { mapFile!: ITiledMap; animatedTiles!: AnimatedTiles; groups: Map; - startX!: number; - startY!: number; circleTexture!: CanvasTexture; circleRedTexture!: CanvasTexture; pendingEvents: Queue = new Queue(); @@ -183,7 +181,6 @@ export class GameScene extends DirtyScene implements CenterListener { private outlinedItem: ActionableItem | null = null; public userInputManager!: UserInputManager; private isReconnecting: boolean | undefined = undefined; - private startLayerName!: string | null; private openChatIcon!: OpenChatIcon; private playerName!: string; private characterLayers!: string[]; @@ -194,6 +191,7 @@ export class GameScene extends DirtyScene implements CenterListener { private pinchManager: PinchManager | undefined; private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time. private emoteManager!: EmoteManager; + startPositionCalculator!: StartPositionCalculator; constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) { super({ @@ -395,7 +393,6 @@ export class GameScene extends DirtyScene implements CenterListener { gameManager.gameSceneIsCreated(this); urlManager.pushRoomIdToUrl(this.room); - this.startLayerName = urlManager.getStartLayerNameFromUrl(); if (touchScreenManager.supportTouchScreen) { this.pinchManager = new PinchManager(this); @@ -458,7 +455,9 @@ export class GameScene extends DirtyScene implements CenterListener { throw new Error('Your map MUST contain a layer of type "objectgroup" whose name is "floorLayer" that represents the layer characters are drawn at. This layer cannot be contained in a group.'); } - this.initStartXAndStartY(); + this.startPositionCalculator = new StartPositionCalculator(this.gameMap, this.mapFile, this.initPosition, urlManager.getStartLayerNameFromUrl()) + + //add entities this.Objects = new Array(); @@ -563,8 +562,8 @@ export class GameScene extends DirtyScene implements CenterListener { this.playerName, this.characterLayers, { - x: this.startX, - y: this.startY + x: this.startPositionCalculator.startX, + y: this.startPositionCalculator.startY }, { left: camera.scrollX, @@ -970,9 +969,9 @@ ${escapedMessage} this.scene.start(roomId); } else { //if the exit points to the current map, we simply teleport the user back to the startLayer - this.initPositionFromLayerName(hash || defaultStartLayerName, hash); - this.CurrentPlayer.x = this.startX; - this.CurrentPlayer.y = this.startY; + this.startPositionCalculator.initPositionFromLayerName(hash, hash); + this.CurrentPlayer.x = this.startPositionCalculator.startX; + this.CurrentPlayer.y = this.startPositionCalculator.startY; setTimeout(() => this.mapTransitioning = false, 500); } } @@ -1035,40 +1034,7 @@ ${escapedMessage} } } - private initStartXAndStartY() { - // If there is an init position passed - if (this.initPosition !== null) { - this.startX = this.initPosition.x; - this.startY = this.initPosition.y; - } else { - // Now, let's find the start layer - if (this.startLayerName) { - this.initPositionFromLayerName(this.startLayerName, this.startLayerName); - } - if (this.startX === undefined) { - // If we have no start layer specified or if the hash passed does not exist, let's go with the default start position. - this.initPositionFromLayerName(defaultStartLayerName, this.startLayerName); - } - } - // Still no start position? Something is wrong with the map, we need a "start" layer. - if (this.startX === undefined) { - console.warn('This map is missing a layer named "start" that contains the available default start positions.'); - // Let's start in the middle of the map - this.startX = this.mapFile.width * 16; - this.startY = this.mapFile.height * 16; - } - } - private initPositionFromLayerName(selectedOrdDefaultLayer: string, selectedLayer: string | null) { - for (const layer of this.gameMap.layersIterator) { - if ((selectedOrdDefaultLayer === layer.name || layer.name.endsWith('/' + selectedOrdDefaultLayer)) && layer.type === 'tilelayer' && (selectedOrdDefaultLayer === defaultStartLayerName || this.isStartLayer(layer))) { - const startPosition = this.startUser(layer, selectedLayer); - this.startX = startPosition.x + this.mapFile.tilewidth / 2; - this.startY = startPosition.y + this.mapFile.tileheight / 2; - } - } - - } private getExitUrl(layer: ITiledMapLayer): string | undefined { return this.getProperty(layer, "exitUrl") as string | undefined; @@ -1081,10 +1047,6 @@ ${escapedMessage} return this.getProperty(layer, "exitSceneUrl") as string | undefined; } - private isStartLayer(layer: ITiledMapLayer): boolean { - return this.getProperty(layer, "startLayer") == true; - } - private getScriptUrls(map: ITiledMap): string[] { return (this.getProperties(map, "script") as string[]).map((script) => (new URL(script, this.MapUrlFile)).toString()); } @@ -1116,38 +1078,6 @@ ${escapedMessage} return gameManager.loadMap(room, this.scene).catch(() => { }); } - private startUser(selectedOrDefaultLayer: ITiledMapTileLayer, startName: string | null): PositionInterface { - const tiles = selectedOrDefaultLayer.data; - if (typeof (tiles) === 'string') { - throw new Error('The content of a JSON map must be filled as a JSON array, not as a string'); - } - const possibleStartPositions: PositionInterface[] = []; - tiles.forEach((objectKey: number, key: number) => { - if (objectKey === 0) { - return; - } - const y = Math.floor(key / selectedOrDefaultLayer.width); - const x = key % selectedOrDefaultLayer.width; - - if (startName && this.gameMap.hasStartTile) { - const properties = this.gameMap.getPropertiesForIndex(objectKey); - if (!properties.length || !properties.some(property => property.name == "start" && property.value == startName)) { - return - } - } - possibleStartPositions.push({ x: x * this.mapFile.tilewidth, y: y * this.mapFile.tilewidth }); - }); - // Get a value at random amongst allowed values - if (possibleStartPositions.length === 0) { - console.warn('The start layer "' + selectedOrDefaultLayer.name + '" for this map is empty.'); - return { - x: 0, - y: 0 - }; - } - // Choose one of the available start positions at random amongst the list of available start positions. - return possibleStartPositions[Math.floor(Math.random() * possibleStartPositions.length)]; - } //todo: in a dedicated class/function? initCamera() { @@ -1184,8 +1114,8 @@ ${escapedMessage} try { this.CurrentPlayer = new Player( this, - this.startX, - this.startY, + this.startPositionCalculator.startX, + this.startPositionCalculator.startY, this.playerName, texturesPromise, PlayerAnimationDirections.Down, diff --git a/front/src/Phaser/Game/StartPositionCalculator.ts b/front/src/Phaser/Game/StartPositionCalculator.ts new file mode 100644 index 00000000..5dc454aa --- /dev/null +++ b/front/src/Phaser/Game/StartPositionCalculator.ts @@ -0,0 +1,117 @@ +import type { PositionInterface } from '../../Connexion/ConnexionModels'; +import type { ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapTileLayer } from '../Map/ITiledMap'; +import type { GameMap } from './GameMap'; + + +const defaultStartLayerName = 'start'; + +export class StartPositionCalculator { + public startX!: number; + public startY!: number; + + + + constructor( + private readonly gameMap: GameMap, + private readonly mapFile: ITiledMap, + private readonly initPosition: PositionInterface | null, + private readonly startLayerName: string | null) { + this.initStartXAndStartY(); + } + private initStartXAndStartY() { + // If there is an init position passed + if (this.initPosition !== null) { + this.startX = this.initPosition.x; + this.startY = this.initPosition.y; + } else { + // Now, let's find the start layer + if (this.startLayerName) { + this.initPositionFromLayerName(this.startLayerName, this.startLayerName); + } + if (this.startX === undefined) { + // If we have no start layer specified or if the hash passed does not exist, let's go with the default start position. + this.initPositionFromLayerName(defaultStartLayerName, this.startLayerName); + } + } + // Still no start position? Something is wrong with the map, we need a "start" layer. + if (this.startX === undefined) { + console.warn('This map is missing a layer named "start" that contains the available default start positions.'); + // Let's start in the middle of the map + this.startX = this.mapFile.width * 16; + this.startY = this.mapFile.height * 16; + } + } + + /** + * + * @param selectedLayer this is always the layer that is selected with the hash in the url + * @param selectedOrDefaultLayer this can also be the {defaultStartLayerName} if the {selectedLayer} didnt yield any start points + */ + public initPositionFromLayerName(selectedOrDefaultLayer: string | null, selectedLayer: string | null) { + if (!selectedOrDefaultLayer) { + selectedOrDefaultLayer = defaultStartLayerName + } + for (const layer of this.gameMap.layersIterator) { + if ((selectedOrDefaultLayer === layer.name || layer.name.endsWith('/' + selectedOrDefaultLayer)) && layer.type === 'tilelayer' && (selectedOrDefaultLayer === defaultStartLayerName || this.isStartLayer(layer))) { + const startPosition = this.startUser(layer, selectedLayer); + this.startX = startPosition.x + this.mapFile.tilewidth / 2; + this.startY = startPosition.y + this.mapFile.tileheight / 2; + } + } + + } + + private isStartLayer(layer: ITiledMapLayer): boolean { + return this.getProperty(layer, "startLayer") == true; + } + + /** + * + * @param selectedLayer this is always the layer that is selected with the hash in the url + * @param selectedOrDefaultLayer this can also be the default layer if the {selectedLayer} didnt yield any start points + */ + private startUser(selectedOrDefaultLayer: ITiledMapTileLayer, selectedLayer: string | null): PositionInterface { + const tiles = selectedOrDefaultLayer.data; + if (typeof (tiles) === 'string') { + throw new Error('The content of a JSON map must be filled as a JSON array, not as a string'); + } + const possibleStartPositions: PositionInterface[] = []; + tiles.forEach((objectKey: number, key: number) => { + if (objectKey === 0) { + return; + } + const y = Math.floor(key / selectedOrDefaultLayer.width); + const x = key % selectedOrDefaultLayer.width; + + if (selectedLayer && this.gameMap.hasStartTile) { + const properties = this.gameMap.getPropertiesForIndex(objectKey); + if (!properties.length || !properties.some(property => property.name == "start" && property.value == selectedLayer)) { + return + } + } + possibleStartPositions.push({ x: x * this.mapFile.tilewidth, y: y * this.mapFile.tilewidth }); + }); + // Get a value at random amongst allowed values + if (possibleStartPositions.length === 0) { + console.warn('The start layer "' + selectedOrDefaultLayer.name + '" for this map is empty.'); + return { + x: 0, + y: 0 + }; + } + // Choose one of the available start positions at random amongst the list of available start positions. + return possibleStartPositions[Math.floor(Math.random() * possibleStartPositions.length)]; + } + + private getProperty(layer: ITiledMapLayer | ITiledMap, name: string): string | boolean | number | undefined { + const properties: ITiledMapLayerProperty[] | undefined = layer.properties; + if (!properties) { + return undefined; + } + const obj = properties.find((property: ITiledMapLayerProperty) => property.name.toLowerCase() === name.toLowerCase()); + if (obj === undefined) { + return undefined; + } + return obj.value; + } +} \ No newline at end of file