solved conflict with develop
This commit is contained in:
commit
fe27169745
78 changed files with 5321 additions and 985 deletions
|
@ -2,7 +2,6 @@ import {HtmlUtils} from "../WebRtc/HtmlUtils";
|
|||
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||
import {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
|
||||
import {ADMIN_URL} from "../Enum/EnvironmentVariable";
|
||||
import {AdminMessageEventTypes} from "../Connexion/AdminMessagesService";
|
||||
|
||||
export const CLASS_CONSOLE_MESSAGE = 'main-console';
|
||||
|
@ -162,42 +161,46 @@ export class ConsoleGlobalMessageManager {
|
|||
this.divMessageConsole.appendChild(section);
|
||||
|
||||
(async () => {
|
||||
// Start loading CSS
|
||||
const cssPromise = ConsoleGlobalMessageManager.loadCss();
|
||||
// Import quill
|
||||
const Quill:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
// Wait for CSS to be loaded
|
||||
await cssPromise;
|
||||
try{
|
||||
// Start loading CSS
|
||||
const cssPromise = ConsoleGlobalMessageManager.loadCss();
|
||||
// Import quill
|
||||
const {default: Quill}:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
// Wait for CSS to be loaded
|
||||
await cssPromise;
|
||||
|
||||
const toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
const toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
|
||||
[{'header': 1}, {'header': 2}], // custom button values
|
||||
[{'list': 'ordered'}, {'list': 'bullet'}],
|
||||
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
|
||||
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
|
||||
[{'direction': 'rtl'}], // text direction
|
||||
[{'header': 1}, {'header': 2}], // custom button values
|
||||
[{'list': 'ordered'}, {'list': 'bullet'}],
|
||||
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
|
||||
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
|
||||
[{'direction': 'rtl'}], // text direction
|
||||
|
||||
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
|
||||
[{'header': [1, 2, 3, 4, 5, 6, false]}],
|
||||
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
|
||||
[{'header': [1, 2, 3, 4, 5, 6, false]}],
|
||||
|
||||
[{'color': []}, {'background': []}], // dropdown with defaults from theme
|
||||
[{'font': []}],
|
||||
[{'align': []}],
|
||||
[{'color': []}, {'background': []}], // dropdown with defaults from theme
|
||||
[{'font': []}],
|
||||
[{'align': []}],
|
||||
|
||||
['clean'],
|
||||
['clean'],
|
||||
|
||||
['link', 'image', 'video']
|
||||
// remove formatting button
|
||||
];
|
||||
['link', 'image', 'video']
|
||||
// remove formatting button
|
||||
];
|
||||
|
||||
new Quill(`#${INPUT_CONSOLE_MESSAGE}`, {
|
||||
theme: 'snow',
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
});
|
||||
new Quill(`#${INPUT_CONSOLE_MESSAGE}`, {
|
||||
theme: 'snow',
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
});
|
||||
}catch(err){
|
||||
console.error(err);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ export enum AdminMessageEventTypes {
|
|||
admin = 'message',
|
||||
audio = 'audio',
|
||||
ban = 'ban',
|
||||
banned = 'banned',
|
||||
}
|
||||
|
||||
interface AdminMessageEvent {
|
||||
|
|
|
@ -188,7 +188,7 @@ export class RoomConnection implements RoomConnection {
|
|||
} else if (message.hasSendusermessage()) {
|
||||
adminMessagesService.onSendusermessage(message.getSendusermessage() as SendUserMessage);
|
||||
} else if (message.hasBanusermessage()) {
|
||||
adminMessagesService.onSendusermessage(message.getSendusermessage() as BanUserMessage);
|
||||
adminMessagesService.onSendusermessage(message.getBanusermessage() as BanUserMessage);
|
||||
} else if (message.hasWorldfullwarningmessage()) {
|
||||
worldFullWarningStream.onMessage();
|
||||
} else if (message.hasRefreshroommessage()) {
|
||||
|
|
|
@ -17,6 +17,8 @@ const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new
|
|||
export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || '') || 8;
|
||||
export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || '4');
|
||||
|
||||
export const isMobile = ():boolean => ( ( window.innerWidth <= 800 ) || ( window.innerHeight <= 600 ) );
|
||||
|
||||
export {
|
||||
DEBUG_MODE,
|
||||
START_ROOM_URL,
|
||||
|
|
35
front/src/Phaser/Components/MobileJoystick.ts
Normal file
35
front/src/Phaser/Components/MobileJoystick.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import VirtualJoystick from 'phaser3-rex-plugins/plugins/virtualjoystick.js';
|
||||
|
||||
const outOfScreenX = -1000;
|
||||
const outOfScreenY = -1000;
|
||||
|
||||
|
||||
//the assets were found here: https://hannemann.itch.io/virtual-joystick-pack-free
|
||||
export const joystickBaseKey = 'joystickBase';
|
||||
export const joystickBaseImg = 'resources/objects/joystickSplitted.png';
|
||||
export const joystickThumbKey = 'joystickThumb';
|
||||
export const joystickThumbImg = 'resources/objects/smallHandleFilledGrey.png';
|
||||
|
||||
export class MobileJoystick extends VirtualJoystick {
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
super(scene, {
|
||||
x: outOfScreenX,
|
||||
y: outOfScreenY,
|
||||
radius: 20,
|
||||
base: scene.add.image(0, 0, joystickBaseKey).setDisplaySize(60, 60).setDepth(99999),
|
||||
thumb: scene.add.image(0, 0, joystickThumbKey).setDisplaySize(30, 30).setDepth(99999),
|
||||
enable: true,
|
||||
dir: "8dir",
|
||||
});
|
||||
|
||||
this.scene.input.on('pointerdown', (pointer: { x: number; y: number; }) => {
|
||||
this.x = pointer.x;
|
||||
this.y = pointer.y;
|
||||
});
|
||||
this.scene.input.on('pointerup', () => {
|
||||
this.x = outOfScreenX;
|
||||
this.y = outOfScreenY;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ export class GameManager {
|
|||
public async init(scenePlugin: Phaser.Scenes.ScenePlugin): Promise<string> {
|
||||
this.startRoom = await connectionManager.initGameConnexion();
|
||||
await this.loadMap(this.startRoom, scenePlugin);
|
||||
|
||||
|
||||
if (!this.playerName) {
|
||||
return LoginSceneName;
|
||||
} else if (!this.characterLayers || !this.characterLayers.length) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {ITiledMap} from "../Map/ITiledMap";
|
||||
import {ITiledMap, ITiledMapLayer} from "../Map/ITiledMap";
|
||||
import {LayersIterator} from "../Map/LayersIterator";
|
||||
|
||||
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
|
||||
|
||||
|
@ -10,8 +11,10 @@ export class GameMap {
|
|||
private key: number|undefined;
|
||||
private lastProperties = new Map<string, string|boolean|number>();
|
||||
private callbacks = new Map<string, Array<PropertyChangeCallback>>();
|
||||
public readonly layersIterator: LayersIterator;
|
||||
|
||||
public constructor(private map: ITiledMap) {
|
||||
this.layersIterator = new LayersIterator(map);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,7 +58,7 @@ 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.map.layers) {
|
||||
for (const layer of this.layersIterator) {
|
||||
if (layer.type !== 'tilelayer') {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
ITiledMapLayerProperty,
|
||||
ITiledMapObject,
|
||||
ITiledText,
|
||||
ITiledMapTileLayer,
|
||||
ITiledTileSet
|
||||
} from "../Map/ITiledMap";
|
||||
import {AddPlayerInterface} from "./AddPlayerInterface";
|
||||
|
@ -65,10 +66,6 @@ import {Room} from "../../Connexion/Room";
|
|||
import {jitsiFactory} from "../../WebRtc/JitsiFactory";
|
||||
import {urlManager} from "../../Url/UrlManager";
|
||||
import {audioManager} from "../../WebRtc/AudioManager";
|
||||
import {IVirtualJoystick} from "../../types";
|
||||
const {
|
||||
default: VirtualJoystick,
|
||||
} = require("phaser3-rex-plugins/plugins/virtualjoystick.js");
|
||||
import {PresentationModeIcon} from "../Components/PresentationModeIcon";
|
||||
import {ChatModeIcon} from "../Components/ChatModeIcon";
|
||||
import {OpenChatIcon, openChatIconName} from "../Components/OpenChatIcon";
|
||||
|
@ -89,6 +86,9 @@ import {Subscription} from "rxjs";
|
|||
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
|
||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import {TextUtils} from "../Components/TextUtils";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey} from "../Components/MobileJoystick";
|
||||
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface|null,
|
||||
|
@ -144,7 +144,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
pendingEvents: Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface> = new Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface>();
|
||||
private initPosition: PositionInterface|null = null;
|
||||
private playersPositionInterpolator = new PlayersPositionInterpolator();
|
||||
public connection!: RoomConnection;
|
||||
public connection: RoomConnection|undefined;
|
||||
private simplePeer!: SimplePeer;
|
||||
private GlobalMessageManager!: GlobalMessageManager;
|
||||
public ConsoleGlobalMessageManager!: ConsoleGlobalMessageManager;
|
||||
|
@ -153,7 +153,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
// A promise that will resolve when the "create" method is called (signaling loading is ended)
|
||||
private createPromise: Promise<void>;
|
||||
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
|
||||
|
||||
private iframeSubscriptionList! : Array<Subscription>;
|
||||
MapUrlFile: string;
|
||||
RoomId: string;
|
||||
instance: string;
|
||||
|
@ -183,7 +183,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
private messageSubscription: Subscription|null = null;
|
||||
private popUpElements : Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
||||
private originalMapUrl: string|undefined;
|
||||
public virtualJoystick!: IVirtualJoystick;
|
||||
|
||||
constructor(private room: Room, MapUrlFile: string, customKey?: string|undefined) {
|
||||
super({
|
||||
|
@ -207,6 +206,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
|
||||
//hook preload scene
|
||||
preload(): void {
|
||||
addLoader(this);
|
||||
const localUser = localUserStore.getLocalUser();
|
||||
const textures = localUser?.textures;
|
||||
if (textures) {
|
||||
|
@ -216,6 +216,10 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
}
|
||||
|
||||
this.load.image(openChatIconName, 'resources/objects/talk.png');
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
this.load.image(joystickBaseKey, joystickBaseImg);
|
||||
this.load.image(joystickThumbKey, joystickThumbImg);
|
||||
}
|
||||
this.load.on(FILE_LOAD_ERROR, (file: {src: string}) => {
|
||||
// If we happen to be in HTTP and we are trying to load a URL in HTTPS only... (this happens only in dev environments)
|
||||
if (window.location.protocol === 'http:' && file.src === this.MapUrlFile && file.src.startsWith('http:') && this.originalMapUrl === undefined) {
|
||||
|
@ -262,8 +266,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
|
||||
this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', {frameWidth: 32, frameHeight: 32});
|
||||
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
|
||||
addLoader(this);
|
||||
}
|
||||
|
||||
// FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving.
|
||||
|
@ -366,6 +368,10 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
urlManager.pushRoomIdToUrl(this.room);
|
||||
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
this.messageSubscription = worldFullMessageStream.stream.subscribe((message) => this.showWorldFullError())
|
||||
|
||||
const playerName = gameManager.getPlayerName();
|
||||
|
@ -389,8 +395,9 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
|
||||
//add layer on map
|
||||
this.Layers = new Array<Phaser.Tilemaps.StaticTilemapLayer>();
|
||||
|
||||
let depth = -2;
|
||||
for (const layer of this.mapFile.layers) {
|
||||
for (const layer of this.gameMap.layersIterator) {
|
||||
if (layer.type === 'tilelayer') {
|
||||
this.addLayer(this.Map.createStaticLayer(layer.name, this.Terrains, 0, 0).setDepth(depth));
|
||||
|
||||
|
@ -415,7 +422,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
}
|
||||
}
|
||||
if (depth === -2) {
|
||||
throw new Error('Your map MUST contain a layer of type "objectgroup" whose name is "floorLayer" that represents the layer characters are drawn at.');
|
||||
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();
|
||||
|
@ -426,26 +433,10 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
//initialise list of other player
|
||||
this.MapPlayers = this.physics.add.group({immovable: true});
|
||||
|
||||
this.virtualJoystick = new VirtualJoystick(this, {
|
||||
x: this.game.renderer.width / 2,
|
||||
y: this.game.renderer.height / 2,
|
||||
radius: 20,
|
||||
base: this.add.circle(0, 0, 20),
|
||||
thumb: this.add.circle(0, 0, 10),
|
||||
enable: true,
|
||||
dir: "8dir",
|
||||
});
|
||||
this.virtualJoystick.visible = true;
|
||||
|
||||
//create input to move
|
||||
mediaManager.setUserInputManager(this.userInputManager);
|
||||
this.userInputManager = new UserInputManager(this, this.virtualJoystick);
|
||||
|
||||
// Listener event to reposition virtual joystick
|
||||
// whatever place you click in game area
|
||||
this.input.on('pointerdown', (pointer: { x: number; y: number; }) => {
|
||||
this.virtualJoystick.x = pointer.x;
|
||||
this.virtualJoystick.y = pointer.y;
|
||||
});
|
||||
this.userInputManager = new UserInputManager(this);
|
||||
|
||||
if (localUserStore.getFullscreen()) {
|
||||
document.querySelector('body')?.requestFullscreen();
|
||||
|
@ -738,7 +729,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
if (JITSI_PRIVATE_MODE && !jitsiUrl) {
|
||||
const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined;
|
||||
|
||||
this.connection.emitQueryJitsiJwtMessage(roomName, adminTag);
|
||||
this.connection?.emitQueryJitsiJwtMessage(roomName, adminTag);
|
||||
} else {
|
||||
this.startJitsi(roomName, undefined);
|
||||
}
|
||||
|
@ -761,9 +752,9 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
});
|
||||
this.gameMap.onPropertyChange('silent', (newValue, oldValue) => {
|
||||
if (newValue === undefined || newValue === false || newValue === '') {
|
||||
this.connection.setSilent(false);
|
||||
this.connection?.setSilent(false);
|
||||
} else {
|
||||
this.connection.setSilent(true);
|
||||
this.connection?.setSilent(true);
|
||||
}
|
||||
});
|
||||
this.gameMap.onPropertyChange('playAudio', (newValue, oldValue, allProps) => {
|
||||
|
@ -787,7 +778,8 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
}
|
||||
|
||||
private listenToIframeEvents(): void {
|
||||
iframeListener.openPopupStream.subscribe((openPopupEvent) => {
|
||||
this.iframeSubscriptionList = [];
|
||||
this.iframeSubscriptionList.push(iframeListener.openPopupStream.subscribe((openPopupEvent) => {
|
||||
|
||||
let objectLayerSquare : ITiledMapObject;
|
||||
const targetObjectData = this.getObjectLayerData(openPopupEvent.targetObject);
|
||||
|
@ -831,7 +823,6 @@ ${escapedMessage}
|
|||
}
|
||||
id++;
|
||||
}
|
||||
|
||||
this.tweens.add({
|
||||
targets : domElement ,
|
||||
scale : 1,
|
||||
|
@ -840,9 +831,9 @@ ${escapedMessage}
|
|||
});
|
||||
|
||||
this.popUpElements.set(openPopupEvent.popupId, domElement);
|
||||
});
|
||||
}));
|
||||
|
||||
iframeListener.closePopupStream.subscribe((closePopupEvent) => {
|
||||
this.iframeSubscriptionList.push(iframeListener.closePopupStream.subscribe((closePopupEvent) => {
|
||||
const popUpElement = this.popUpElements.get(closePopupEvent.popupId);
|
||||
if (popUpElement === undefined) {
|
||||
console.error('Could not close popup with ID ', closePopupEvent.popupId,'. Maybe it has already been closed?');
|
||||
|
@ -858,23 +849,25 @@ ${escapedMessage}
|
|||
this.popUpElements.delete(closePopupEvent.popupId);
|
||||
},
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
iframeListener.disablePlayerControlStream.subscribe(()=>{
|
||||
this.iframeSubscriptionList.push(iframeListener.disablePlayerControlStream.subscribe(()=>{
|
||||
this.userInputManager.disableControls();
|
||||
})
|
||||
iframeListener.enablePlayerControlStream.subscribe(()=>{
|
||||
}));
|
||||
|
||||
this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(()=>{
|
||||
this.userInputManager.restoreControls();
|
||||
})
|
||||
}));
|
||||
let scriptedBubbleSprite : Sprite;
|
||||
iframeListener.displayBubbleStream.subscribe(()=>{
|
||||
this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{
|
||||
scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white');
|
||||
scriptedBubbleSprite.setDisplayOrigin(48, 48);
|
||||
this.add.existing(scriptedBubbleSprite);
|
||||
})
|
||||
iframeListener.removeBubbleStream.subscribe(()=>{
|
||||
}));
|
||||
|
||||
this.iframeSubscriptionList.push(iframeListener.removeBubbleStream.subscribe(()=>{
|
||||
scriptedBubbleSprite.destroy();
|
||||
})
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
|
@ -919,6 +912,10 @@ ${escapedMessage}
|
|||
this.simplePeer.closeAllConnections();
|
||||
this.simplePeer?.unregister();
|
||||
this.messageSubscription?.unsubscribe();
|
||||
|
||||
for(const iframeEvents of this.iframeSubscriptionList){
|
||||
iframeEvents.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private removeAllRemotePlayers(): void {
|
||||
|
@ -976,13 +973,14 @@ ${escapedMessage}
|
|||
}
|
||||
|
||||
private initPositionFromLayerName(layerName: string) {
|
||||
for (const layer of this.mapFile.layers) {
|
||||
if (layerName === layer.name && layer.type === 'tilelayer' && (layerName === defaultStartLayerName || this.isStartLayer(layer))) {
|
||||
for (const layer of this.gameMap.layersIterator) {
|
||||
if ((layerName === layer.name || layer.name.endsWith('/'+layerName)) && layer.type === 'tilelayer' && (layerName === defaultStartLayerName || this.isStartLayer(layer))) {
|
||||
const startPosition = this.startUser(layer);
|
||||
this.startX = startPosition.x + this.mapFile.tilewidth/2;
|
||||
this.startY = startPosition.y + this.mapFile.tileheight/2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private getExitUrl(layer: ITiledMapLayer): string|undefined {
|
||||
|
@ -1005,7 +1003,7 @@ ${escapedMessage}
|
|||
}
|
||||
|
||||
private getProperty(layer: ITiledMapLayer|ITiledMap, name: string): string|boolean|number|undefined {
|
||||
const properties: ITiledMapLayerProperty[] = layer.properties;
|
||||
const properties: ITiledMapLayerProperty[]|undefined = layer.properties;
|
||||
if (!properties) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -1017,7 +1015,7 @@ ${escapedMessage}
|
|||
}
|
||||
|
||||
private getProperties(layer: ITiledMapLayer|ITiledMap, name: string): (string|number|boolean|undefined)[] {
|
||||
const properties: ITiledMapLayerProperty[] = layer.properties;
|
||||
const properties: ITiledMapLayerProperty[]|undefined = layer.properties;
|
||||
if (!properties) {
|
||||
return [];
|
||||
}
|
||||
|
@ -1031,7 +1029,7 @@ ${escapedMessage}
|
|||
await gameManager.loadMap(room, this.scene);
|
||||
}
|
||||
|
||||
private startUser(layer: ITiledMapLayer): PositionInterface {
|
||||
private startUser(layer: ITiledMapTileLayer): PositionInterface {
|
||||
const tiles = layer.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');
|
||||
|
@ -1187,7 +1185,7 @@ ${escapedMessage}
|
|||
this.lastMoveEventSent = event;
|
||||
this.lastSentTick = this.currentTick;
|
||||
const camera = this.cameras.main;
|
||||
this.connection.sharePosition(event.x, event.y, event.direction, event.moving, {
|
||||
this.connection?.sharePosition(event.x, event.y, event.direction, event.moving, {
|
||||
left: camera.scrollX,
|
||||
top: camera.scrollY,
|
||||
right: camera.scrollX + camera.width,
|
||||
|
@ -1253,7 +1251,7 @@ ${escapedMessage}
|
|||
* Put all the players on the map on map load.
|
||||
*/
|
||||
private doInitUsersPosition(usersPosition: MessageUserPositionInterface[]): void {
|
||||
const currentPlayerId = this.connection.getUserId();
|
||||
const currentPlayerId = this.connection?.getUserId();
|
||||
this.removeAllRemotePlayers();
|
||||
// load map
|
||||
usersPosition.forEach((userPosition : MessageUserPositionInterface) => {
|
||||
|
@ -1397,7 +1395,7 @@ ${escapedMessage}
|
|||
* Sends to the server an event emitted by one of the ActionableItems.
|
||||
*/
|
||||
emitActionableEvent(itemId: number, eventName: string, state: unknown, parameters: unknown) {
|
||||
this.connection.emitActionableEvent(itemId, eventName, state, parameters);
|
||||
this.connection?.emitActionableEvent(itemId, eventName, state, parameters);
|
||||
}
|
||||
|
||||
public onResize(): void {
|
||||
|
@ -1405,7 +1403,7 @@ ${escapedMessage}
|
|||
|
||||
// Send new viewport to server
|
||||
const camera = this.cameras.main;
|
||||
this.connection.setViewport({
|
||||
this.connection?.setViewport({
|
||||
left: camera.scrollX,
|
||||
top: camera.scrollY,
|
||||
right: camera.scrollX + camera.width,
|
||||
|
@ -1461,7 +1459,7 @@ ${escapedMessage}
|
|||
const jitsiUrl = allProps.get("jitsiUrl") as string|undefined;
|
||||
|
||||
jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl);
|
||||
this.connection.setSilent(true);
|
||||
this.connection?.setSilent(true);
|
||||
mediaManager.hideGameOverlay();
|
||||
|
||||
//permit to stop jitsi when user close iframe
|
||||
|
|
|
@ -1,54 +1,33 @@
|
|||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {loadAllLayers, loadCustomTexture} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import {loadAllLayers} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
import Container = Phaser.GameObjects.Container;
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {addLoader} from "../Components/Loader";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import { SelectCharacterSceneName } from "./SelectCharacterScene";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const CustomizeSceneName = "CustomizeScene";
|
||||
|
||||
enum CustomizeTextures{
|
||||
icon = "icon",
|
||||
arrowRight = "arrow_right",
|
||||
mainFont = "main_font",
|
||||
arrowUp = "arrow_up",
|
||||
}
|
||||
export const CustomizeSceneKey = "CustomizeScene";
|
||||
const customizeSceneKey = 'customizeScene';
|
||||
|
||||
export class CustomizeScene extends AbstractCharacterScene {
|
||||
|
||||
private textField!: TextField;
|
||||
private enterField!: TextField;
|
||||
|
||||
private arrowRight!: Image;
|
||||
private arrowLeft!: Image;
|
||||
|
||||
private arrowDown!: Image;
|
||||
private arrowUp!: Image;
|
||||
|
||||
private Rectangle!: Rectangle;
|
||||
|
||||
private mobileTapUP!: Rectangle;
|
||||
private mobileTapDOWN!: Rectangle;
|
||||
private mobileTapLEFT!: Rectangle;
|
||||
private mobileTapRIGHT!: Rectangle;
|
||||
|
||||
private mobileTapENTER!: Rectangle;
|
||||
|
||||
private logo!: Image;
|
||||
|
||||
private selectedLayers: number[] = [0];
|
||||
private containersRow: Container[][] = [];
|
||||
private activeRow:number = 0;
|
||||
private layers: BodyResourceDescriptionInterface[][] = [];
|
||||
|
||||
private customizeSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
key: CustomizeSceneName
|
||||
|
@ -58,6 +37,8 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
preload() {
|
||||
addLoader(this);
|
||||
|
||||
this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html');
|
||||
|
||||
this.layers = loadAllLayers(this.load);
|
||||
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||
|
@ -67,106 +48,42 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
||||
});
|
||||
});
|
||||
|
||||
this.load.image(CustomizeTextures.arrowRight, "resources/objects/arrow_right.png");
|
||||
this.load.image(CustomizeTextures.icon, "resources/logos/tcm_full.png");
|
||||
this.load.image(CustomizeTextures.arrowUp, "resources/objects/arrow_up.png");
|
||||
this.load.bitmapFont(CustomizeTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
}
|
||||
|
||||
create() {
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 30, 'Customize your own Avatar!');
|
||||
const middleX = this.getMiddleX();
|
||||
this.customizeSceneElement = this.add.dom(middleX, 0).createFromCache(customizeSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.customizeSceneElement, customizeSceneKey);
|
||||
|
||||
this.enterField = new TextField(this, this.game.renderer.width / 2, 60, 'Start the game by pressing ENTER\n\n or touching the center rectangle');
|
||||
this.customizeSceneElement.addListener('click');
|
||||
this.customizeSceneElement.on('click', (event:MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'customizeSceneButtonLeft') {
|
||||
this.moveCursorHorizontally(-1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonRight') {
|
||||
this.moveCursorHorizontally(1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonDown') {
|
||||
this.moveCursorVertically(1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonUp') {
|
||||
this.moveCursorVertically(-1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneFormBack') {
|
||||
if(this.activeRow > 0){
|
||||
this.moveCursorVertically(-1);
|
||||
}else{
|
||||
this.backToPreviousScene();
|
||||
}
|
||||
}else if((event?.target as HTMLButtonElement).id === 'customizeSceneFormSubmit') {
|
||||
if(this.activeRow < 5){
|
||||
this.moveCursorVertically(1);
|
||||
}else{
|
||||
this.nextSceneToCamera();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, CustomizeTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
|
||||
this.arrowRight = new Image(this, this.game.renderer.width*0.9, this.game.renderer.height/2, CustomizeTextures.arrowRight);
|
||||
this.add.existing(this.arrowRight);
|
||||
this.mobileTapRIGHT = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width*0.9,
|
||||
this.game.renderer.height/2,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorHorizontally(1);
|
||||
});
|
||||
|
||||
this.arrowLeft = new Image(this, this.game.renderer.width/9, this.game.renderer.height/2, CustomizeTextures.arrowRight);
|
||||
this.arrowLeft.flipX = true;
|
||||
this.add.existing(this.arrowLeft);
|
||||
this.mobileTapLEFT = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width/9,
|
||||
this.game.renderer.height/2,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorHorizontally(-1);
|
||||
});
|
||||
|
||||
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 2, 32, 33)
|
||||
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 3, 32, 33)
|
||||
this.Rectangle.setStrokeStyle(2, 0xFFFFFF);
|
||||
this.add.existing(this.Rectangle);
|
||||
this.mobileTapENTER = this.add
|
||||
.rectangle(
|
||||
this.cameras.main.worldView.x + this.cameras.main.width / 2,
|
||||
this.cameras.main.worldView.y + this.cameras.main.height / 2,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
const layers: string[] = [];
|
||||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
gameManager.setCharacterLayers(layers);
|
||||
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
});
|
||||
|
||||
this.arrowDown = new Image(this, this.game.renderer.width - 30, 100, CustomizeTextures.arrowUp);
|
||||
this.arrowDown.flipY = true;
|
||||
this.add.existing(this.arrowDown);
|
||||
this.mobileTapDOWN = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width - 30,
|
||||
100,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorVertically(1);
|
||||
});
|
||||
|
||||
this.arrowUp = new Image(this, this.game.renderer.width - 30, 60, CustomizeTextures.arrowUp);
|
||||
this.add.existing(this.arrowUp);
|
||||
this.mobileTapUP = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width - 30,
|
||||
60,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorVertically(-1);
|
||||
});
|
||||
|
||||
this.createCustomizeLayer(0, 0, 0);
|
||||
this.createCustomizeLayer(0, 0, 1);
|
||||
|
@ -177,22 +94,10 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
|
||||
this.moveLayers();
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
const layers: string[] = [];
|
||||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!areCharacterLayersValid(layers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gameManager.setCharacterLayers(layers);
|
||||
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
this.nextSceneToCamera();
|
||||
});
|
||||
this.input.keyboard.on('keyup-BACKSPACE', () => {
|
||||
this.backToPreviousScene();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keyup-RIGHT', () => this.moveCursorHorizontally(1));
|
||||
|
@ -222,6 +127,27 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
}
|
||||
|
||||
private moveCursorVertically(index:number): void {
|
||||
|
||||
if(index === -1 && this.activeRow === 5){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormSubmit') as HTMLButtonElement;
|
||||
button.innerHTML = `Next <img src="resources/objects/arrow_up.png"/>`;
|
||||
}
|
||||
|
||||
if(index === 1 && this.activeRow === 4){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormSubmit') as HTMLButtonElement;
|
||||
button.innerText = 'Finish';
|
||||
}
|
||||
|
||||
if(index === -1 && this.activeRow === 1){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
|
||||
button.innerText = `Return`;
|
||||
}
|
||||
|
||||
if(index === 1 && this.activeRow === 0){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
|
||||
button.innerHTML = `Back <img src="resources/objects/arrow_up.png"/>`;
|
||||
}
|
||||
|
||||
this.activeRow += index;
|
||||
if (this.activeRow < 0) {
|
||||
this.activeRow = 0
|
||||
|
@ -236,11 +162,6 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
localUserStore.setCustomCursorPosition(this.activeRow, this.selectedLayers);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
super.update(time, delta);
|
||||
this.enterField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x, the layer's vertical position
|
||||
* @param y, the layer's horizontal position
|
||||
|
@ -298,7 +219,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
*/
|
||||
private moveLayers(): void {
|
||||
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||
const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;
|
||||
const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
||||
const screenWidth = this.game.renderer.width;
|
||||
const screenHeight = this.game.renderer.height;
|
||||
for (let i = 0; i < this.containersRow.length; i++) {
|
||||
|
@ -337,39 +258,63 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||
}
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.customizeSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
public onResize(): void {
|
||||
this.moveLayers();
|
||||
|
||||
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||
this.mobileTapENTER.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 2;
|
||||
this.mobileTapENTER.y = this.cameras.main.worldView.y + this.cameras.main.height / 2;
|
||||
|
||||
this.textField.x = this.game.renderer.width/2;
|
||||
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
|
||||
this.arrowUp.x = this.game.renderer.width - 30;
|
||||
this.mobileTapUP.x = this.game.renderer.width - 30;
|
||||
this.arrowUp.y = 60;
|
||||
this.mobileTapUP.y = 60;
|
||||
|
||||
this.arrowDown.x = this.game.renderer.width - 30;
|
||||
this.mobileTapDOWN.x = this.game.renderer.width - 30;
|
||||
this.arrowDown.y = 100;
|
||||
this.mobileTapDOWN.y = 100;
|
||||
|
||||
this.arrowLeft.x = this.game.renderer.width/9;
|
||||
this.mobileTapLEFT.x = this.game.renderer.width/9;
|
||||
this.arrowLeft.y = this.game.renderer.height/2;
|
||||
this.mobileTapLEFT.y = this.game.renderer.height/2;
|
||||
|
||||
this.arrowRight.x = this.game.renderer.width*0.9;
|
||||
this.mobileTapRIGHT.x = this.game.renderer.width*0.9;
|
||||
this.arrowRight.y = this.game.renderer.height/2;
|
||||
this.mobileTapRIGHT.y = this.game.renderer.height/2;
|
||||
|
||||
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.customizeSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
protected getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.customizeSceneElement
|
||||
&& this.customizeSceneElement.node
|
||||
&& this.customizeSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.customizeSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
: 150
|
||||
);
|
||||
}
|
||||
|
||||
private nextSceneToCamera(){
|
||||
const layers: string[] = [];
|
||||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!areCharacterLayersValid(layers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gameManager.setCharacterLayers(layers);
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
this.scene.remove(SelectCharacterSceneName);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
}
|
||||
|
||||
private backToPreviousScene(){
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
this.scene.run(SelectCharacterSceneName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
|||
import {SoundMeter} from "../Components/SoundMeter";
|
||||
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import Zone = Phaser.GameObjects.Zone;
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
|
||||
export const EnableCameraSceneName = "EnableCameraScene";
|
||||
enum LoginTextures {
|
||||
|
@ -17,12 +21,11 @@ enum LoginTextures {
|
|||
arrowUp = "arrow_up"
|
||||
}
|
||||
|
||||
const enableCameraSceneKey = 'enableCameraScene';
|
||||
|
||||
export class EnableCameraScene extends Phaser.Scene {
|
||||
private textField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private cameraNameField!: TextField;
|
||||
private logo!: Image;
|
||||
private arrowLeft!: Image;
|
||||
private arrowRight!: Image;
|
||||
private arrowDown!: Image;
|
||||
|
@ -36,7 +39,9 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
private microphoneNameField!: TextField;
|
||||
private repositionCallback!: (this: Window, ev: UIEvent) => void;
|
||||
|
||||
private mobileTapRectangle!: Rectangle;
|
||||
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
|
||||
private mobileTapZone!: Zone;
|
||||
constructor() {
|
||||
super({
|
||||
key: EnableCameraSceneName
|
||||
|
@ -45,8 +50,10 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
preload() {
|
||||
|
||||
this.load.html(enableCameraSceneKey, 'resources/html/EnableCameraScene.html');
|
||||
|
||||
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
this.load.image(LoginTextures.arrowRight, "resources/objects/arrow_right.png");
|
||||
this.load.image(LoginTextures.arrowUp, "resources/objects/arrow_up.png");
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
|
@ -54,19 +61,27 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
create() {
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 20, 'Turn on your camera and microphone');
|
||||
|
||||
this.pressReturnField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height - 30, 'Touch here\n\n or \n\nPress enter to start');
|
||||
const middleX = this.getMiddleX();
|
||||
this.enableCameraSceneElement = this.add.dom(middleX, 0).createFromCache(enableCameraSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey);
|
||||
|
||||
const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement;
|
||||
continuingButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
this.login();
|
||||
});
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
/* FIX ME */
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 20, '');
|
||||
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapRectangle = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height - 30,
|
||||
200,
|
||||
50,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.mobileTapZone = this.add.zone(this.game.renderer.width / 2,this.game.renderer.height - 30,200,50)
|
||||
.setInteractive().on("pointerdown", () => {
|
||||
this.login();
|
||||
});
|
||||
|
||||
|
@ -96,9 +111,6 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
this.arrowDown.setInteractive().on('pointerdown', this.nextMic.bind(this));
|
||||
this.add.existing(this.arrowDown);
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
this.login();
|
||||
});
|
||||
|
@ -209,11 +221,9 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.mobileTapRectangle.x = this.game.renderer.width / 2;
|
||||
this.mobileTapZone.x = this.game.renderer.width / 2;
|
||||
this.cameraNameField.x = this.game.renderer.width / 2;
|
||||
this.microphoneNameField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
|
||||
this.cameraNameField.y = bounds.top / RESOLUTION - 8;
|
||||
|
||||
|
@ -233,18 +243,20 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
|
||||
this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
|
||||
this.arrowUp.y = this.microphoneNameField.y;
|
||||
|
||||
this.pressReturnField.y = Math.max(this.game.renderer.height - 30, this.microphoneNameField.y + 20);
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = Math.max(this.game.renderer.height - 20, this.microphoneNameField.y + 30);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
|
||||
this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
|
||||
|
||||
mediaManager.setLastUpdateScene();
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.enableCameraSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private login(): void {
|
||||
|
@ -270,4 +282,15 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||
}
|
||||
this.updateWebCamName();
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.enableCameraSceneElement
|
||||
&& this.enableCameraSceneElement.node
|
||||
&& this.enableCameraSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.enableCameraSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
: (300 / RESOLUTION)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,19 @@
|
|||
import {gameManager} from "../Game/GameManager";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import {TextInput} from "../Components/TextInput";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import {SelectCharacterSceneName} from "./SelectCharacterScene";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {isUserNameValid, maxUserNameLength} from "../../Connexion/LocalUser";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {MenuScene} from "../Menu/MenuScene";
|
||||
import { isUserNameValid } from "../../Connexion/LocalUser";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
//todo: put this constants in a dedicated file
|
||||
export const LoginSceneName = "LoginScene";
|
||||
enum LoginTextures {
|
||||
icon = "icon",
|
||||
mainFont = "main_font"
|
||||
}
|
||||
|
||||
const loginSceneKey = 'loginScene';
|
||||
|
||||
export class LoginScene extends ResizableScene {
|
||||
private nameInput!: TextInput;
|
||||
private textField!: TextField;
|
||||
private infoTextField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private logo!: Image;
|
||||
|
||||
private loginSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
private name: string = '';
|
||||
private mobileTapRectangle!: Rectangle;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
|
@ -32,78 +23,82 @@ export class LoginScene extends ResizableScene {
|
|||
}
|
||||
|
||||
preload() {
|
||||
//this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
this.load.html(loginSceneKey, 'resources/html/loginScene.html');
|
||||
}
|
||||
|
||||
create() {
|
||||
const middleX = this.getMiddleX();
|
||||
this.loginSceneElement = this.add.dom(middleX, 0).createFromCache(loginSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.loginSceneElement, loginSceneKey);
|
||||
|
||||
this.nameInput = new TextInput(this, this.game.renderer.width / 2, 70, maxUserNameLength, this.name,(text: string) => {
|
||||
this.name = text;
|
||||
localUserStore.setName(text);
|
||||
})
|
||||
.setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
this.nameInput.focus();
|
||||
})
|
||||
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Enter your name:')
|
||||
.setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
this.nameInput.focus();
|
||||
})
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapRectangle = this.add.rectangle(
|
||||
this.game.renderer.width / 2,
|
||||
130,
|
||||
this.game.renderer.width / 2,
|
||||
60,
|
||||
).setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
this.login(this.name)
|
||||
})
|
||||
this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 130, 'Touch here\n\n or \n\nPress enter to start')
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
const infoText = "Commands: \n - Arrows or W, A, S, D to move\n - SHIFT to run";
|
||||
this.infoTextField = new TextField(this, 10, this.game.renderer.height - 35, infoText, false);
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
if (isUserNameValid(this.name)) {
|
||||
this.login(this.name);
|
||||
const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
|
||||
const inputElement = this.loginSceneElement.getChildByID('loginSceneName') as HTMLInputElement;
|
||||
inputElement.value = localUserStore.getName() ?? '';
|
||||
inputElement.focus();
|
||||
inputElement.addEventListener('keypress', (event: KeyboardEvent) => {
|
||||
if(inputElement.value.length > 7){
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
pErrorElement.innerHTML = '';
|
||||
if(inputElement.value && !isUserNameValid(inputElement.value)){
|
||||
pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.';
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
this.login(inputElement);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
const continuingButton = this.loginSceneElement.getChildByID('loginSceneFormSubmit') as HTMLButtonElement;
|
||||
continuingButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
this.login(inputElement);
|
||||
});
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
if (this.name == '') {
|
||||
this.pressReturnField?.setVisible(false);
|
||||
} else {
|
||||
this.pressReturnField?.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
private login(inputElement: HTMLInputElement): void {
|
||||
const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
|
||||
this.name = inputElement.value;
|
||||
if (this.name === '') {
|
||||
pErrorElement.innerHTML = 'The name is empty';
|
||||
return
|
||||
}
|
||||
if(!isUserNameValid(this.name)){
|
||||
pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.';
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private login(name: string): void {
|
||||
if (this.name === '') return
|
||||
gameManager.setPlayerName(name);
|
||||
gameManager.setPlayerName(this.name);
|
||||
|
||||
this.scene.stop(LoginSceneName)
|
||||
gameManager.tryResumingGame(this, SelectCharacterSceneName);
|
||||
this.scene.remove(LoginSceneName)
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.nameInput.setX(this.game.renderer.width / 2 - 64);
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.mobileTapRectangle.x = this.game.renderer.width / 2;
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
this.infoTextField.y = this.game.renderer.height - 35;
|
||||
update(time: number, delta: number): void {
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.loginSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.loginSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
const middleX = ((window.innerWidth) - ((this.loginSceneElement && this.loginSceneElement.width > 0 ? this.loginSceneElement.width : 200 /*FIXME to use a const will be injected in HTMLElement*/)*2)) / 2;
|
||||
return (middleX > 0 ? (middleX / 2) : 0);
|
||||
}
|
||||
}
|
||||
|
|
77
front/src/Phaser/Login/SelectCharacterMobileScene.ts
Normal file
77
front/src/Phaser/Login/SelectCharacterMobileScene.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import {gameManager} from "../Game/GameManager";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||
import {CustomizeSceneName} from "./CustomizeScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import {addLoader} from "../Components/Loader";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {MenuScene} from "../Menu/MenuScene";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "./SelectCharacterScene";
|
||||
|
||||
export class SelectCharacterMobileScene extends SelectCharacterScene {
|
||||
|
||||
create(){
|
||||
super.create();
|
||||
this.selectedRectangle.destroy();
|
||||
}
|
||||
|
||||
protected defineSetupPlayer(numero: number){
|
||||
const deltaX = 30;
|
||||
const deltaY = 2;
|
||||
let [playerX, playerY] = this.getCharacterPosition();
|
||||
let playerVisible = true;
|
||||
let playerScale = 1.5;
|
||||
let playserOpactity = 1;
|
||||
|
||||
if( this.currentSelectUser !== numero ){
|
||||
playerVisible = false;
|
||||
}
|
||||
if( numero === (this.currentSelectUser + 1) ){
|
||||
playerY -= deltaY;
|
||||
playerX += deltaX;
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if( numero === (this.currentSelectUser + 2) ){
|
||||
playerY -= deltaY;
|
||||
playerX += (deltaX * 2);
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if( numero === (this.currentSelectUser - 1) ){
|
||||
playerY -= deltaY;
|
||||
playerX -= deltaX;
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if( numero === (this.currentSelectUser - 2) ){
|
||||
playerY -= deltaY;
|
||||
playerX -= (deltaX * 2);
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
return {playerX, playerY, playerScale, playserOpactity, playerVisible}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
protected getCharacterPosition(): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height / 3
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -1,275 +1,275 @@
|
|||
import {gameManager} from "../Game/GameManager";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||
import {CustomizeSceneName} from "./CustomizeScene";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {loadAllDefaultModels, loadCustomTexture} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import {addLoader} from "../Components/Loader";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {MenuScene} from "../Menu/MenuScene";
|
||||
import { SelectCharacterMobileScene } from "./SelectCharacterMobileScene";
|
||||
|
||||
//todo: put this constants in a dedicated file
|
||||
export const SelectCharacterSceneName = "SelectCharacterScene";
|
||||
enum LoginTextures {
|
||||
playButton = "play_button",
|
||||
icon = "icon",
|
||||
mainFont = "main_font",
|
||||
customizeButton = "customize_button",
|
||||
customizeButtonSelected = "customize_button_selected"
|
||||
}
|
||||
|
||||
const selectCharacterKey = 'selectCharacterScene';
|
||||
|
||||
export class SelectCharacterScene extends AbstractCharacterScene {
|
||||
private readonly nbCharactersPerRow = 6;
|
||||
private textField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private logo!: Image;
|
||||
private customizeButton!: Image;
|
||||
private customizeButtonSelected!: Image;
|
||||
protected readonly nbCharactersPerRow = 6;
|
||||
protected selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option
|
||||
protected players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
protected playerModels!: BodyResourceDescriptionInterface[];
|
||||
|
||||
private selectedRectangle!: Rectangle;
|
||||
private selectedRectangleXPos = 0; // Number of the character selected in the rows
|
||||
private selectedRectangleYPos = 0; // Number of the character selected in the columns
|
||||
private selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option
|
||||
private players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
private mobileTapRectangle!: Rectangle;
|
||||
private playerModels!: BodyResourceDescriptionInterface[];
|
||||
protected selectedRectangle!: Rectangle;
|
||||
|
||||
protected selectCharacterSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
protected currentSelectUser = 0;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
key: SelectCharacterSceneName
|
||||
key: SelectCharacterSceneName,
|
||||
});
|
||||
}
|
||||
|
||||
preload() {
|
||||
addLoader(this);
|
||||
|
||||
this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html');
|
||||
|
||||
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
|
||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||
this.playerModels.push(bodyResourceDescription);
|
||||
});
|
||||
})
|
||||
|
||||
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
this.playerModels = loadAllDefaultModels(this.load);
|
||||
this.load.image(LoginTextures.customizeButton, 'resources/objects/customize.png');
|
||||
this.load.image(LoginTextures.customizeButtonSelected, 'resources/objects/customize_selected.png');
|
||||
|
||||
addLoader(this);
|
||||
}
|
||||
|
||||
create() {
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Select your character');
|
||||
this.pressReturnField = new TextField(
|
||||
this,
|
||||
this.game.renderer.width / 2,
|
||||
90 + 32 * Math.ceil( this.playerModels.length / this.nbCharactersPerRow) + 60,
|
||||
'Touch here\n\n or \n\nPress enter to start');
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapRectangle = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width / 2,
|
||||
275,
|
||||
this.game.renderer.width / 2,
|
||||
50,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.nextScene();
|
||||
});
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.selectCharacterSceneElement = this.add.dom(middleX, 0).createFromCache(selectCharacterKey);
|
||||
MenuScene.revealMenusAfterInit(this.selectCharacterSceneElement, selectCharacterKey);
|
||||
|
||||
this.selectCharacterSceneElement.addListener('click');
|
||||
this.selectCharacterSceneElement.on('click', (event:MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'selectCharacterButtonLeft') {
|
||||
this.moveToLeft();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterButtonRight') {
|
||||
this.moveToRight();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterSceneFormSubmit') {
|
||||
this.nextSceneToCameraScene();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterSceneFormCustomYourOwnSubmit') {
|
||||
this.nextSceneToCustomizeScene();
|
||||
}
|
||||
});
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
||||
|
||||
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF);
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
return this.nextScene();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', () => {
|
||||
if(this.selectedRectangleYPos * this.nbCharactersPerRow + (this.selectedRectangleXPos + 2))
|
||||
if (
|
||||
this.selectedRectangleXPos < this.nbCharactersPerRow - 1
|
||||
&& ((this.selectedRectangleYPos * this.nbCharactersPerRow) + (this.selectedRectangleXPos + 1) + 1) <= this.playerModels.length
|
||||
) {
|
||||
this.selectedRectangleXPos++;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.input.keyboard.on('keydown-LEFT', () => {
|
||||
if (
|
||||
this.selectedRectangleXPos > 0
|
||||
&& ((this.selectedRectangleYPos * this.nbCharactersPerRow) + (this.selectedRectangleXPos - 1) + 1) <= this.playerModels.length
|
||||
) {
|
||||
this.selectedRectangleXPos--;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.input.keyboard.on('keydown-DOWN', () => {
|
||||
if (
|
||||
this.selectedRectangleYPos < Math.ceil(this.playerModels.length / this.nbCharactersPerRow)
|
||||
&& (
|
||||
(((this.selectedRectangleYPos + 1) * this.nbCharactersPerRow) + this.selectedRectangleXPos + 1) <= this.playerModels.length // check if player isn't empty
|
||||
|| (this.selectedRectangleYPos + 1) === Math.ceil(this.playerModels.length / this.nbCharactersPerRow) // check if is custom rectangle
|
||||
)
|
||||
) {
|
||||
this.selectedRectangleYPos++;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.input.keyboard.on('keydown-UP', () => {
|
||||
if (
|
||||
this.selectedRectangleYPos > 0
|
||||
&& (((this.selectedRectangleYPos - 1) * this.nbCharactersPerRow) + this.selectedRectangleXPos + 1) <= this.playerModels.length
|
||||
) {
|
||||
this.selectedRectangleYPos--;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.selectedRectangle.setDepth(2);
|
||||
|
||||
/*create user*/
|
||||
this.createCurrentPlayer();
|
||||
|
||||
const playerNumber = localUserStore.getPlayerCharacterIndex();
|
||||
if (playerNumber && playerNumber !== -1) {
|
||||
this.selectedRectangleXPos = playerNumber % this.nbCharactersPerRow;
|
||||
this.selectedRectangleYPos = Math.floor(playerNumber / this.nbCharactersPerRow);
|
||||
this.updateSelectedPlayer();
|
||||
} else if (playerNumber === -1) {
|
||||
this.selectedRectangleYPos = Math.ceil(this.playerModels.length / this.nbCharactersPerRow);
|
||||
this.updateSelectedPlayer();
|
||||
}
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
return this.nextSceneToCameraScene();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', () => {
|
||||
this.moveToRight();
|
||||
});
|
||||
this.input.keyboard.on('keydown-LEFT', () => {
|
||||
this.moveToLeft();
|
||||
});
|
||||
this.input.keyboard.on('keydown-UP', () => {
|
||||
this.moveToUp();
|
||||
});
|
||||
this.input.keyboard.on('keydown-DOWN', () => {
|
||||
this.moveToDown();
|
||||
});
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
}
|
||||
|
||||
private nextScene(): void {
|
||||
protected nextSceneToCameraScene(): void {
|
||||
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
|
||||
return;
|
||||
}
|
||||
this.scene.stop(SelectCharacterSceneName);
|
||||
if (this.selectedPlayer !== null) {
|
||||
gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
} else {
|
||||
this.scene.run(CustomizeSceneName);
|
||||
if(!this.selectedPlayer){
|
||||
return;
|
||||
}
|
||||
this.scene.stop(SelectCharacterSceneName);
|
||||
gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
this.scene.remove(SelectCharacterSceneName);
|
||||
}
|
||||
|
||||
protected nextSceneToCustomizeScene(): void {
|
||||
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
|
||||
return;
|
||||
}
|
||||
this.scene.sleep(SelectCharacterSceneName);
|
||||
this.scene.run(CustomizeSceneName);
|
||||
}
|
||||
|
||||
createCurrentPlayer(): void {
|
||||
for (let i = 0; i <this.playerModels.length; i++) {
|
||||
const playerResource = this.playerModels[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
const player = this.physics.add.sprite(x, y, playerResource.name, 0);
|
||||
player.setBounce(0.2);
|
||||
player.setCollideWorldBounds(true);
|
||||
const [middleX, middleY] = this.getCharacterPosition();
|
||||
const player = this.physics.add.sprite(middleX, middleY, playerResource.name, 0);
|
||||
this.setUpPlayer(player, i);
|
||||
this.anims.create({
|
||||
key: playerResource.name,
|
||||
frames: this.anims.generateFrameNumbers(playerResource.name, {start: 0, end: 2,}),
|
||||
frameRate: 10,
|
||||
frames: this.anims.generateFrameNumbers(playerResource.name, {start: 0, end: 11}),
|
||||
frameRate: 8,
|
||||
repeat: -1
|
||||
});
|
||||
player.setInteractive().on("pointerdown", () => {
|
||||
this.selectedRectangleXPos = col;
|
||||
this.selectedRectangleYPos = row;
|
||||
this.updateSelectedPlayer();
|
||||
if(this.currentSelectUser === i){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser = i;
|
||||
this.moveUser();
|
||||
});
|
||||
this.players.push(player);
|
||||
}
|
||||
|
||||
const maxRow = Math.ceil( this.playerModels.length / this.nbCharactersPerRow);
|
||||
this.customizeButton = new Image(this, this.game.renderer.width / 2, 90 + 32 * maxRow + 6, LoginTextures.customizeButton);
|
||||
this.customizeButton.setOrigin(0.5, 0.5);
|
||||
this.add.existing(this.customizeButton);
|
||||
this.customizeButtonSelected = new Image(this, this.game.renderer.width / 2, 90 + 32 * maxRow + 6, LoginTextures.customizeButtonSelected);
|
||||
this.customizeButtonSelected.setOrigin(0.5, 0.5);
|
||||
this.customizeButtonSelected.setVisible(false);
|
||||
this.add.existing(this.customizeButtonSelected);
|
||||
this.selectedPlayer = this.players[this.currentSelectUser];
|
||||
this.selectedPlayer.play(this.playerModels[this.currentSelectUser].name);
|
||||
}
|
||||
|
||||
this.customizeButton.setInteractive().on("pointerdown", () => {
|
||||
this.selectedRectangleYPos = Math.ceil(this.playerModels.length / this.nbCharactersPerRow);
|
||||
this.updateSelectedPlayer();
|
||||
this.nextScene();
|
||||
});
|
||||
this.customizeButtonSelected.setInteractive().on("pointerdown", () => {
|
||||
this.nextScene();
|
||||
});
|
||||
protected moveUser(){
|
||||
for(let i = 0; i < this.players.length; i++){
|
||||
const player = this.players[i];
|
||||
this.setUpPlayer(player, i);
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
}
|
||||
|
||||
this.selectedPlayer = this.players[0];
|
||||
this.selectedPlayer.play(this.playerModels[0].name);
|
||||
protected moveToLeft(){
|
||||
if(this.currentSelectUser === 0){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser -= 1;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToRight(){
|
||||
if(this.currentSelectUser === (this.players.length - 1)){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser += 1;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToUp(){
|
||||
if(this.currentSelectUser < this.nbCharactersPerRow){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser -= this.nbCharactersPerRow;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToDown(){
|
||||
if((this.currentSelectUser + this.nbCharactersPerRow) > (this.players.length - 1)){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser += this.nbCharactersPerRow;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected defineSetupPlayer(numero: number){
|
||||
const deltaX = 32;
|
||||
const deltaY = 32;
|
||||
let [playerX, playerY] = this.getCharacterPosition(); // player X and player y are middle of the
|
||||
|
||||
playerX = ( (playerX - (deltaX * 2.5)) + ((deltaX) * (numero % this.nbCharactersPerRow)) ); // calcul position on line users
|
||||
playerY = ( (playerY - (deltaY * 2)) + ((deltaY) * ( Math.floor(numero / this.nbCharactersPerRow) )) ); // calcul position on column users
|
||||
|
||||
const playerVisible = true;
|
||||
const playerScale = 1;
|
||||
const playserOpactity = 1;
|
||||
|
||||
// if selected
|
||||
if( numero === this.currentSelectUser ){
|
||||
this.selectedRectangle.setX(playerX);
|
||||
this.selectedRectangle.setY(playerY);
|
||||
}
|
||||
|
||||
return {playerX, playerY, playerScale, playserOpactity, playerVisible}
|
||||
}
|
||||
|
||||
protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, numero: number){
|
||||
|
||||
const {playerX, playerY, playerScale, playserOpactity, playerVisible} = this.defineSetupPlayer(numero);
|
||||
player.setBounce(0.2);
|
||||
player.setCollideWorldBounds(true);
|
||||
player.setVisible( playerVisible );
|
||||
player.setScale(playerScale, playerScale);
|
||||
player.setAlpha(playserOpactity);
|
||||
player.setX(playerX);
|
||||
player.setY(playerY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
private getCharacterPosition(x: number, y: number): [number, number] {
|
||||
protected getCharacterPosition(): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2 + 16 + (x - this.nbCharactersPerRow / 2) * 32,
|
||||
y * 32 + 90
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height / 2.5
|
||||
];
|
||||
}
|
||||
|
||||
private updateSelectedPlayer(): void {
|
||||
this.selectedPlayer?.anims.pause();
|
||||
// If we selected the customize button
|
||||
if (this.selectedRectangleYPos === Math.ceil(this.playerModels.length / this.nbCharactersPerRow)) {
|
||||
this.selectedPlayer = null;
|
||||
this.selectedRectangle.setVisible(false);
|
||||
this.customizeButtonSelected.setVisible(true);
|
||||
this.customizeButton.setVisible(false);
|
||||
localUserStore.setPlayerCharacterIndex(-1);
|
||||
return;
|
||||
}
|
||||
this.customizeButtonSelected.setVisible(false);
|
||||
this.customizeButton.setVisible(true);
|
||||
const [x, y] = this.getCharacterPosition(this.selectedRectangleXPos, this.selectedRectangleYPos);
|
||||
this.selectedRectangle.setVisible(true);
|
||||
this.selectedRectangle.setX(x);
|
||||
this.selectedRectangle.setY(y);
|
||||
this.selectedRectangle.setSize(32, 32);
|
||||
const playerNumber = this.selectedRectangleXPos + this.selectedRectangleYPos * this.nbCharactersPerRow;
|
||||
const player = this.players[playerNumber];
|
||||
player.play(this.playerModels[playerNumber].name);
|
||||
protected updateSelectedPlayer(): void {
|
||||
this.selectedPlayer?.anims.pause(this.selectedPlayer?.anims.currentAnim.frames[0]);
|
||||
const player = this.players[this.currentSelectUser];
|
||||
player.play(this.playerModels[this.currentSelectUser].name);
|
||||
this.selectedPlayer = player;
|
||||
localUserStore.setPlayerCharacterIndex(playerNumber);
|
||||
localUserStore.setPlayerCharacterIndex(this.currentSelectUser);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.selectCharacterSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
this.customizeButton.x = this.game.renderer.width / 2;
|
||||
this.customizeButtonSelected.x = this.game.renderer.width / 2;
|
||||
//move position of user
|
||||
this.moveUser();
|
||||
|
||||
for (let i = 0; i <this.playerModels.length; i++) {
|
||||
const player = this.players[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
player.x = x;
|
||||
player.y = y;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.selectCharacterSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
protected getMiddleX() : number{
|
||||
return (this.game.renderer.width / 2) -
|
||||
(
|
||||
this.selectCharacterSceneElement
|
||||
&& this.selectCharacterSceneElement.node
|
||||
&& this.selectCharacterSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.selectCharacterSceneElement.node.getBoundingClientRect().width / 4)
|
||||
: 150
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,33 +3,26 @@ import Rectangle = Phaser.GameObjects.Rectangle;
|
|||
import { addLoader } from "../Components/Loader";
|
||||
import { gameManager} from "../Game/GameManager";
|
||||
import { ResizableScene } from "./ResizableScene";
|
||||
import { TextField } from "../Components/TextField";
|
||||
import { EnableCameraSceneName } from "./EnableCameraScene";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { CompanionResourceDescriptionInterface } from "../Companion/CompanionTextures";
|
||||
import { getAllCompanionResources } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const SelectCompanionSceneName = "SelectCompanionScene";
|
||||
|
||||
enum LoginTextures {
|
||||
playButton = "play_button",
|
||||
icon = "icon",
|
||||
mainFont = "main_font"
|
||||
}
|
||||
const selectCompanionSceneKey = 'selectCompanionScene';
|
||||
|
||||
export class SelectCompanionScene extends ResizableScene {
|
||||
private logo!: Image;
|
||||
private textField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private readonly nbCharactersPerRow = 7;
|
||||
|
||||
private selectedRectangle!: Rectangle;
|
||||
|
||||
private selectedCompanion!: Phaser.Physics.Arcade.Sprite;
|
||||
private companions: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
private companionModels: Array<CompanionResourceDescriptionInterface|null> = [null];
|
||||
private companionModels: Array<CompanionResourceDescriptionInterface> = [];
|
||||
|
||||
private confirmTouchArea!: Rectangle;
|
||||
private selectCompanionSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
private currentCompanion = 0;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
|
@ -40,204 +33,221 @@ export class SelectCompanionScene extends ResizableScene {
|
|||
preload() {
|
||||
addLoader(this);
|
||||
|
||||
this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html');
|
||||
|
||||
getAllCompanionResources(this.load).forEach(model => {
|
||||
this.companionModels.push(model);
|
||||
});
|
||||
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
|
||||
addLoader(this);
|
||||
}
|
||||
|
||||
create() {
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Select your companion');
|
||||
|
||||
const confirmTouchAreaY = 115 + 32 * Math.ceil(this.companionModels.length / this.nbCharactersPerRow);
|
||||
this.pressReturnField = new TextField(
|
||||
this,
|
||||
this.game.renderer.width / 2,
|
||||
confirmTouchAreaY,
|
||||
'Touch here\n\n or \n\n press enter to start'
|
||||
);
|
||||
this.confirmTouchArea = this.add
|
||||
.rectangle(this.game.renderer.width / 2, confirmTouchAreaY, 200, 50)
|
||||
.setInteractive()
|
||||
.on("pointerdown", this.nextScene.bind(this));
|
||||
const middleX = this.getMiddleX();
|
||||
this.selectCompanionSceneElement = this.add.dom(middleX, 0).createFromCache(selectCompanionSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.selectCompanionSceneElement, selectCompanionSceneKey);
|
||||
|
||||
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
||||
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF);
|
||||
this.selectCompanionSceneElement.addListener('click');
|
||||
this.selectCompanionSceneElement.on('click', (event:MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'selectCharacterButtonLeft') {
|
||||
this.moveToLeft();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterButtonRight') {
|
||||
this.moveToRight();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCompanionSceneFormSubmit') {
|
||||
this.nextScene();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCompanionSceneFormBack') {
|
||||
this._nextScene();
|
||||
}
|
||||
});
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
// input events
|
||||
this.input.keyboard.on('keyup-ENTER', this.nextScene.bind(this));
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', this.selectNext.bind(this));
|
||||
this.input.keyboard.on('keydown-LEFT', this.selectPrevious.bind(this));
|
||||
this.input.keyboard.on('keydown-DOWN', this.jumpToNextRow.bind(this));
|
||||
this.input.keyboard.on('keydown-UP', this.jumpToPreviousRow.bind(this));
|
||||
this.input.keyboard.on('keydown-RIGHT', this.moveToRight.bind(this));
|
||||
this.input.keyboard.on('keydown-LEFT', this.moveToLeft.bind(this));
|
||||
|
||||
if(localUserStore.getCompanion()){
|
||||
const companionIndex = this.companionModels.findIndex((companion) => companion.name === localUserStore.getCompanion());
|
||||
if(companionIndex > -1 || companionIndex < this.companions.length){
|
||||
this.currentCompanion = companionIndex;
|
||||
this.selectedCompanion = this.companions[companionIndex];
|
||||
}
|
||||
}
|
||||
|
||||
localUserStore.setCompanion(null);
|
||||
gameManager.setCompanion(null);
|
||||
|
||||
this.createCurrentCompanion();
|
||||
this.selectCompanion(this.getCompanionIndex());
|
||||
this.updateSelectedCompanion();
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
}
|
||||
|
||||
private jumpToPreviousRow(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion) - this.nbCharactersPerRow;
|
||||
if (index >= 0) {
|
||||
this.selectCompanion(index);
|
||||
}
|
||||
}
|
||||
|
||||
private jumpToNextRow(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion) + this.nbCharactersPerRow;
|
||||
if (index < this.companions.length) {
|
||||
this.selectCompanion(index);
|
||||
}
|
||||
}
|
||||
|
||||
private selectPrevious(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion);
|
||||
this.selectCompanion(index - 1);
|
||||
}
|
||||
|
||||
private selectNext(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion);
|
||||
this.selectCompanion(index + 1);
|
||||
}
|
||||
|
||||
private selectCompanion(index?: number): void {
|
||||
if (typeof index === 'undefined') {
|
||||
index = this.companions.indexOf(this.selectedCompanion);
|
||||
}
|
||||
|
||||
// make sure index is inside possible range
|
||||
index = Math.min(this.companions.length - 1, Math.max(0, index));
|
||||
|
||||
if (this.selectedCompanion === this.companions[index]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedCompanion.anims.pause();
|
||||
this.selectedCompanion = this.companions[index];
|
||||
|
||||
this.redrawSelectedRectangle();
|
||||
|
||||
const model = this.companionModels[index];
|
||||
|
||||
if (model !== null) {
|
||||
this.selectedCompanion.anims.play(model.name);
|
||||
}
|
||||
}
|
||||
|
||||
private redrawSelectedRectangle(): void {
|
||||
this.selectedRectangle.setVisible(true);
|
||||
this.selectedRectangle.setX(this.selectedCompanion.x);
|
||||
this.selectedRectangle.setY(this.selectedCompanion.y);
|
||||
this.selectedRectangle.setSize(32, 32);
|
||||
}
|
||||
|
||||
private storeCompanionSelection(): string|null {
|
||||
const index = this.companions.indexOf(this.selectedCompanion);
|
||||
const model = this.companionModels[index];
|
||||
const companion = model === null ? null : model.name;
|
||||
|
||||
localUserStore.setCompanion(companion);
|
||||
|
||||
return companion;
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.selectCompanionSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private nextScene(): void {
|
||||
const companion = this.storeCompanionSelection();
|
||||
localUserStore.setCompanion(this.companionModels[this.currentCompanion].name);
|
||||
gameManager.setCompanion(this.companionModels[this.currentCompanion].name);
|
||||
|
||||
this._nextScene();
|
||||
}
|
||||
|
||||
private _nextScene(){
|
||||
// next scene
|
||||
this.scene.stop(SelectCompanionSceneName);
|
||||
|
||||
gameManager.setCompanion(companion);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
|
||||
this.scene.remove(SelectCompanionSceneName);
|
||||
}
|
||||
|
||||
private createCurrentCompanion(): void {
|
||||
for (let i = 0; i < this.companionModels.length; i++) {
|
||||
const companionResource = this.companionModels[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
|
||||
let name = "null";
|
||||
if (companionResource !== null) {
|
||||
name = companionResource.name;
|
||||
}
|
||||
|
||||
const companion = this.physics.add.sprite(x, y, name, 0);
|
||||
companion.setBounce(0.2);
|
||||
companion.setCollideWorldBounds(true);
|
||||
|
||||
if (companionResource !== null) {
|
||||
this.anims.create({
|
||||
key: name,
|
||||
frames: this.anims.generateFrameNumbers(name, {start: 0, end: 2,}),
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
const companionResource = this.companionModels[i]
|
||||
const [middleX, middleY] = this.getCompanionPosition();
|
||||
const companion = this.physics.add.sprite(middleX, middleY, companionResource.name, 0);
|
||||
this.setUpCompanion(companion, i);
|
||||
this.anims.create({
|
||||
key: companionResource.name,
|
||||
frames: this.anims.generateFrameNumbers(companionResource.name, {start: 0, end: 2,}),
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
companion.setInteractive().on("pointerdown", () => {
|
||||
this.selectCompanion(i);
|
||||
this.currentCompanion = i;
|
||||
this.moveCompanion();
|
||||
});
|
||||
|
||||
this.companions.push(companion);
|
||||
}
|
||||
|
||||
this.selectedCompanion = this.companions[0];
|
||||
}
|
||||
|
||||
private getCharacterPosition(x: number, y: number): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2 + 16 + (x - this.nbCharactersPerRow / 2) * 32,
|
||||
y * 32 + 90
|
||||
];
|
||||
this.selectedCompanion = this.companions[this.currentCompanion];
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
this.moveCompanion();
|
||||
|
||||
for (let i = 0; i < this.companionModels.length; i++) {
|
||||
const companion = this.companions[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
companion.x = x;
|
||||
companion.y = y;
|
||||
}
|
||||
|
||||
this.redrawSelectedRectangle();
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.selectCompanionSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private getCompanionIndex(): number {
|
||||
const companion = localUserStore.getCompanion();
|
||||
private updateSelectedCompanion(): void {
|
||||
this.selectedCompanion?.anims.pause();
|
||||
const companion = this.companions[this.currentCompanion];
|
||||
companion.play(this.companionModels[this.currentCompanion].name);
|
||||
this.selectedCompanion = companion;
|
||||
}
|
||||
|
||||
if (companion === null) {
|
||||
return 0;
|
||||
private moveCompanion(){
|
||||
for(let i = 0; i < this.companions.length; i++){
|
||||
const companion = this.companions[i];
|
||||
this.setUpCompanion(companion, i);
|
||||
}
|
||||
this.updateSelectedCompanion();
|
||||
}
|
||||
|
||||
return this.companionModels.findIndex(model => model !== null && model.name === companion);
|
||||
private moveToLeft(){
|
||||
if(this.currentCompanion === 0){
|
||||
return;
|
||||
}
|
||||
this.currentCompanion -= 1;
|
||||
this.moveCompanion();
|
||||
}
|
||||
|
||||
private moveToRight(){
|
||||
if(this.currentCompanion === (this.companions.length - 1)){
|
||||
return;
|
||||
}
|
||||
this.currentCompanion += 1;
|
||||
this.moveCompanion();
|
||||
}
|
||||
|
||||
private defineSetupCompanion(numero: number){
|
||||
const deltaX = 30;
|
||||
const deltaY = 2;
|
||||
let [companionX, companionY] = this.getCompanionPosition();
|
||||
let companionVisible = true;
|
||||
let companionScale = 1.5;
|
||||
let companionOpactity = 1;
|
||||
if( this.currentCompanion !== numero ){
|
||||
companionVisible = false;
|
||||
}
|
||||
if( numero === (this.currentCompanion + 1) ){
|
||||
companionY -= deltaY;
|
||||
companionX += deltaX;
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
if( numero === (this.currentCompanion + 2) ){
|
||||
companionY -= deltaY;
|
||||
companionX += (deltaX * 2);
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
if( numero === (this.currentCompanion - 1) ){
|
||||
companionY -= deltaY;
|
||||
companionX -= deltaX;
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
if( numero === (this.currentCompanion - 2) ){
|
||||
companionY -= deltaY;
|
||||
companionX -= (deltaX * 2);
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
return {companionX, companionY, companionScale, companionOpactity, companionVisible}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
private getCompanionPosition(): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height / 3
|
||||
];
|
||||
}
|
||||
|
||||
private setUpCompanion(companion: Phaser.Physics.Arcade.Sprite, numero: number){
|
||||
|
||||
const {companionX, companionY, companionScale, companionOpactity, companionVisible} = this.defineSetupCompanion(numero);
|
||||
companion.setBounce(0.2);
|
||||
companion.setCollideWorldBounds(true);
|
||||
companion.setVisible( companionVisible );
|
||||
companion.setScale(companionScale, companionScale);
|
||||
companion.setAlpha(companionOpactity);
|
||||
companion.setX(companionX);
|
||||
companion.setY(companionY);
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.selectCompanionSceneElement
|
||||
&& this.selectCompanionSceneElement.node
|
||||
&& this.selectCompanionSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.selectCompanionSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
: 150
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export interface ITiledMap {
|
|||
* Map orientation (orthogonal)
|
||||
*/
|
||||
orientation: string;
|
||||
properties: ITiledMapLayerProperty[];
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
|
||||
/**
|
||||
* Render order (right-down)
|
||||
|
@ -24,6 +24,11 @@ export interface ITiledMap {
|
|||
tilewidth: number;
|
||||
tilesets: ITiledTileSet[];
|
||||
version: number;
|
||||
compressionlevel?: number;
|
||||
infinite?: boolean;
|
||||
nextlayerid?: number;
|
||||
tiledversion?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface ITiledMapLayerProperty {
|
||||
|
@ -38,19 +43,35 @@ export interface ITiledMapLayerProperty {
|
|||
value: boolean
|
||||
}*/
|
||||
|
||||
export interface ITiledMapLayer {
|
||||
export type ITiledMapLayer = ITiledMapGroupLayer | ITiledMapObjectLayer | ITiledMapTileLayer;
|
||||
|
||||
export interface ITiledMapGroupLayer {
|
||||
id?: number,
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
|
||||
type: "group";
|
||||
visible: boolean;
|
||||
x: number;
|
||||
y: number;
|
||||
/**
|
||||
* Layers for group layer
|
||||
*/
|
||||
layers: ITiledMapLayer[];
|
||||
}
|
||||
|
||||
export interface ITiledMapTileLayer {
|
||||
id?: number,
|
||||
data: number[]|string;
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties: ITiledMapLayerProperty[];
|
||||
encoding: string;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
encoding?: string;
|
||||
compression?: string;
|
||||
|
||||
/**
|
||||
* Type of layer (tilelayer, objectgroup)
|
||||
*/
|
||||
type: string;
|
||||
type: "tilelayer";
|
||||
visible: boolean;
|
||||
width: number;
|
||||
x: number;
|
||||
|
@ -59,7 +80,28 @@ export interface ITiledMapLayer {
|
|||
/**
|
||||
* Draw order (topdown (default), index)
|
||||
*/
|
||||
draworder: string;
|
||||
draworder?: string;
|
||||
}
|
||||
|
||||
export interface ITiledMapObjectLayer {
|
||||
id?: number,
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
encoding?: string;
|
||||
compression?: string;
|
||||
|
||||
type: "objectgroup";
|
||||
visible: boolean;
|
||||
width: number;
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
/**
|
||||
* Draw order (topdown (default), index)
|
||||
*/
|
||||
draworder?: string;
|
||||
objects: ITiledMapObject[];
|
||||
}
|
||||
|
||||
|
|
44
front/src/Phaser/Map/LayersIterator.ts
Normal file
44
front/src/Phaser/Map/LayersIterator.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import {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,6 +1,7 @@
|
|||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
|
||||
const helpCameraSettings = 'helpCameraSettings';
|
||||
|
@ -25,7 +26,7 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
private createHelpCameraSettings() : void {
|
||||
const middleX = (window.innerWidth / 3) - (370*0.85);
|
||||
const middleX = this.getMiddleX();
|
||||
this.helpCameraSettingsElement = this.add.dom(middleX, -800, undefined, {overflow: 'scroll'}).createFromCache(helpCameraSettings);
|
||||
this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings);
|
||||
this.helpCameraSettingsElement.addListener('click');
|
||||
|
@ -46,19 +47,13 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||
private openHelpCameraSettingsOpened(): void{
|
||||
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
||||
this.helpCameraSettingsOpened = true;
|
||||
let middleY = (window.innerHeight / 3) - (495);
|
||||
if(middleY < 0){
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = (window.innerWidth / 3) - (370*0.85);
|
||||
if(middleX < 0){
|
||||
middleX = 0;
|
||||
}
|
||||
if(window.navigator.userAgent.includes('Firefox')){
|
||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>';
|
||||
}else if(window.navigator.userAgent.includes('Chrome')){
|
||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-chrome.png"/>';
|
||||
}
|
||||
const middleY = this.getMiddleY();
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
y: middleY,
|
||||
|
@ -70,6 +65,7 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
private closeHelpCameraSettingsOpened(): void{
|
||||
const middleX = this.getMiddleX();
|
||||
const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
|
||||
helpCameraSettingsInfo.innerText = '';
|
||||
helpCameraSettingsInfo.style.display = 'none';
|
||||
|
@ -77,6 +73,7 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
y: -400,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3',
|
||||
overflow: 'scroll'
|
||||
|
@ -91,5 +88,49 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||
}, 250);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
const middleX = this.getMiddleX();
|
||||
const middleY = this.getMiddleY();
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
x: middleX,
|
||||
y: middleY,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
const middleX = this.getMiddleX();
|
||||
const middleY = this.getMiddleY();
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
x: middleX,
|
||||
y: middleY,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.helpCameraSettingsElement
|
||||
&& this.helpCameraSettingsElement.node
|
||||
&& this.helpCameraSettingsElement.node.getBoundingClientRect().width > 0
|
||||
? (this.helpCameraSettingsElement.node.getBoundingClientRect().width / 4)
|
||||
: (400 / 2)
|
||||
);
|
||||
}
|
||||
|
||||
private getMiddleY() : number{
|
||||
const middleY = ((window.innerHeight) - (
|
||||
(this.helpCameraSettingsElement
|
||||
&& this.helpCameraSettingsElement.node
|
||||
&& this.helpCameraSettingsElement.node.getBoundingClientRect().height > 0
|
||||
? this.helpCameraSettingsElement.node.getBoundingClientRect().height : 400 /*FIXME to use a const will be injected in HTMLElement*/)*2)) / 2;
|
||||
return (middleY > 0 ? middleY / RESOLUTION : 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ const gameMenuIconKey = 'gameMenuIcon';
|
|||
const gameSettingsMenuKey = 'gameSettingsMenu';
|
||||
const gameShare = 'gameShare';
|
||||
|
||||
const closedSideMenuX = -200;
|
||||
const closedSideMenuX = -1000;
|
||||
const openedSideMenuX = 0;
|
||||
|
||||
/**
|
||||
|
@ -91,7 +91,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
|
||||
this.menuElement.addListener('click');
|
||||
this.menuElement.on('click', this.onMenuClick.bind(this));
|
||||
|
||||
|
||||
worldFullWarningStream.stream.subscribe(() => this.showWorldCapacityWarning());
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,8 @@ export class MenuScene extends Phaser.Scene {
|
|||
this.closeAll();
|
||||
this.sideMenuOpened = true;
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = 'X';
|
||||
if (gameManager.getCurrentGameScene(this).connection && gameManager.getCurrentGameScene(this).connection.isAdmin()) {
|
||||
const connection = gameManager.getCurrentGameScene(this).connection;
|
||||
if (connection && connection.isAdmin()) {
|
||||
const adminSection = this.menuElement.getChildByID('adminConsoleSection') as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
}
|
||||
|
@ -134,7 +135,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private showWorldCapacityWarning() {
|
||||
if (!this.warningContainer) {
|
||||
this.warningContainer = new WarningContainer(this);
|
||||
|
@ -147,7 +148,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
this.warningContainer = null
|
||||
this.warningContainerTimeout = null
|
||||
}, 120000);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private closeSideMenu(): void {
|
||||
|
|
|
@ -7,11 +7,11 @@ export const gameReportRessource = 'resources/html/gameReport.html';
|
|||
|
||||
export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
||||
private opened: boolean = false;
|
||||
|
||||
|
||||
private userId!: number;
|
||||
private userName!: string|undefined;
|
||||
private anonymous: boolean;
|
||||
|
||||
|
||||
constructor(scene: Phaser.Scene, anonymous: boolean) {
|
||||
super(scene, -2000, -2000);
|
||||
this.anonymous = anonymous;
|
||||
|
@ -23,7 +23,7 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
|||
const textToHide = this.getChildByID('askActionP') as HTMLElement;
|
||||
textToHide.hidden = true;
|
||||
}
|
||||
|
||||
|
||||
scene.add.existing(this);
|
||||
MenuScene.revealMenusAfterInit(this, gameReportKey);
|
||||
|
||||
|
@ -45,10 +45,10 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
|||
this.close();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.userId = userId;
|
||||
this.userName = userName;
|
||||
|
||||
|
||||
const mainEl = this.getChildByID('gameReport') as HTMLElement;
|
||||
this.x = this.getCenteredX(mainEl);
|
||||
this.y = this.getHiddenY(mainEl);
|
||||
|
@ -82,7 +82,7 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
|||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//todo: into a parent class?
|
||||
private getCenteredX(mainEl: HTMLElement): number {
|
||||
return window.innerWidth / 4 - mainEl.clientWidth / 2;
|
||||
|
@ -93,7 +93,7 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
|||
private getCenteredY(mainEl: HTMLElement): number {
|
||||
return window.innerHeight / 4 - mainEl.clientHeight / 2;
|
||||
}
|
||||
|
||||
|
||||
private toggleBlock(): void {
|
||||
!blackListManager.isBlackListed(this.userId) ? blackListManager.blackList(this.userId) : blackListManager.cancelBlackList(this.userId);
|
||||
this.close();
|
||||
|
@ -109,10 +109,10 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
|||
gamePError.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
gameManager.getCurrentGameScene(this.scene).connection.emitReportPlayerMessage(
|
||||
gameManager.getCurrentGameScene(this.scene).connection?.emitReportPlayerMessage(
|
||||
this.userId,
|
||||
gameTextArea.value
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
22
front/src/Phaser/UserInput/PinchManager.ts
Normal file
22
front/src/Phaser/UserInput/PinchManager.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import {Pinch} from "phaser3-rex-plugins/plugins/gestures.js";
|
||||
|
||||
export class PinchManager {
|
||||
private scene: Phaser.Scene;
|
||||
private pinch!: any; // eslint-disable-line
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
this.scene = scene;
|
||||
this.pinch = new Pinch(scene);
|
||||
|
||||
this.pinch.on('pinch', (pinch:any) => { // eslint-disable-line
|
||||
let newZoom = this.scene.cameras.main.zoom * pinch.scaleFactor;
|
||||
if (newZoom < 0.25) {
|
||||
newZoom = 0.25;
|
||||
} else if(newZoom > 2) {
|
||||
newZoom = 2;
|
||||
}
|
||||
this.scene.cameras.main.setZoom(newZoom);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
import { Direction, IVirtualJoystick } from "../../types";
|
||||
import { Direction } from "../../types";
|
||||
import {GameScene} from "../Game/GameScene";
|
||||
const {
|
||||
default: VirtualJoystick,
|
||||
} = require("phaser3-rex-plugins/plugins/virtualjoystick.js");
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {MobileJoystick} from "../Components/MobileJoystick";
|
||||
|
||||
interface UserInputManagerDatum {
|
||||
keyInstance: Phaser.Input.Keyboard.Key;
|
||||
|
@ -20,6 +19,7 @@ export enum UserInputEvent {
|
|||
JoystickMove,
|
||||
}
|
||||
|
||||
|
||||
//we cannot use a map structure so we have to create a replacment
|
||||
export class ActiveEventList {
|
||||
private eventMap : Map<UserInputEvent, boolean> = new Map<UserInputEvent, boolean>();
|
||||
|
@ -44,17 +44,23 @@ export class UserInputManager {
|
|||
private Scene: GameScene;
|
||||
private isInputDisabled : boolean;
|
||||
|
||||
private joystick : IVirtualJoystick;
|
||||
private joystick!: MobileJoystick;
|
||||
private joystickEvents = new ActiveEventList();
|
||||
private joystickForceThreshold = 60;
|
||||
private joystickForceAccuX = 0;
|
||||
private joystickForceAccuY = 0;
|
||||
|
||||
constructor(Scene: GameScene, virtualJoystick: IVirtualJoystick) {
|
||||
constructor(Scene: GameScene) {
|
||||
this.Scene = Scene;
|
||||
this.isInputDisabled = false;
|
||||
this.initKeyBoardEvent();
|
||||
this.joystick = virtualJoystick;
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
this.initVirtualJoystick();
|
||||
}
|
||||
}
|
||||
|
||||
initVirtualJoystick() {
|
||||
this.joystick = new MobileJoystick(this.Scene);
|
||||
this.joystick.on("update", () => {
|
||||
this.joystickForceAccuX = this.joystick.forceX ? this.joystickForceAccuX : 0;
|
||||
this.joystickForceAccuY = this.joystick.forceY ? this.joystickForceAccuY : 0;
|
||||
|
@ -62,18 +68,18 @@ export class UserInputManager {
|
|||
for (const name in cursorKeys) {
|
||||
const key = cursorKeys[name as Direction];
|
||||
switch (name) {
|
||||
case "up":
|
||||
this.joystickEvents.set(UserInputEvent.MoveUp, key.isDown);
|
||||
break;
|
||||
case "left":
|
||||
this.joystickEvents.set(UserInputEvent.MoveLeft, key.isDown);
|
||||
break;
|
||||
case "down":
|
||||
this.joystickEvents.set(UserInputEvent.MoveDown, key.isDown);
|
||||
break;
|
||||
case "right":
|
||||
this.joystickEvents.set(UserInputEvent.MoveRight, key.isDown);
|
||||
break;
|
||||
case "up":
|
||||
this.joystickEvents.set(UserInputEvent.MoveUp, key.isDown);
|
||||
break;
|
||||
case "left":
|
||||
this.joystickEvents.set(UserInputEvent.MoveLeft, key.isDown);
|
||||
break;
|
||||
case "down":
|
||||
this.joystickEvents.set(UserInputEvent.MoveDown, key.isDown);
|
||||
break;
|
||||
case "right":
|
||||
this.joystickEvents.set(UserInputEvent.MoveRight, key.isDown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -105,6 +111,7 @@ export class UserInputManager {
|
|||
this.Scene.input.keyboard.removeAllListeners();
|
||||
}
|
||||
|
||||
//todo: should we also disable the joystick?
|
||||
disableControls(){
|
||||
this.Scene.input.keyboard.removeAllKeys();
|
||||
this.isInputDisabled = true;
|
||||
|
|
16
front/src/Touch/TouchScreenManager.ts
Normal file
16
front/src/Touch/TouchScreenManager.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
class TouchScreenManager {
|
||||
|
||||
readonly supportTouchScreen:boolean;
|
||||
|
||||
constructor() {
|
||||
this.supportTouchScreen = this.detectTouchscreen();
|
||||
}
|
||||
|
||||
//found here: https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript#4819886
|
||||
detectTouchscreen(): boolean {
|
||||
return (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
|
||||
}
|
||||
}
|
||||
|
||||
export const touchScreenManager = new TouchScreenManager();
|
|
@ -315,12 +315,17 @@ export class MediaManager {
|
|||
}
|
||||
|
||||
private enableScreenSharing() {
|
||||
this.monitorClose.style.display = "none";
|
||||
this.monitor.style.display = "block";
|
||||
this.monitorBtn.classList.add("enabled");
|
||||
this.getScreenMedia().then((stream) => {
|
||||
this.triggerStartedScreenSharingCallbacks(stream);
|
||||
this.monitorClose.style.display = "none";
|
||||
this.monitor.style.display = "block";
|
||||
this.monitorBtn.classList.add("enabled");
|
||||
}, () => {
|
||||
this.monitorClose.style.display = "block";
|
||||
this.monitor.style.display = "none";
|
||||
this.monitorBtn.classList.remove("enabled");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private disableScreenSharing() {
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'phaser';
|
|||
import GameConfig = Phaser.Types.Core.GameConfig;
|
||||
import "../dist/resources/style/index.scss";
|
||||
|
||||
import {DEBUG_MODE, JITSI_URL, RESOLUTION} from "./Enum/EnvironmentVariable";
|
||||
import {DEBUG_MODE, isMobile, RESOLUTION} from "./Enum/EnvironmentVariable";
|
||||
import {LoginScene} from "./Phaser/Login/LoginScene";
|
||||
import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene";
|
||||
import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene";
|
||||
|
@ -17,7 +17,7 @@ import {HelpCameraSettingsScene} from "./Phaser/Menu/HelpCameraSettingsScene";
|
|||
import {localUserStore} from "./Connexion/LocalUserStore";
|
||||
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
|
||||
import {iframeListener} from "./Api/IframeListener";
|
||||
import {discussionManager} from "./WebRtc/DiscussionManager";
|
||||
import { SelectCharacterMobileScene } from './Phaser/Login/SelectCharacterMobileScene';
|
||||
|
||||
const {width, height} = coWebsiteManager.getGameSize();
|
||||
|
||||
|
@ -34,7 +34,7 @@ const fps : Phaser.Types.Core.FPSConfig = {
|
|||
/**
|
||||
* Use setTimeout instead of requestAnimationFrame to run the game loop.
|
||||
*/
|
||||
forceSetTimeOut: true,
|
||||
forceSetTimeOut: false,
|
||||
/**
|
||||
* Calculate the average frame delta from this many consecutive frame intervals.
|
||||
*/
|
||||
|
@ -68,14 +68,22 @@ switch (phaserMode) {
|
|||
throw new Error('phaserMode parameter must be one of "auto", "canvas" or "webgl"');
|
||||
}
|
||||
|
||||
|
||||
const config: GameConfig = {
|
||||
type: mode,
|
||||
title: "WorkAdventure",
|
||||
width: width / RESOLUTION,
|
||||
height: height / RESOLUTION,
|
||||
parent: "game",
|
||||
scene: [EntryScene, LoginScene, SelectCharacterScene, SelectCompanionScene, EnableCameraScene, ReconnectingScene, ErrorScene, CustomizeScene, MenuScene, HelpCameraSettingsScene],
|
||||
scene: [EntryScene,
|
||||
LoginScene,
|
||||
isMobile() ? SelectCharacterMobileScene : SelectCharacterScene,
|
||||
SelectCompanionScene,
|
||||
EnableCameraScene,
|
||||
ReconnectingScene,
|
||||
ErrorScene,
|
||||
CustomizeScene,
|
||||
MenuScene,
|
||||
HelpCameraSettingsScene],
|
||||
zoom: RESOLUTION,
|
||||
fps: fps,
|
||||
dom: {
|
||||
|
|
12
front/src/rex-plugins.d.ts
vendored
Normal file
12
front/src/rex-plugins.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
declare module 'phaser3-rex-plugins/plugins/virtualjoystick.js' {
|
||||
const content: any; // eslint-disable-line
|
||||
export default content;
|
||||
}
|
||||
declare module 'phaser3-rex-plugins/plugins/gestures-plugin.js' {
|
||||
const content: any; // eslint-disable-line
|
||||
export default content;
|
||||
}
|
||||
declare module 'phaser3-rex-plugins/plugins/gestures.js' {
|
||||
export const Pinch: any; // eslint-disable-line
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue