diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts index e900a059..45621e1c 100644 --- a/front/src/Phaser/Game/CameraManager.ts +++ b/front/src/Phaser/Game/CameraManager.ts @@ -1,16 +1,26 @@ import { Easing } from '../../types'; import { HtmlUtils } from '../../WebRtc/HtmlUtils'; import type { Box } from '../../WebRtc/LayoutManager'; +import type { Player } from '../Player/Player'; import type { WaScaleManager } from '../Services/WaScaleManager'; import type { GameScene } from './GameScene'; +export enum CameraMode { + Free = 'Free', + Follow = 'Follow', + Focus = 'Focus', +} + export class CameraManager extends Phaser.Events.EventEmitter { private scene: GameScene; private camera: Phaser.Cameras.Scene2D.Camera; + private cameraBounds: { x: number, y: number }; private waScaleManager: WaScaleManager; - private cameraBounds: { x: number, y: number }; + private cameraMode: CameraMode = CameraMode.Free; + + private restoreZoomTween?: Phaser.Tweens.Tween; constructor(scene: GameScene, cameraBounds: { x: number, y: number }, waScaleManager: WaScaleManager) { super(); @@ -28,11 +38,13 @@ export class CameraManager extends Phaser.Events.EventEmitter { return this.camera; } - public changeCameraFocus( + public enterFocusMode( focusOn: { x: number, y: number, width: number, height: number }, duration: number = 1000, ): void { + this.setCameraMode(CameraMode.Focus); this.waScaleManager.saveZoom(); - this.waScaleManager.lockZoomingViaPlayerInput(); + + this.restoreZoomTween?.stop(); const maxZoomModifier = 2.84; // How to get max zoom value? const currentZoomModifier = this.waScaleManager.zoomModifier; const zoomModifierChange = maxZoomModifier - currentZoomModifier; @@ -46,9 +58,15 @@ export class CameraManager extends Phaser.Events.EventEmitter { }); } + public leaveFocusMode(player: Player): void { + // We are forcing camera.pan to kill previous pan animation on EnterFocusMode + this.camera.pan(player.x, player.y, 1, Easing.SineEaseOut, true); + this.startFollow(player); + this.restoreZoom(); + } + public startFollow(target: object | Phaser.GameObjects.GameObject): void { - this.waScaleManager.lockZoomingViaPlayerInput(false); - this.waScaleManager.restoreZoom(); + this.setCameraMode(CameraMode.Follow); this.camera.startFollow(target, true); } @@ -69,6 +87,30 @@ export class CameraManager extends Phaser.Events.EventEmitter { ); } + public isCameraLocked(): boolean { + return this.cameraMode === CameraMode.Focus; + } + + private setCameraMode(mode: CameraMode): void { + if (this.cameraMode === mode) { + return; + } + this.cameraMode = mode; + } + + private restoreZoom(): void { + this.restoreZoomTween?.stop(); + this.restoreZoomTween = this.scene.tweens.addCounter({ + from: this.waScaleManager.zoomModifier, + to: this.waScaleManager.getSaveZoom(), + duration: 1000, + ease: Easing.SineEaseOut, + onUpdate: (tween: Phaser.Tweens.Tween) => { + this.waScaleManager.zoomModifier = tween.getValue(); + } + }); + } + private initCamera() { this.camera = this.scene.cameras.main; this.camera.setBounds(0, 0, this.cameraBounds.x, this.cameraBounds.y); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 4afd0383..90297272 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -788,7 +788,7 @@ export class GameScene extends DirtyScene { for (const zone of zones) { for (const property of zone.properties ?? []) { if (property.name === 'focusable' && property.value === true) { - this.cameraManager.changeCameraFocus(zone); + this.cameraManager.enterFocusMode(zone); break; } } @@ -802,7 +802,7 @@ export class GameScene extends DirtyScene { for (const zone of zones) { for (const property of zone.properties ?? []) { if (property.name === 'focusable' && property.value === true) { - this.cameraManager.startFollow(this.CurrentPlayer); + this.cameraManager.leaveFocusMode(this.CurrentPlayer); break; } } @@ -1954,7 +1954,7 @@ ${escapedMessage} } zoomByFactor(zoomFactor: number) { - if (waScaleManager.isZoomingViaPlayerInputLocked()) { + if (this.cameraManager.isCameraLocked()) { return; } waScaleManager.zoomModifier *= zoomFactor; diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index f8aeba2d..ee2ca9ea 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -12,8 +12,6 @@ export class WaScaleManager { private actualZoom: number = 1; private _saveZoom: number = 1; - private zoomingViaPlayerInputLocked: boolean = false; - public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) { this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber); } @@ -23,14 +21,6 @@ export class WaScaleManager { this.game = game; } - public isZoomingViaPlayerInputLocked(): boolean { - return this.zoomingViaPlayerInputLocked; - } - - public lockZoomingViaPlayerInput(lock: boolean = true): void { - this.zoomingViaPlayerInputLocked = lock; - } - public applyNewSize() { const { width, height } = coWebsiteManager.getGameSize(); @@ -82,6 +72,10 @@ export class WaScaleManager { this._saveZoom = this.hdpiManager.zoomModifier; } + public getSaveZoom(): number { + return this._saveZoom; + } + public restoreZoom(): void { this.hdpiManager.zoomModifier = this._saveZoom; this.applyNewSize();