diff --git a/front/dist/index.html b/front/dist/index.html index a680c59a..92a7bf3c 100644 --- a/front/dist/index.html +++ b/front/dist/index.html @@ -39,7 +39,53 @@ WorkAdventure -
+
+
+
+
+ +
+ + + + +
+
+ +
+
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+
+ -->
diff --git a/front/dist/resources/objects/layout_modes.png b/front/dist/resources/objects/layout_modes.png new file mode 100644 index 00000000..abd9adaf Binary files /dev/null and b/front/dist/resources/objects/layout_modes.png differ diff --git a/front/dist/resources/style/style.css b/front/dist/resources/style/style.css index 5f0e1cab..30e099ef 100644 --- a/front/dist/resources/style/style.css +++ b/front/dist/resources/style/style.css @@ -23,34 +23,12 @@ body .message-info.info{ body .message-info.warning{ background: #ffa500d6; } -video{ - -webkit-transform: scaleX(-1); - transform: scaleX(-1); -} -.webrtc{ - display: none; - position: absolute; - right: 0px; - height: 100%; - width: 300px; -} -.webrtc.active{ - display: block; -} - -.webrtc, .activeCam{} -.activeCam .video-container{ - position: absolute; - height: 25%; - top: 10px; - margin: 5px; - right: -100px; +.video-container{ + position: relative; transition: all 0.2s ease; - border-color: black; - border-style: solid; - border-width: 0.2px; + background-color: #00000099; } -.activeCam .video-container i{ +.video-container i{ position: absolute; width: 100px; height: 65px; @@ -63,10 +41,10 @@ video{ font-size: 28px; color: white; } -.activeCam .video-container img.active{ +.video-container img.active{ display: block; } -.activeCam .video-container img{ +.video-container img{ position: absolute; display: none; width: 15px; @@ -78,36 +56,29 @@ video{ padding: 10px; z-index: 2; } -.activeCam .video-container video{ +.video-container video{ height: 100%; } -.webrtc:hover .activeCam .video-container{ - right: 10px; -} -.activeCam .video-container#div-myCamVideo{ +.video-container#div-myCamVideo{ border: none; } -.activeCam .video-container video#myCamVideo{ - width: 200px; - height: 113px; + +#div-myCamVideo { + position: absolute; + right: 0; + bottom: 0; } -/*CSS size for 2 - 3 elements*/ -.activeCam .video-container:nth-child(1){ - /*this is for camera of user*/ - top: 75%; -} -.activeCam .video-container:nth-child(2){ - top: 0%; -} -.activeCam .video-container:nth-child(3){ - top: 25%; -} -.activeCam .video-container:nth-child(4) { - top: 50%; +video#myCamVideo{ + width: 15vw; + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + /*width: 200px;*/ + /*height: 113px;*/ } + /*btn animation*/ .btn-cam-action div{ cursor: pointer; @@ -118,11 +89,11 @@ video{ background: #666; box-shadow: 2px 2px 24px #444; border-radius: 48px; - transform: translateY(12vw); + transform: translateY(12vh); transition-timing-function: ease-in-out; bottom: 20px; } -.webrtc:hover .btn-cam-action div{ +#activeCam:hover .btn-cam-action div{ transform: translateY(0); } .btn-cam-action div:hover{ @@ -237,3 +208,156 @@ video{ .webrtcsetup.active{ display: block; } + + +/* New layout */ +body { + margin: 0; + height: 100vh; + width: 100vw; +} +.main-container { + height: 100vh; + width: 100vw; + display: flex; + align-items: stretch; +} + +@media (min-aspect-ratio: 1/1) { + .main-container { + flex-direction: row; + } + + .game-overlay { + flex-direction: row; + } + + .sidebar { + flex-direction: column; + } + + .sidebar > div { + max-height: 21%; + } +} +@media (max-aspect-ratio: 1/1) { + .main-container { + flex-direction: column; + } + + .game-overlay { + flex-direction: column; + } + + .sidebar { + flex-direction: row; + align-items: flex-end; + } + + .sidebar > div { + max-width: 21%; + } +} + +.game { + flex-basis: 100%; + position: relative; /* Position relative is needed for the game-overlay. */ +} + +/* A potentially shared website could appear in an iframe in the cowebsite space. */ +.cowebsite { + flex-basis: 100%; + transition: flex-basis 0.5s; +} + +/*.cowebsite:hover { + flex-basis: 100%; +}*/ + +.cowebsite iframe { + width: 100%; + height: 100%; +} + + +.game-overlay { + display: none; + position: absolute; + width: 100%; + height: 100%; + /* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */ +} + +.game-overlay.active { + display: flex; +} + +.game-overlay video { + width: 100% +} + +.main-section { + flex: 0 0 75%; + display: flex; + justify-content: start; + /*align-items: flex-start;*/ + flex-wrap: wrap; +} + +.main-section > div { + margin: 5%; + flex-basis: 90%; + /*flex-shrink: 2;*/ +} + +.sidebar { + flex: 0 0 25%; + display: flex; +} + +.sidebar > div { + margin: 2%; +} + +/* Let's make sure videos are vertically centered if they need to be cropped */ +.media-container { + display: flex; + justify-content: center; + flex-direction: column; + overflow: hidden; +} + +.chat-mode { + display: flex; + width: 100%; + + flex-wrap: wrap; + align-items: flex-start; + + padding: 1%; +} + +.chat-mode div { + margin: 1%; + max-height: 96%; +} + +.chat-mode.one-col > div { + flex-basis: 98%; +} + +.chat-mode.two-col > div { + flex-basis: 48%; +} + +.chat-mode.three-col > div { + flex-basis: 31.333333%; +} + +.chat-mode.four-col > div { + flex-basis: 23%; +} + +.chat-mode > div:last-child { + flex-grow: 5; +} diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 487f3fb1..c4517545 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1,34 +1,33 @@ import {GameManager, gameManager, HasMovedEvent} from "./GameManager"; import { Connection, - GroupCreatedUpdatedMessageInterface, MessageUserJoined, + GroupCreatedUpdatedMessageInterface, + MessageUserJoined, MessageUserMovedInterface, - MessageUserPositionInterface, PointInterface, PositionInterface + MessageUserPositionInterface, + PointInterface, + PositionInterface } from "../../Connection"; import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player"; -import { DEBUG_MODE, ZOOM_LEVEL, POSITION_DELAY } from "../../Enum/EnvironmentVariable"; -import { - ITiledMap, - ITiledMapLayer, - ITiledMapLayerProperty, - ITiledTileSet -} from "../Map/ITiledMap"; +import {DEBUG_MODE, POSITION_DELAY, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable"; +import {ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledTileSet} from "../Map/ITiledMap"; import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character"; -import Texture = Phaser.Textures.Texture; -import Sprite = Phaser.GameObjects.Sprite; -import CanvasTexture = Phaser.Textures.CanvasTexture; import {AddPlayerInterface} from "./AddPlayerInterface"; import {PlayerAnimationNames} from "../Player/Animation"; import {PlayerMovement} from "./PlayerMovement"; import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator"; import {RemotePlayer} from "../Entity/RemotePlayer"; -import GameObject = Phaser.GameObjects.GameObject; -import { Queue } from 'queue-typescript'; -import {SimplePeer} from "../../WebRtc/SimplePeer"; +import {Queue} from 'queue-typescript'; +import {SimplePeer, UserSimplePeer} from "../../WebRtc/SimplePeer"; import {ReconnectingSceneName} from "../Reconnecting/ReconnectingScene"; -import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR; import {FourOFourSceneName} from "../Reconnecting/FourOFourScene"; -import {LAYERS, loadAllLayers} from "../Entity/body_character"; +import {loadAllLayers} from "../Entity/body_character"; +import {layoutManager, LayoutMode} from "../../WebRtc/LayoutManager"; +import Texture = Phaser.Textures.Texture; +import Sprite = Phaser.GameObjects.Sprite; +import CanvasTexture = Phaser.Textures.CanvasTexture; +import GameObject = Phaser.GameObjects.GameObject; +import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR; export enum Textures { @@ -107,6 +106,9 @@ export class GameScene extends Phaser.Scene { private PositionNextScene: Array> = new Array>(); private startLayerName: string|undefined; + private presentationModeSprite!: Sprite; + private chatModeSprite!: Sprite; + private repositionCallback!: (this: Window, ev: UIEvent) => void; static createFromUrl(mapUrlFile: string, instance: string, key: string|null = null): GameScene { const mapKey = GameScene.getMapKeyByUrl(mapUrlFile); @@ -159,6 +161,12 @@ export class GameScene extends Phaser.Scene { ); }); + this.load.spritesheet( + 'layout_modes', + 'resources/objects/layout_modes.png', + {frameWidth: 32, frameHeight: 32} + ); + loadAllLayers(this.load); this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); @@ -214,10 +222,24 @@ export class GameScene extends Phaser.Scene { this.scene.stop(this.scene.key); this.scene.remove(this.scene.key); + window.removeEventListener('resize', this.repositionCallback); }) // When connection is performed, let's connect SimplePeer this.simplePeer = new SimplePeer(this.connection); + const self = this; + this.simplePeer.registerPeerConnectionListener({ + onConnect(user: UserSimplePeer) { + self.presentationModeSprite.setVisible(true); + self.chatModeSprite.setVisible(true); + }, + onDisconnect(userId: string) { + if (self.simplePeer.getNbConnections() === 0) { + self.presentationModeSprite.setVisible(false); + self.chatModeSprite.setVisible(false); + } + } + }) this.scene.wake(); this.scene.sleep(ReconnectingSceneName); @@ -364,6 +386,41 @@ export class GameScene extends Phaser.Scene { } }, 500); } + + this.presentationModeSprite = this.add.sprite(2, this.game.renderer.height - 2, 'layout_modes', 0); + this.presentationModeSprite.setScrollFactor(0, 0); + this.presentationModeSprite.setOrigin(0, 1); + this.presentationModeSprite.setInteractive(); + this.presentationModeSprite.setVisible(false); + this.presentationModeSprite.on('pointerup', this.switchLayoutMode.bind(this)); + this.chatModeSprite = this.add.sprite(36, this.game.renderer.height - 2, 'layout_modes', 3); + this.chatModeSprite.setScrollFactor(0, 0); + this.chatModeSprite.setOrigin(0, 1); + this.chatModeSprite.setInteractive(); + this.chatModeSprite.setVisible(false); + this.chatModeSprite.on('pointerup', this.switchLayoutMode.bind(this)); + + // FIXME: change this to use the UserInputManager class for input + this.input.keyboard.on('keyup-' + 'M', () => { + this.switchLayoutMode(); + }); + + this.repositionCallback = this.reposition.bind(this); + window.addEventListener('resize', this.repositionCallback); + this.reposition(); + } + + private switchLayoutMode(): void { + const mode = layoutManager.getLayoutMode(); + if (mode === LayoutMode.Presentation) { + layoutManager.switchLayoutMode(LayoutMode.VideoChat); + this.presentationModeSprite.setFrame(1); + this.chatModeSprite.setFrame(2); + } else { + layoutManager.switchLayoutMode(LayoutMode.Presentation); + this.presentationModeSprite.setFrame(0); + this.chatModeSprite.setFrame(3); + } } private getExitSceneUrl(layer: ITiledMapLayer): string|undefined { @@ -625,6 +682,7 @@ export class GameScene extends Phaser.Scene { this.simplePeer.unregister(); this.scene.stop(); this.scene.remove(this.scene.key); + window.removeEventListener('resize', this.repositionCallback); this.scene.start(nextSceneKey.key, { startLayerName: nextSceneKey.hash }); @@ -812,4 +870,9 @@ export class GameScene extends Phaser.Scene { const endPos = mapUrlStart.indexOf(".json"); return mapUrlStart.substring(startPos, endPos); } + + private reposition(): void { + this.presentationModeSprite.setY(this.game.renderer.height - 2); + this.chatModeSprite.setY(this.game.renderer.height - 2); + } } diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts new file mode 100644 index 00000000..0150760c --- /dev/null +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -0,0 +1,56 @@ +import {HtmlUtils} from "./HtmlUtils"; + +export type CoWebsiteStateChangedCallback = () => void; + +export class CoWebsiteManager { + + private static observers = new Array(); + + public static loadCoWebsite(url: string): void { + const cowebsiteDiv = HtmlUtils.getElementByIdOrFail("cowebsite"); + cowebsiteDiv.innerHTML = ''; + + const iframe = document.createElement('iframe'); + iframe.id = 'cowebsite-iframe'; + iframe.src = url; + cowebsiteDiv.appendChild(iframe); + CoWebsiteManager.fire(); + } + + public static closeCoWebsite(): void { + const cowebsiteDiv = HtmlUtils.getElementByIdOrFail("cowebsite"); + cowebsiteDiv.innerHTML = ''; + CoWebsiteManager.fire(); + } + + public static getGameSize(): {width: number, height: number} { + const iframe = document.getElementById('cowebsite-iframe'); + if (iframe === null) { + return { + width: window.innerWidth, + height: window.innerHeight + } + } + if (window.innerWidth >= window.innerHeight) { + return { + width: window.innerWidth / 2, + height: window.innerHeight + } + } else { + return { + width: window.innerWidth, + height: window.innerHeight / 2 + } + } + } + + public static onStateChange(observer: CoWebsiteStateChangedCallback) { + CoWebsiteManager.observers.push(observer); + } + + private static fire(): void { + for (const callback of CoWebsiteManager.observers) { + callback(); + } + } +} diff --git a/front/src/WebRtc/HtmlUtils.ts b/front/src/WebRtc/HtmlUtils.ts new file mode 100644 index 00000000..c2e6ff6d --- /dev/null +++ b/front/src/WebRtc/HtmlUtils.ts @@ -0,0 +1,10 @@ +export class HtmlUtils { + public static getElementByIdOrFail(id: string): T { + const elem = document.getElementById(id); + if (elem === null) { + throw new Error("Cannot find HTML element with id '"+id+"'"); + } + // FIXME: does not check the type of the returned type + return elem as T; + } +} diff --git a/front/src/WebRtc/LayoutManager.ts b/front/src/WebRtc/LayoutManager.ts new file mode 100644 index 00000000..6695fe7f --- /dev/null +++ b/front/src/WebRtc/LayoutManager.ts @@ -0,0 +1,135 @@ +import {HtmlUtils} from "./HtmlUtils"; + +export enum LayoutMode { + // All videos are displayed on the right side of the screen. If there is a screen sharing, it is displayed in the middle. + Presentation = "Presentation", + // Videos take the whole page. + VideoChat = "VideoChat", +} + +export enum DivImportance { + // For screen sharing + Important = "Important", + // For normal video + Normal = "Normal", +} + +/** + * This class is in charge of the video-conference layout. + * It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode. + */ +class LayoutManager { + private mode: LayoutMode = LayoutMode.Presentation; + + private importantDivs: Map = new Map(); + private normalDivs: Map = new Map(); + + public add(importance: DivImportance, userId: string, html: string): void { + const div = document.createElement('div'); + div.innerHTML = html; + div.id = "user-"+userId; + div.className = "media-container" + + if (importance === DivImportance.Important) { + this.importantDivs.set(userId, div); + + // If this is the first video with high importance, let's switch mode automatically. + if (this.importantDivs.size === 1 && this.mode === LayoutMode.VideoChat) { + this.switchLayoutMode(LayoutMode.Presentation); + } + } else if (importance === DivImportance.Normal) { + this.normalDivs.set(userId, div); + } else { + throw new Error('Unexpected importance'); + } + + this.positionDiv(div, importance); + this.adjustVideoChatClass(); + } + + private positionDiv(elem: HTMLDivElement, importance: DivImportance): void { + if (this.mode === LayoutMode.VideoChat) { + const chatModeDiv = HtmlUtils.getElementByIdOrFail('chat-mode'); + chatModeDiv.appendChild(elem); + } else { + if (importance === DivImportance.Important) { + const mainSectionDiv = HtmlUtils.getElementByIdOrFail('main-section'); + mainSectionDiv.appendChild(elem); + } else if (importance === DivImportance.Normal) { + const sideBarDiv = HtmlUtils.getElementByIdOrFail('sidebar'); + sideBarDiv.appendChild(elem); + } + } + } + + /** + * Removes the DIV matching userId. + */ + public remove(userId: string): void { + console.log('Removing video for userID '+userId+'.'); + let div = this.importantDivs.get(userId); + if (div !== undefined) { + div.remove(); + this.importantDivs.delete(userId); + this.adjustVideoChatClass(); + return; + } + + div = this.normalDivs.get(userId); + if (div !== undefined) { + div.remove(); + this.normalDivs.delete(userId); + this.adjustVideoChatClass(); + return; + } + + console.log('Cannot remove userID '+userId+'. Already removed?'); + //throw new Error('Could not find user ID "'+userId+'"'); + } + + private adjustVideoChatClass(): void { + const chatModeDiv = HtmlUtils.getElementByIdOrFail('chat-mode'); + chatModeDiv.classList.remove('one-col', 'two-col', 'three-col', 'four-col'); + + const nbUsers = this.importantDivs.size + this.normalDivs.size; + + if (nbUsers <= 1) { + chatModeDiv.classList.add('one-col'); + } else if (nbUsers <= 4) { + chatModeDiv.classList.add('two-col'); + } else if (nbUsers <= 9) { + chatModeDiv.classList.add('three-col'); + } else { + chatModeDiv.classList.add('four-col'); + } + } + + public switchLayoutMode(layoutMode: LayoutMode) { + this.mode = layoutMode; + + if (layoutMode === LayoutMode.Presentation) { + HtmlUtils.getElementByIdOrFail('sidebar').style.display = 'flex'; + HtmlUtils.getElementByIdOrFail('main-section').style.display = 'flex'; + HtmlUtils.getElementByIdOrFail('chat-mode').style.display = 'none'; + } else { + HtmlUtils.getElementByIdOrFail('sidebar').style.display = 'none'; + HtmlUtils.getElementByIdOrFail('main-section').style.display = 'none'; + HtmlUtils.getElementByIdOrFail('chat-mode').style.display = 'flex'; + } + + for (const div of this.importantDivs.values()) { + this.positionDiv(div, DivImportance.Important); + } + for (const div of this.normalDivs.values()) { + this.positionDiv(div, DivImportance.Normal); + } + } + + public getLayoutMode(): LayoutMode { + return this.mode; + } +} + +const layoutManager = new LayoutManager(); + +export { layoutManager }; diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts index e69850a2..39a61738 100644 --- a/front/src/WebRtc/MediaManager.ts +++ b/front/src/WebRtc/MediaManager.ts @@ -1,3 +1,5 @@ +import {DivImportance, layoutManager} from "./LayoutManager"; + const videoConstraint: boolean|MediaTrackConstraints = { width: { ideal: 1280 }, height: { ideal: 720 }, @@ -73,8 +75,8 @@ export class MediaManager { } activeVisio(){ - const webRtc = this.getElementByIdOrFail('webRtc'); - webRtc.classList.add('active'); + const gameOverlay = this.getElementByIdOrFail('game-overlay'); + gameOverlay.classList.add('active'); } enabledCamera() { @@ -184,18 +186,22 @@ export class MediaManager { */ addActiveVideo(userId : string, userName: string = ""){ this.webrtcInAudio.play(); - const elementRemoteVideo = this.getElementByIdOrFail("activeCam"); + userName = userName.toUpperCase(); const color = this.getColorByString(userName); - elementRemoteVideo.insertAdjacentHTML('beforeend', ` -
+ + const html = ` +
- ${userName} + ${userName}
- `); + `; + + layoutManager.add(DivImportance.Normal, userId, html); + this.remoteVideo.set(userId, this.getElementByIdOrFail(userId)); } @@ -232,11 +238,10 @@ export class MediaManager { if (element) { element.style.opacity = "0"; } - element = document.getElementById(`div-${userId}`); - if (!element) { - return; + element = document.getElementById(`name-${userId}`); + if (element) { + element.style.display = "block"; } - element.style.borderStyle = "solid"; } /** @@ -248,11 +253,10 @@ export class MediaManager { if(element){ element.style.opacity = "1"; } - element = document.getElementById(`div-${userId}`); - if(!element){ - return; + element = document.getElementById(`name-${userId}`); + if(element){ + element.style.display = "none"; } - element.style.borderStyle = "none"; } /** @@ -274,11 +278,7 @@ export class MediaManager { * @param userId */ removeActiveVideo(userId : string){ - const element = document.getElementById(`div-${userId}`); - if(!element){ - return; - } - element.remove(); + layoutManager.remove(userId); this.remoteVideo.delete(userId); } diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 553c9307..fdc2d0c2 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -14,6 +14,12 @@ export interface UserSimplePeer{ initiator?: boolean; } +export interface PeerConnectionListener { + onConnect(user: UserSimplePeer): void; + + onDisconnect(userId: string): void; +} + /** * This class manages connections to all the peers in the same group as me. */ @@ -24,6 +30,7 @@ export class SimplePeer { private PeerConnectionArray: Map = new Map(); private readonly updateLocalStreamCallback: (media: MediaStream) => void; + private readonly peerConnectionListeners: Array = new Array(); constructor(Connection: Connection, WebRtcRoomId: string = "test-webrtc") { this.Connection = Connection; @@ -34,6 +41,14 @@ export class SimplePeer { this.initialise(); } + public registerPeerConnectionListener(peerConnectionListener: PeerConnectionListener) { + this.peerConnectionListeners.push(peerConnectionListener); + } + + public getNbConnections(): number { + return this.PeerConnectionArray.size; + } + /** * permit to listen when user could start visio */ @@ -182,6 +197,10 @@ export class SimplePeer { }); this.addMedia(user.userId); + + for (const peerConnectionListener of this.peerConnectionListeners) { + peerConnectionListener.onConnect(user); + } } /** @@ -203,6 +222,9 @@ export class SimplePeer { peer.destroy(); this.PeerConnectionArray.delete(userId) //console.log('Nb users in peerConnectionArray '+this.PeerConnectionArray.size); + for (const peerConnectionListener of this.peerConnectionListeners) { + peerConnectionListener.onDisconnect(userId); + } } catch (err) { console.error("closeConnection", err) } diff --git a/front/src/index.ts b/front/src/index.ts index 7634351f..75ad0fe6 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -4,16 +4,21 @@ import {DEBUG_MODE, RESOLUTION} from "./Enum/EnvironmentVariable"; import {cypressAsserter} from "./Cypress/CypressAsserter"; import {LoginScene} from "./Phaser/Login/LoginScene"; import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene"; -import {gameManager} from "./Phaser/Game/GameManager"; import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene"; import {EnableCameraScene} from "./Phaser/Login/EnableCameraScene"; import {FourOFourScene} from "./Phaser/Reconnecting/FourOFourScene"; import {CustomizeScene} from "./Phaser/Login/CustomizeScene"; +import {HtmlUtils} from "./WebRtc/HtmlUtils"; +import {CoWebsiteManager} from "./WebRtc/CoWebsiteManager"; + +//CoWebsiteManager.loadCoWebsite('https://thecodingmachine.com'); + +const {width, height} = CoWebsiteManager.getGameSize(); const config: GameConfig = { - title: "Office game", - width: window.innerWidth / RESOLUTION, - height: window.innerHeight / RESOLUTION, + title: "WorkAdventure", + width: width / RESOLUTION, + height: height / RESOLUTION, parent: "game", scene: [LoginScene, SelectCharacterScene, EnableCameraScene, ReconnectingScene, FourOFourScene, CustomizeScene], zoom: RESOLUTION, @@ -30,5 +35,12 @@ cypressAsserter.gameStarted(); const game = new Phaser.Game(config); window.addEventListener('resize', function (event) { - game.scale.resize(window.innerWidth / RESOLUTION, window.innerHeight / RESOLUTION); + const {width, height} = CoWebsiteManager.getGameSize(); + + game.scale.resize(width / RESOLUTION, height / RESOLUTION); +}); +CoWebsiteManager.onStateChange(() => { + const {width, height} = CoWebsiteManager.getGameSize(); + + game.scale.resize(width / RESOLUTION, height / RESOLUTION); });