Merge remote-tracking branch 'remotes/upstream/develop' into tiles-start-positions
This commit is contained in:
commit
7f61e9addd
182 changed files with 17118 additions and 4494 deletions
|
@ -1,17 +1,17 @@
|
|||
import {ResizableScene} from "../Login/ResizableScene";
|
||||
import { ResizableScene } from "../Login/ResizableScene";
|
||||
import GameObject = Phaser.GameObjects.GameObject;
|
||||
import Events = Phaser.Scenes.Events;
|
||||
import AnimationEvents = Phaser.Animations.Events;
|
||||
import StructEvents = Phaser.Structs.Events;
|
||||
import {SKIP_RENDER_OPTIMIZATIONS} from "../../Enum/EnvironmentVariable";
|
||||
import { SKIP_RENDER_OPTIMIZATIONS } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
/**
|
||||
* A scene that can track its dirty/pristine state.
|
||||
*/
|
||||
export abstract class DirtyScene extends ResizableScene {
|
||||
private isAlreadyTracking: boolean = false;
|
||||
protected dirty:boolean = true;
|
||||
private objectListChanged:boolean = true;
|
||||
protected dirty: boolean = true;
|
||||
private objectListChanged: boolean = true;
|
||||
private physicsEnabled: boolean = false;
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,7 @@ export abstract class DirtyScene extends ResizableScene {
|
|||
|
||||
this.events.on(Events.RENDER, () => {
|
||||
this.objectListChanged = false;
|
||||
this.dirty = false;
|
||||
});
|
||||
|
||||
this.physics.disableUpdate();
|
||||
|
@ -58,7 +59,6 @@ export abstract class DirtyScene extends ResizableScene {
|
|||
this.physicsEnabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private trackAnimation(): void {
|
||||
|
@ -70,7 +70,7 @@ export abstract class DirtyScene extends ResizableScene {
|
|||
}
|
||||
|
||||
public markDirty(): void {
|
||||
this.events.once(Phaser.Scenes.Events.POST_UPDATE, () => this.dirty = true);
|
||||
this.events.once(Phaser.Scenes.Events.POST_UPDATE, () => (this.dirty = true));
|
||||
}
|
||||
|
||||
public onResize(): void {
|
||||
|
|
|
@ -1,31 +1,24 @@
|
|||
import {GameScene} from "./GameScene";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import type {Room} from "../../Connexion/Room";
|
||||
import {MenuScene, MenuSceneName} from "../Menu/MenuScene";
|
||||
import {LoginSceneName} from "../Login/LoginScene";
|
||||
import {SelectCharacterSceneName} from "../Login/SelectCharacterScene";
|
||||
import {EnableCameraSceneName} from "../Login/EnableCameraScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {get} from "svelte/store";
|
||||
import {requestedCameraState, requestedMicrophoneState} from "../../Stores/MediaStore";
|
||||
import {helpCameraSettingsVisibleStore} from "../../Stores/HelpCameraSettingsStore";
|
||||
|
||||
export interface HasMovedEvent {
|
||||
direction: string;
|
||||
moving: boolean;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
import { GameScene } from "./GameScene";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import type { Room } from "../../Connexion/Room";
|
||||
import { MenuScene, MenuSceneName } from "../Menu/MenuScene";
|
||||
import { LoginSceneName } from "../Login/LoginScene";
|
||||
import { SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import { EnableCameraSceneName } from "../Login/EnableCameraScene";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { get } from "svelte/store";
|
||||
import { requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
|
||||
import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore";
|
||||
|
||||
/**
|
||||
* This class should be responsible for any scene starting/stopping
|
||||
*/
|
||||
export class GameManager {
|
||||
private playerName: string|null;
|
||||
private characterLayers: string[]|null;
|
||||
private companion: string|null;
|
||||
private startRoom!:Room;
|
||||
currentGameSceneName: string|null = null;
|
||||
private playerName: string | null;
|
||||
private characterLayers: string[] | null;
|
||||
private companion: string | null;
|
||||
private startRoom!: Room;
|
||||
currentGameSceneName: string | null = null;
|
||||
|
||||
constructor() {
|
||||
this.playerName = localUserStore.getName();
|
||||
|
@ -56,23 +49,22 @@ export class GameManager {
|
|||
localUserStore.setCharacterLayers(layers);
|
||||
}
|
||||
|
||||
getPlayerName(): string|null {
|
||||
getPlayerName(): string | null {
|
||||
return this.playerName;
|
||||
}
|
||||
|
||||
getCharacterLayers(): string[] {
|
||||
if (!this.characterLayers) {
|
||||
throw 'characterLayers are not set';
|
||||
throw "characterLayers are not set";
|
||||
}
|
||||
return this.characterLayers;
|
||||
}
|
||||
|
||||
|
||||
setCompanion(companion: string|null): void {
|
||||
setCompanion(companion: string | null): void {
|
||||
this.companion = companion;
|
||||
}
|
||||
|
||||
getCompanion(): string|null {
|
||||
getCompanion(): string | null {
|
||||
return this.companion;
|
||||
}
|
||||
|
||||
|
@ -81,18 +73,21 @@ export class GameManager {
|
|||
const mapDetail = await room.getMapDetail();
|
||||
|
||||
const gameIndex = scenePlugin.getIndex(roomID);
|
||||
if(gameIndex === -1){
|
||||
const game : Phaser.Scene = new GameScene(room, mapDetail.mapUrl);
|
||||
if (gameIndex === -1) {
|
||||
const game: Phaser.Scene = new GameScene(room, mapDetail.mapUrl);
|
||||
scenePlugin.add(roomID, game, false);
|
||||
}
|
||||
}
|
||||
|
||||
public goToStartingMap(scenePlugin: Phaser.Scenes.ScenePlugin): void {
|
||||
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
|
||||
console.log("starting " + (this.currentGameSceneName || this.startRoom.id));
|
||||
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
|
||||
scenePlugin.launch(MenuSceneName);
|
||||
|
||||
if(!localUserStore.getHelpCameraSettingsShown() && (!get(requestedMicrophoneState) || !get(requestedCameraState))){
|
||||
if (
|
||||
!localUserStore.getHelpCameraSettingsShown() &&
|
||||
(!get(requestedMicrophoneState) || !get(requestedCameraState))
|
||||
) {
|
||||
helpCameraSettingsVisibleStore.set(true);
|
||||
localUserStore.setHelpCameraSettingsShown();
|
||||
}
|
||||
|
@ -109,7 +104,7 @@ export class GameManager {
|
|||
* This will close the socket connections and stop the gameScene, but won't remove it.
|
||||
*/
|
||||
leaveGame(scene: Phaser.Scene, targetSceneName: string, sceneClass: Phaser.Scene): void {
|
||||
if (this.currentGameSceneName === null) throw 'No current scene id set!';
|
||||
if (this.currentGameSceneName === null) throw "No current scene id set!";
|
||||
const gameScene: GameScene = scene.scene.get(this.currentGameSceneName) as GameScene;
|
||||
gameScene.cleanupClosingScene();
|
||||
scene.scene.stop(this.currentGameSceneName);
|
||||
|
@ -128,13 +123,13 @@ export class GameManager {
|
|||
scene.scene.start(this.currentGameSceneName);
|
||||
scene.scene.wake(MenuSceneName);
|
||||
} else {
|
||||
scene.scene.run(fallbackSceneName)
|
||||
scene.scene.run(fallbackSceneName);
|
||||
}
|
||||
}
|
||||
|
||||
public getCurrentGameScene(scene: Phaser.Scene): GameScene {
|
||||
if (this.currentGameSceneName === null) throw 'No current scene id set!';
|
||||
return scene.scene.get(this.currentGameSceneName) as GameScene
|
||||
if (this.currentGameSceneName === null) throw "No current scene id set!";
|
||||
return scene.scene.get(this.currentGameSceneName) as GameScene;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
import type { ITiledMap, ITiledMapLayerProperty } from "../Map/ITiledMap";
|
||||
import { LayersIterator } from "../Map/LayersIterator";
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapLayerProperty } from "../Map/ITiledMap";
|
||||
import { flattenGroupLayersMap } from "../Map/LayersFlattener";
|
||||
import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
|
||||
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
|
||||
|
||||
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
|
||||
export type PropertyChangeCallback = (
|
||||
newValue: string | number | boolean | undefined,
|
||||
oldValue: string | number | boolean | undefined,
|
||||
allProps: Map<string, string | boolean | number>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* A wrapper around a ITiledMap interface to provide additional capabilities.
|
||||
|
@ -12,41 +18,52 @@ export class GameMap {
|
|||
private lastProperties = new Map<string, string | boolean | number>();
|
||||
private callbacks = new Map<string, Array<PropertyChangeCallback>>();
|
||||
|
||||
private tileSetPropertyMap: { [tile_index: number]: Array<ITiledMapLayerProperty> } = {}
|
||||
public readonly layersIterator: LayersIterator;
|
||||
private tileSetPropertyMap: { [tile_index: number]: Array<ITiledMapLayerProperty> } = {};
|
||||
public readonly flatLayers: ITiledMapLayer[];
|
||||
public readonly phaserLayers: TilemapLayer[] = [];
|
||||
|
||||
public exitUrls: Array<string> = []
|
||||
public exitUrls: Array<string> = [];
|
||||
|
||||
public hasStartTile = false;
|
||||
|
||||
public constructor(private map: ITiledMap) {
|
||||
this.layersIterator = new LayersIterator(map);
|
||||
|
||||
public constructor(
|
||||
private map: ITiledMap,
|
||||
phaserMap: Phaser.Tilemaps.Tilemap,
|
||||
terrains: Array<Phaser.Tilemaps.Tileset>
|
||||
) {
|
||||
this.flatLayers = flattenGroupLayersMap(map);
|
||||
let depth = -2;
|
||||
for (const layer of this.flatLayers) {
|
||||
if (layer.type === "tilelayer") {
|
||||
this.phaserLayers.push(phaserMap.createLayer(layer.name, terrains, 0, 0).setDepth(depth));
|
||||
}
|
||||
if (layer.type === "objectgroup" && layer.name === "floorLayer") {
|
||||
depth = DEPTH_OVERLAY_INDEX;
|
||||
}
|
||||
}
|
||||
for (const tileset of map.tilesets) {
|
||||
tileset?.tiles?.forEach(tile => {
|
||||
tileset?.tiles?.forEach((tile) => {
|
||||
if (tile.properties) {
|
||||
this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties
|
||||
tile.properties.forEach(prop => {
|
||||
this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties;
|
||||
tile.properties.forEach((prop) => {
|
||||
if (prop.name == "exitUrl" && typeof prop.value == "string") {
|
||||
this.exitUrls.push(prop.value);
|
||||
} else if (prop.name == "start") {
|
||||
this.hasStartTile = true
|
||||
this.hasStartTile = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public getPropertiesForIndex(index: number): Array<ITiledMapLayerProperty> {
|
||||
if (this.tileSetPropertyMap[index]) {
|
||||
return this.tileSetPropertyMap[index]
|
||||
return this.tileSetPropertyMap[index];
|
||||
}
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the position of the current player (in pixels)
|
||||
* This will trigger events if properties are changing.
|
||||
|
@ -88,8 +105,8 @@ export class GameMap {
|
|||
private getProperties(key: number): Map<string, string | boolean | number> {
|
||||
const properties = new Map<string, string | boolean | number>();
|
||||
|
||||
for (const layer of this.layersIterator) {
|
||||
if (layer.type !== 'tilelayer') {
|
||||
for (const layer of this.flatLayers) {
|
||||
if (layer.type !== "tilelayer") {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -99,7 +116,7 @@ export class GameMap {
|
|||
if (tiles[key] == 0) {
|
||||
continue;
|
||||
}
|
||||
tileIndex = tiles[key]
|
||||
tileIndex = tiles[key];
|
||||
}
|
||||
|
||||
// There is a tile in this layer, let's embed the properties
|
||||
|
@ -113,20 +130,29 @@ export class GameMap {
|
|||
}
|
||||
|
||||
if (tileIndex) {
|
||||
this.tileSetPropertyMap[tileIndex]?.forEach(property => {
|
||||
this.tileSetPropertyMap[tileIndex]?.forEach((property) => {
|
||||
if (property.value) {
|
||||
properties.set(property.name, property.value)
|
||||
properties.set(property.name, property.value);
|
||||
} else if (properties.has(property.name)) {
|
||||
properties.delete(property.name)
|
||||
properties.delete(property.name);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private trigger(propName: string, oldValue: string | number | boolean | undefined, newValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) {
|
||||
public getMap(): ITiledMap {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
private trigger(
|
||||
propName: string,
|
||||
oldValue: string | number | boolean | undefined,
|
||||
newValue: string | number | boolean | undefined,
|
||||
allProps: Map<string, string | boolean | number>
|
||||
) {
|
||||
const callbacksArray = this.callbacks.get(propName);
|
||||
if (callbacksArray !== undefined) {
|
||||
for (const callback of callbacksArray) {
|
||||
|
@ -146,4 +172,18 @@ export class GameMap {
|
|||
}
|
||||
callbacksArray.push(callback);
|
||||
}
|
||||
|
||||
public findLayer(layerName: string): ITiledMapLayer | undefined {
|
||||
return this.flatLayers.find((layer) => layer.name === layerName);
|
||||
}
|
||||
|
||||
public findPhaserLayer(layerName: string): TilemapLayer | undefined {
|
||||
return this.phaserLayers.find((layer) => layer.layer.name === layerName);
|
||||
}
|
||||
|
||||
public addTerrain(terrain: Phaser.Tilemaps.Tileset): void {
|
||||
for (const phaserLayer of this.phaserLayers) {
|
||||
phaserLayer.tileset.push(terrain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,14 @@
|
|||
import type {HasMovedEvent} from "./GameManager";
|
||||
import {MAX_EXTRAPOLATION_TIME} from "../../Enum/EnvironmentVariable";
|
||||
import type {PositionInterface} from "../../Connexion/ConnexionModels";
|
||||
import { MAX_EXTRAPOLATION_TIME } from "../../Enum/EnvironmentVariable";
|
||||
import type { PositionInterface } from "../../Connexion/ConnexionModels";
|
||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||
|
||||
export class PlayerMovement {
|
||||
public constructor(private startPosition: PositionInterface, private startTick: number, private endPosition: HasMovedEvent, private endTick: number) {
|
||||
}
|
||||
public constructor(
|
||||
private startPosition: PositionInterface,
|
||||
private startTick: number,
|
||||
private endPosition: HasPlayerMovedEvent,
|
||||
private endTick: number
|
||||
) {}
|
||||
|
||||
public isOutdated(tick: number): boolean {
|
||||
//console.log(tick, this.endTick, MAX_EXTRAPOLATION_TIME)
|
||||
|
@ -17,21 +21,25 @@ export class PlayerMovement {
|
|||
return tick > this.endTick + MAX_EXTRAPOLATION_TIME;
|
||||
}
|
||||
|
||||
public getPosition(tick: number): HasMovedEvent {
|
||||
public getPosition(tick: number): HasPlayerMovedEvent {
|
||||
// Special case: end position reached and end position is not moving
|
||||
if (tick >= this.endTick && this.endPosition.moving === false) {
|
||||
//console.log('Movement finished ', this.endPosition)
|
||||
return this.endPosition;
|
||||
}
|
||||
|
||||
const x = (this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.x;
|
||||
const y = (this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.y;
|
||||
const x =
|
||||
(this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) +
|
||||
this.startPosition.x;
|
||||
const y =
|
||||
(this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) +
|
||||
this.startPosition.y;
|
||||
//console.log('Computed position ', x, y)
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
direction: this.endPosition.direction,
|
||||
moving: true
|
||||
}
|
||||
moving: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
* This class is in charge of computing the position of all players.
|
||||
* Player movement is delayed by 200ms so position depends on ticks.
|
||||
*/
|
||||
import type {PlayerMovement} from "./PlayerMovement";
|
||||
import type {HasMovedEvent} from "./GameManager";
|
||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||
import type { PlayerMovement } from "./PlayerMovement";
|
||||
|
||||
export class PlayersPositionInterpolator {
|
||||
playerMovements: Map<number, PlayerMovement> = new Map<number, PlayerMovement>();
|
||||
|
||||
updatePlayerPosition(userId: number, playerMovement: PlayerMovement) : void {
|
||||
updatePlayerPosition(userId: number, playerMovement: PlayerMovement): void {
|
||||
this.playerMovements.set(userId, playerMovement);
|
||||
}
|
||||
|
||||
|
@ -16,15 +16,15 @@ export class PlayersPositionInterpolator {
|
|||
this.playerMovements.delete(userId);
|
||||
}
|
||||
|
||||
getUpdatedPositions(tick: number) : Map<number, HasMovedEvent> {
|
||||
const positions = new Map<number, HasMovedEvent>();
|
||||
getUpdatedPositions(tick: number): Map<number, HasPlayerMovedEvent> {
|
||||
const positions = new Map<number, HasPlayerMovedEvent>();
|
||||
this.playerMovements.forEach((playerMovement: PlayerMovement, userId: number) => {
|
||||
if (playerMovement.isOutdated(tick)) {
|
||||
//console.log("outdated")
|
||||
this.playerMovements.delete(userId);
|
||||
}
|
||||
//console.log("moving")
|
||||
positions.set(userId, playerMovement.getPosition(tick))
|
||||
positions.set(userId, playerMovement.getPosition(tick));
|
||||
});
|
||||
return positions;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import type { PositionInterface } from '../../Connexion/ConnexionModels';
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapTileLayer } from '../Map/ITiledMap';
|
||||
import type { GameMap } from './GameMap';
|
||||
import type { PositionInterface } from "../../Connexion/ConnexionModels";
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapTileLayer } from "../Map/ITiledMap";
|
||||
import type { GameMap } from "./GameMap";
|
||||
|
||||
|
||||
const defaultStartLayerName = 'start';
|
||||
const defaultStartLayerName = "start";
|
||||
|
||||
export class StartPositionCalculator {
|
||||
|
||||
public startPosition!: PositionInterface
|
||||
public startPosition!: PositionInterface;
|
||||
|
||||
constructor(
|
||||
private readonly gameMap: GameMap,
|
||||
private readonly mapFile: ITiledMap,
|
||||
private readonly initPosition: PositionInterface | null,
|
||||
private readonly startLayerName: string | null) {
|
||||
public readonly startLayerName: string | null
|
||||
) {
|
||||
this.initStartXAndStartY();
|
||||
}
|
||||
private initStartXAndStartY() {
|
||||
|
@ -32,34 +31,39 @@ export class StartPositionCalculator {
|
|||
}
|
||||
// Still no start position? Something is wrong with the map, we need a "start" layer.
|
||||
if (this.startPosition === undefined) {
|
||||
console.warn('This map is missing a layer named "start" that contains the available default start positions.');
|
||||
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.startPosition = {
|
||||
x: this.mapFile.width * 16,
|
||||
y: this.mapFile.height * 16
|
||||
y: 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
|
||||
*/
|
||||
*
|
||||
* @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
|
||||
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))) {
|
||||
if (
|
||||
(selectedOrDefaultLayer === layer.name || layer.name.endsWith("/" + selectedOrDefaultLayer)) &&
|
||||
layer.type === "tilelayer" &&
|
||||
(selectedOrDefaultLayer === defaultStartLayerName || this.isStartLayer(layer))
|
||||
) {
|
||||
const startPosition = this.startUser(layer, selectedLayer);
|
||||
this.startPosition = {
|
||||
x: startPosition.x + this.mapFile.tilewidth / 2,
|
||||
y: startPosition.y + this.mapFile.tileheight / 2
|
||||
}
|
||||
y: startPosition.y + this.mapFile.tileheight / 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private isStartLayer(layer: ITiledMapLayer): boolean {
|
||||
|
@ -67,14 +71,14 @@ export class StartPositionCalculator {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @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
|
||||
* @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');
|
||||
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) => {
|
||||
|
@ -86,8 +90,11 @@ export class StartPositionCalculator {
|
|||
|
||||
if (selectedLayer && this.gameMap.hasStartTile) {
|
||||
const properties = this.gameMap.getPropertiesForIndex(objectKey);
|
||||
if (!properties.length || !properties.some(property => property.name == "start" && property.value == selectedLayer)) {
|
||||
return
|
||||
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 });
|
||||
|
@ -97,7 +104,7 @@ export class StartPositionCalculator {
|
|||
console.warn('The start layer "' + selectedOrDefaultLayer.name + '" for this map is empty.');
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
// Choose one of the available start positions at random amongst the list of available start positions.
|
||||
|
@ -109,10 +116,12 @@ export class StartPositionCalculator {
|
|||
if (!properties) {
|
||||
return undefined;
|
||||
}
|
||||
const obj = properties.find((property: ITiledMapLayerProperty) => property.name.toLowerCase() === name.toLowerCase());
|
||||
const obj = properties.find(
|
||||
(property: ITiledMapLayerProperty) => property.name.toLowerCase() === name.toLowerCase()
|
||||
);
|
||||
if (obj === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return obj.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* Represents the interface for the Tiled exported data structure (JSON). Used
|
||||
* when loading resources via Resource loader.
|
||||
*/
|
||||
import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
|
||||
|
||||
export interface ITiledMap {
|
||||
width: number;
|
||||
height: number;
|
||||
|
@ -34,7 +36,7 @@ export interface ITiledMap {
|
|||
export interface ITiledMapLayerProperty {
|
||||
name: string;
|
||||
type: string;
|
||||
value: string|boolean|number|undefined;
|
||||
value: string | boolean | number | undefined;
|
||||
}
|
||||
|
||||
/*export interface ITiledMapLayerBooleanProperty {
|
||||
|
@ -46,7 +48,7 @@ export interface ITiledMapLayerProperty {
|
|||
export type ITiledMapLayer = ITiledMapGroupLayer | ITiledMapObjectLayer | ITiledMapTileLayer;
|
||||
|
||||
export interface ITiledMapGroupLayer {
|
||||
id?: number,
|
||||
id?: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
|
@ -62,8 +64,8 @@ export interface ITiledMapGroupLayer {
|
|||
}
|
||||
|
||||
export interface ITiledMapTileLayer {
|
||||
id?: number,
|
||||
data: number[]|string;
|
||||
id?: number;
|
||||
data: number[] | string;
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
|
@ -81,10 +83,11 @@ export interface ITiledMapTileLayer {
|
|||
* Draw order (topdown (default), index)
|
||||
*/
|
||||
draworder?: string;
|
||||
phaserLayer?: TilemapLayer;
|
||||
}
|
||||
|
||||
export interface ITiledMapObjectLayer {
|
||||
id?: number,
|
||||
id?: number;
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
|
@ -114,7 +117,7 @@ export interface ITiledMapObject {
|
|||
gid: number;
|
||||
height: number;
|
||||
name: string;
|
||||
properties: {[key: string]: string};
|
||||
properties: { [key: string]: string };
|
||||
rotation: number;
|
||||
type: string;
|
||||
visible: boolean;
|
||||
|
@ -130,26 +133,26 @@ export interface ITiledMapObject {
|
|||
/**
|
||||
* Polygon points
|
||||
*/
|
||||
polygon: {x: number, y: number}[];
|
||||
polygon: { x: number; y: number }[];
|
||||
|
||||
/**
|
||||
* Polyline points
|
||||
*/
|
||||
polyline: {x: number, y: number}[];
|
||||
polyline: { x: number; y: number }[];
|
||||
|
||||
text?: ITiledText
|
||||
text?: ITiledText;
|
||||
}
|
||||
|
||||
export interface ITiledText {
|
||||
text: string,
|
||||
wrap?: boolean,
|
||||
fontfamily?: string,
|
||||
pixelsize?: number,
|
||||
color?: string,
|
||||
underline?: boolean,
|
||||
italic?: boolean,
|
||||
strikeout?: boolean,
|
||||
halign?: "center"|"right"|"justify"|"left"
|
||||
text: string;
|
||||
wrap?: boolean;
|
||||
fontfamily?: string;
|
||||
pixelsize?: number;
|
||||
color?: string;
|
||||
underline?: boolean;
|
||||
italic?: boolean;
|
||||
strikeout?: boolean;
|
||||
halign?: "center" | "right" | "justify" | "left";
|
||||
}
|
||||
|
||||
export interface ITiledTileSet {
|
||||
|
@ -160,7 +163,7 @@ export interface ITiledTileSet {
|
|||
imagewidth: number;
|
||||
margin: number;
|
||||
name: string;
|
||||
properties: {[key: string]: string};
|
||||
properties: { [key: string]: string };
|
||||
spacing: number;
|
||||
tilecount: number;
|
||||
tileheight: number;
|
||||
|
@ -176,10 +179,10 @@ export interface ITiledTileSet {
|
|||
}
|
||||
|
||||
export interface ITile {
|
||||
id: number,
|
||||
type?: string
|
||||
id: number;
|
||||
type?: string;
|
||||
|
||||
properties?: Array<ITiledMapLayerProperty>
|
||||
properties?: Array<ITiledMapLayerProperty>;
|
||||
}
|
||||
|
||||
export interface ITiledMapTerrain {
|
||||
|
|
21
front/src/Phaser/Map/LayersFlattener.ts
Normal file
21
front/src/Phaser/Map/LayersFlattener.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import type { ITiledMap, ITiledMapLayer } from "./ITiledMap";
|
||||
|
||||
/**
|
||||
* Flatten the grouped layers
|
||||
*/
|
||||
export function flattenGroupLayersMap(map: ITiledMap) {
|
||||
const flatLayers: ITiledMapLayer[] = [];
|
||||
flattenGroupLayers(map.layers, "", flatLayers);
|
||||
return flatLayers;
|
||||
}
|
||||
|
||||
function flattenGroupLayers(layers: ITiledMapLayer[], prefix: string, flatLayers: ITiledMapLayer[]) {
|
||||
for (const layer of layers) {
|
||||
if (layer.type === "group") {
|
||||
flattenGroupLayers(layer.layers, prefix + layer.name + "/", flatLayers);
|
||||
} else {
|
||||
layer.name = prefix + layer.name;
|
||||
flatLayers.push(layer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
import type {ITiledMap, ITiledMapLayer} from "./ITiledMap";
|
||||
|
||||
/**
|
||||
* Iterates over the layers of a map, flattening the grouped layers
|
||||
*/
|
||||
export class LayersIterator implements IterableIterator<ITiledMapLayer> {
|
||||
|
||||
private layers: ITiledMapLayer[] = [];
|
||||
private pointer: number = 0;
|
||||
|
||||
constructor(private map: ITiledMap) {
|
||||
this.initLayersList(map.layers, '');
|
||||
}
|
||||
|
||||
private initLayersList(layers : ITiledMapLayer[], prefix : string) {
|
||||
for (const layer of layers) {
|
||||
if (layer.type === 'group') {
|
||||
this.initLayersList(layer.layers, prefix + layer.name + '/');
|
||||
} else {
|
||||
const layerWithNewName = { ...layer };
|
||||
layerWithNewName.name = prefix+layerWithNewName.name;
|
||||
this.layers.push(layerWithNewName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public next(): IteratorResult<ITiledMapLayer> {
|
||||
if (this.pointer < this.layers.length) {
|
||||
return {
|
||||
done: false,
|
||||
value: this.layers[this.pointer++]
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
done: true,
|
||||
value: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Symbol.iterator](): IterableIterator<ITiledMapLayer> {
|
||||
return new LayersIterator(this.map);
|
||||
}
|
||||
}
|
|
@ -1,24 +1,29 @@
|
|||
import {LoginScene, LoginSceneName} from "../Login/LoginScene";
|
||||
import {SelectCharacterScene, SelectCharacterSceneName} from "../Login/SelectCharacterScene";
|
||||
import {SelectCompanionScene, SelectCompanionSceneName} from "../Login/SelectCompanionScene";
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {gameReportKey, gameReportRessource, ReportMenu} from "./ReportMenu";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {GameConnexionTypes} from "../../Url/UrlManager";
|
||||
import {WarningContainer, warningContainerHtml, warningContainerKey} from "../Components/WarningContainer";
|
||||
import {worldFullWarningStream} from "../../Connexion/WorldFullWarningStream";
|
||||
import {menuIconVisible} from "../../Stores/MenuStore";
|
||||
import {videoConstraintStore} from "../../Stores/MediaStore";
|
||||
import {consoleGlobalMessageManagerVisibleStore} from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import {get} from "svelte/store";
|
||||
import { LoginScene, LoginSceneName } from "../Login/LoginScene";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import { SelectCompanionScene, SelectCompanionSceneName } from "../Login/SelectCompanionScene";
|
||||
import { gameManager } from "../Game/GameManager";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { gameReportKey, gameReportRessource, ReportMenu } from "./ReportMenu";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import { GameConnexionTypes } from "../../Url/UrlManager";
|
||||
import { WarningContainer, warningContainerHtml, warningContainerKey } from "../Components/WarningContainer";
|
||||
import { worldFullWarningStream } from "../../Connexion/WorldFullWarningStream";
|
||||
import { menuIconVisible } from "../../Stores/MenuStore";
|
||||
import { videoConstraintStore } from "../../Stores/MediaStore";
|
||||
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import { iframeListener } from "../../Api/IframeListener";
|
||||
import { Subscription } from "rxjs";
|
||||
import { registerMenuCommandStream } from "../../Api/Events/ui/MenuItemRegisterEvent";
|
||||
import { sendMenuClickedEvent } from "../../Api/iframe/Ui/MenuItem";
|
||||
import { consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
export const MenuSceneName = 'MenuScene';
|
||||
const gameMenuKey = 'gameMenu';
|
||||
const gameMenuIconKey = 'gameMenuIcon';
|
||||
const gameSettingsMenuKey = 'gameSettingsMenu';
|
||||
const gameShare = 'gameShare';
|
||||
export const MenuSceneName = "MenuScene";
|
||||
const gameMenuKey = "gameMenu";
|
||||
const gameMenuIconKey = "gameMenuIcon";
|
||||
const gameSettingsMenuKey = "gameSettingsMenu";
|
||||
const gameShare = "gameShare";
|
||||
|
||||
const closedSideMenuX = -1000;
|
||||
const openedSideMenuX = 0;
|
||||
|
@ -39,19 +44,49 @@ export class MenuScene extends Phaser.Scene {
|
|||
private menuButton!: Phaser.GameObjects.DOMElement;
|
||||
private warningContainer: WarningContainer | null = null;
|
||||
private warningContainerTimeout: NodeJS.Timeout | null = null;
|
||||
|
||||
private subscriptions = new Subscription();
|
||||
constructor() {
|
||||
super({key: MenuSceneName});
|
||||
super({ key: MenuSceneName });
|
||||
|
||||
this.gameQualityValue = localUserStore.getGameQualityValue();
|
||||
this.videoQualityValue = localUserStore.getVideoQualityValue();
|
||||
|
||||
this.subscriptions.add(
|
||||
registerMenuCommandStream.subscribe((menuCommand) => {
|
||||
this.addMenuOption(menuCommand);
|
||||
})
|
||||
);
|
||||
|
||||
this.subscriptions.add(
|
||||
iframeListener.unregisterMenuCommandStream.subscribe((menuCommand) => {
|
||||
this.destroyMenu(menuCommand);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
preload () {
|
||||
this.load.html(gameMenuKey, 'resources/html/gameMenu.html');
|
||||
this.load.html(gameMenuIconKey, 'resources/html/gameMenuIcon.html');
|
||||
this.load.html(gameSettingsMenuKey, 'resources/html/gameQualityMenu.html');
|
||||
this.load.html(gameShare, 'resources/html/gameShare.html');
|
||||
reset() {
|
||||
const addedMenuItems = [...this.menuElement.node.querySelectorAll(".fromApi")];
|
||||
for (let index = addedMenuItems.length - 1; index >= 0; index--) {
|
||||
addedMenuItems[index].remove();
|
||||
}
|
||||
}
|
||||
|
||||
public addMenuOption(menuText: string) {
|
||||
const wrappingSection = document.createElement("section");
|
||||
const escapedHtml = HtmlUtils.escapeHtml(menuText);
|
||||
wrappingSection.innerHTML = `<button class="fromApi" id="${escapedHtml}">${escapedHtml}</button>`;
|
||||
const menuItemContainer = this.menuElement.node.querySelector("#gameMenu main");
|
||||
if (menuItemContainer) {
|
||||
menuItemContainer.querySelector(`#${escapedHtml}.fromApi`)?.remove();
|
||||
menuItemContainer.insertBefore(wrappingSection, menuItemContainer.querySelector("#socialLinks"));
|
||||
}
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.html(gameMenuKey, "resources/html/gameMenu.html");
|
||||
this.load.html(gameMenuIconKey, "resources/html/gameMenuIcon.html");
|
||||
this.load.html(gameSettingsMenuKey, "resources/html/gameQualityMenu.html");
|
||||
this.load.html(gameShare, "resources/html/gameShare.html");
|
||||
this.load.html(gameReportKey, gameReportRessource);
|
||||
this.load.html(warningContainerKey, warningContainerHtml);
|
||||
}
|
||||
|
@ -60,42 +95,46 @@ export class MenuScene extends Phaser.Scene {
|
|||
menuIconVisible.set(true);
|
||||
this.menuElement = this.add.dom(closedSideMenuX, 30).createFromCache(gameMenuKey);
|
||||
this.menuElement.setOrigin(0);
|
||||
MenuScene.revealMenusAfterInit(this.menuElement, 'gameMenu');
|
||||
MenuScene.revealMenusAfterInit(this.menuElement, "gameMenu");
|
||||
|
||||
const middleX = (window.innerWidth / 3) - 298;
|
||||
const middleX = window.innerWidth / 3 - 298;
|
||||
this.gameQualityMenuElement = this.add.dom(middleX, -400).createFromCache(gameSettingsMenuKey);
|
||||
MenuScene.revealMenusAfterInit(this.gameQualityMenuElement, 'gameQuality');
|
||||
|
||||
MenuScene.revealMenusAfterInit(this.gameQualityMenuElement, "gameQuality");
|
||||
|
||||
this.gameShareElement = this.add.dom(middleX, -400).createFromCache(gameShare);
|
||||
MenuScene.revealMenusAfterInit(this.gameShareElement, gameShare);
|
||||
this.gameShareElement.addListener('click');
|
||||
this.gameShareElement.on('click', (event:MouseEvent) => {
|
||||
this.gameShareElement.addListener("click");
|
||||
this.gameShareElement.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'gameShareFormSubmit') {
|
||||
if ((event?.target as HTMLInputElement).id === "gameShareFormSubmit") {
|
||||
this.copyLink();
|
||||
}else if((event?.target as HTMLInputElement).id === 'gameShareFormCancel') {
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameShareFormCancel") {
|
||||
this.closeGameShare();
|
||||
}
|
||||
});
|
||||
|
||||
this.gameReportElement = new ReportMenu(this, connectionManager.getConnexionType === GameConnexionTypes.anonymous);
|
||||
mediaManager.setShowReportModalCallBacks((userId, userName) => {
|
||||
this.closeAll();
|
||||
this.gameReportElement.open(parseInt(userId), userName);
|
||||
this.gameReportElement = new ReportMenu(
|
||||
this,
|
||||
connectionManager.getConnexionType === GameConnexionTypes.anonymous
|
||||
);
|
||||
showReportScreenStore.subscribe((user) => {
|
||||
if (user !== null) {
|
||||
this.closeAll();
|
||||
this.gameReportElement.open(user.userId, user.userName);
|
||||
}
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keyup-TAB', () => {
|
||||
this.input.keyboard.on("keyup-TAB", () => {
|
||||
this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu();
|
||||
});
|
||||
this.menuButton = this.add.dom(0, 0).createFromCache(gameMenuIconKey);
|
||||
this.menuButton.addListener('click');
|
||||
this.menuButton.on('click', () => {
|
||||
this.menuButton.addListener("click");
|
||||
this.menuButton.on("click", () => {
|
||||
this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu();
|
||||
});
|
||||
|
||||
this.menuElement.addListener('click');
|
||||
this.menuElement.on('click', this.onMenuClick.bind(this));
|
||||
this.menuElement.addListener("click");
|
||||
this.menuElement.on("click", this.onMenuClick.bind(this));
|
||||
|
||||
worldFullWarningStream.stream.subscribe(() => this.showWorldCapacityWarning());
|
||||
}
|
||||
|
@ -112,7 +151,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
public revealMenuIcon(): void {
|
||||
//TODO fix me: add try catch because at the same time, 'this.menuButton' variable doesn't exist and there is error on 'getChildByID' function
|
||||
try {
|
||||
(this.menuButton.getChildByID('menuIcon') as HTMLElement).hidden = false;
|
||||
(this.menuButton.getChildByID("menuIcon") as HTMLElement).hidden = false;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
@ -122,22 +161,22 @@ export class MenuScene extends Phaser.Scene {
|
|||
if (this.sideMenuOpened) return;
|
||||
this.closeAll();
|
||||
this.sideMenuOpened = true;
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = 'X';
|
||||
this.menuButton.getChildByID("openMenuButton").innerHTML = "X";
|
||||
const connection = gameManager.getCurrentGameScene(this).connection;
|
||||
if (connection && connection.isAdmin()) {
|
||||
const adminSection = this.menuElement.getChildByID('adminConsoleSection') as HTMLElement;
|
||||
const adminSection = this.menuElement.getChildByID("adminConsoleSection") as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
}
|
||||
//TODO bind with future metadata of card
|
||||
//if (connectionManager.getConnexionType === GameConnexionTypes.anonymous){
|
||||
const adminSection = this.menuElement.getChildByID('socialLinks') as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
const adminSection = this.menuElement.getChildByID("socialLinks") as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
//}
|
||||
this.tweens.add({
|
||||
targets: this.menuElement,
|
||||
x: openedSideMenuX,
|
||||
duration: 500,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -150,23 +189,22 @@ export class MenuScene extends Phaser.Scene {
|
|||
}
|
||||
this.warningContainerTimeout = setTimeout(() => {
|
||||
this.warningContainer?.destroy();
|
||||
this.warningContainer = null
|
||||
this.warningContainerTimeout = null
|
||||
this.warningContainer = null;
|
||||
this.warningContainerTimeout = null;
|
||||
}, 120000);
|
||||
|
||||
}
|
||||
|
||||
private closeSideMenu(): void {
|
||||
if (!this.sideMenuOpened) return;
|
||||
this.sideMenuOpened = false;
|
||||
this.closeAll();
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = `<img src="/static/images/menu.svg">`;
|
||||
this.menuButton.getChildByID("openMenuButton").innerHTML = `<img src="/static/images/menu.svg">`;
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
this.tweens.add({
|
||||
targets: this.menuElement,
|
||||
x: closedSideMenuX,
|
||||
duration: 500,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -180,29 +218,33 @@ export class MenuScene extends Phaser.Scene {
|
|||
|
||||
this.settingsMenuOpened = true;
|
||||
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID('select-game-quality') as HTMLInputElement;
|
||||
gameQualitySelect.value = ''+this.gameQualityValue;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID('select-video-quality') as HTMLInputElement;
|
||||
videoQualitySelect.value = ''+this.videoQualityValue;
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID("select-game-quality") as HTMLInputElement;
|
||||
gameQualitySelect.value = "" + this.gameQualityValue;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID("select-video-quality") as HTMLInputElement;
|
||||
videoQualitySelect.value = "" + this.videoQualityValue;
|
||||
|
||||
this.gameQualityMenuElement.addListener('click');
|
||||
this.gameQualityMenuElement.on('click', (event:MouseEvent) => {
|
||||
this.gameQualityMenuElement.addListener("click");
|
||||
this.gameQualityMenuElement.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if ((event?.target as HTMLInputElement).id === 'gameQualityFormSubmit') {
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID('select-game-quality') as HTMLInputElement;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID('select-video-quality') as HTMLInputElement;
|
||||
if ((event?.target as HTMLInputElement).id === "gameQualityFormSubmit") {
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID(
|
||||
"select-game-quality"
|
||||
) as HTMLInputElement;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID(
|
||||
"select-video-quality"
|
||||
) as HTMLInputElement;
|
||||
this.saveSetting(parseInt(gameQualitySelect.value), parseInt(videoQualitySelect.value));
|
||||
} else if((event?.target as HTMLInputElement).id === 'gameQualityFormCancel') {
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameQualityFormCancel") {
|
||||
this.closeGameQualityMenu();
|
||||
}
|
||||
});
|
||||
|
||||
let middleY = this.scale.height / 2 - 392/2;
|
||||
if(middleY < 0){
|
||||
let middleY = this.scale.height / 2 - 392 / 2;
|
||||
if (middleY < 0) {
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = this.scale.width / 2 - 457/2;
|
||||
if(middleX < 0){
|
||||
let middleX = this.scale.width / 2 - 457 / 2;
|
||||
if (middleX < 0) {
|
||||
middleX = 0;
|
||||
}
|
||||
this.tweens.add({
|
||||
|
@ -210,7 +252,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
y: middleY,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -218,17 +260,16 @@ export class MenuScene extends Phaser.Scene {
|
|||
if (!this.settingsMenuOpened) return;
|
||||
this.settingsMenuOpened = false;
|
||||
|
||||
this.gameQualityMenuElement.removeListener('click');
|
||||
this.gameQualityMenuElement.removeListener("click");
|
||||
this.tweens.add({
|
||||
targets: this.gameQualityMenuElement,
|
||||
y: -400,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private openGameShare(): void{
|
||||
private openGameShare(): void {
|
||||
if (this.gameShareOpened) {
|
||||
this.closeGameShare();
|
||||
return;
|
||||
|
@ -236,17 +277,17 @@ export class MenuScene extends Phaser.Scene {
|
|||
//close all
|
||||
this.closeAll();
|
||||
|
||||
const gameShareLink = this.gameShareElement.getChildByID('gameShareLink') as HTMLInputElement;
|
||||
const gameShareLink = this.gameShareElement.getChildByID("gameShareLink") as HTMLInputElement;
|
||||
gameShareLink.value = location.toString();
|
||||
|
||||
this.gameShareOpened = true;
|
||||
|
||||
let middleY = this.scale.height / 2 - 85;
|
||||
if(middleY < 0){
|
||||
if (middleY < 0) {
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = this.scale.width / 2 - 200;
|
||||
if(middleX < 0){
|
||||
if (middleX < 0) {
|
||||
middleX = 0;
|
||||
}
|
||||
this.tweens.add({
|
||||
|
@ -254,58 +295,64 @@ export class MenuScene extends Phaser.Scene {
|
|||
y: middleY,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private closeGameShare(): void{
|
||||
const gameShareInfo = this.gameShareElement.getChildByID('gameShareInfo') as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = '';
|
||||
gameShareInfo.style.display = 'none';
|
||||
private closeGameShare(): void {
|
||||
const gameShareInfo = this.gameShareElement.getChildByID("gameShareInfo") as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = "";
|
||||
gameShareInfo.style.display = "none";
|
||||
this.gameShareOpened = false;
|
||||
this.tweens.add({
|
||||
targets: this.gameShareElement,
|
||||
y: -400,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private onMenuClick(event:MouseEvent) {
|
||||
if((event?.target as HTMLInputElement).classList.contains('not-button')){
|
||||
private onMenuClick(event: MouseEvent) {
|
||||
const htmlMenuItem = event?.target as HTMLInputElement;
|
||||
if (htmlMenuItem.classList.contains("not-button")) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
if (htmlMenuItem.classList.contains("fromApi")) {
|
||||
sendMenuClickedEvent(htmlMenuItem.id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((event?.target as HTMLInputElement).id) {
|
||||
case 'changeNameButton':
|
||||
case "changeNameButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(this, LoginSceneName, new LoginScene());
|
||||
break;
|
||||
case 'sparkButton':
|
||||
case "sparkButton":
|
||||
this.gotToCreateMapPage();
|
||||
break;
|
||||
case 'changeSkinButton':
|
||||
case "changeSkinButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(this, SelectCharacterSceneName, new SelectCharacterScene());
|
||||
break;
|
||||
case 'changeCompanionButton':
|
||||
case "changeCompanionButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(this, SelectCompanionSceneName, new SelectCompanionScene());
|
||||
break;
|
||||
case 'closeButton':
|
||||
case "closeButton":
|
||||
this.closeSideMenu();
|
||||
break;
|
||||
case 'shareButton':
|
||||
case "shareButton":
|
||||
this.openGameShare();
|
||||
break;
|
||||
case 'editGameSettingsButton':
|
||||
case "editGameSettingsButton":
|
||||
this.openGameSettingsMenu();
|
||||
break;
|
||||
case 'toggleFullscreen':
|
||||
case "toggleFullscreen":
|
||||
this.toggleFullscreen();
|
||||
break;
|
||||
case 'adminConsoleButton':
|
||||
case "adminConsoleButton":
|
||||
if (get(consoleGlobalMessageManagerVisibleStore)) {
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
} else {
|
||||
|
@ -317,12 +364,12 @@ export class MenuScene extends Phaser.Scene {
|
|||
|
||||
private async copyLink() {
|
||||
await navigator.clipboard.writeText(location.toString());
|
||||
const gameShareInfo = this.gameShareElement.getChildByID('gameShareInfo') as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = 'Link copied, you can share it now!';
|
||||
gameShareInfo.style.display = 'block';
|
||||
const gameShareInfo = this.gameShareElement.getChildByID("gameShareInfo") as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = "Link copied, you can share it now!";
|
||||
gameShareInfo.style.display = "block";
|
||||
}
|
||||
|
||||
private saveSetting(valueGame: number, valueVideo: number){
|
||||
private saveSetting(valueGame: number, valueVideo: number) {
|
||||
if (valueGame !== this.gameQualityValue) {
|
||||
this.gameQualityValue = valueGame;
|
||||
localUserStore.setGameQualityValue(valueGame);
|
||||
|
@ -339,27 +386,31 @@ export class MenuScene extends Phaser.Scene {
|
|||
private gotToCreateMapPage() {
|
||||
//const sparkHost = 'https://'+window.location.host.replace('play.', '')+'/choose-map.html';
|
||||
//TODO fix me: this button can to send us on WorkAdventure BO.
|
||||
const sparkHost = 'https://workadventu.re/getting-started';
|
||||
window.open(sparkHost, '_blank');
|
||||
const sparkHost = "https://workadventu.re/getting-started";
|
||||
window.open(sparkHost, "_blank");
|
||||
}
|
||||
|
||||
private closeAll(){
|
||||
private closeAll() {
|
||||
this.closeGameQualityMenu();
|
||||
this.closeGameShare();
|
||||
this.gameReportElement.close();
|
||||
}
|
||||
|
||||
private toggleFullscreen() {
|
||||
const body = document.querySelector('body')
|
||||
const body = document.querySelector("body");
|
||||
if (body) {
|
||||
if (document.fullscreenElement ?? document.fullscreen) {
|
||||
document.exitFullscreen()
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
body.requestFullscreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public destroyMenu(menu: string) {
|
||||
this.menuElement.getChildByID(menu).remove();
|
||||
}
|
||||
|
||||
public isDirty(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue