subtle changes in CameraManager in order to distinguish between setPosition and focusOn

This commit is contained in:
Hanusiak Piotr 2021-12-16 14:31:26 +01:00
parent 5f26a39a5d
commit 4ebc55a429
2 changed files with 73 additions and 24 deletions

View File

@ -1,13 +1,22 @@
import { Easing } from "../../types"; import { Easing } from "../../types";
import { HtmlUtils } from "../../WebRtc/HtmlUtils"; import { HtmlUtils } from "../../WebRtc/HtmlUtils";
import type { Box } from "../../WebRtc/LayoutManager"; import type { Box } from "../../WebRtc/LayoutManager";
import type { Player } from "../Player/Player"; import { hasMovedEventName, Player } from "../Player/Player";
import type { WaScaleManager } from "../Services/WaScaleManager"; import type { WaScaleManager } from "../Services/WaScaleManager";
import type { GameScene } from "./GameScene"; import type { GameScene } from "./GameScene";
export enum CameraMode { export enum CameraMode {
Free = "Free", /**
* Camera looks at certain point but is not locked and will start following the player on his movement
*/
Positioned = "Positioned",
/**
* Camera is actively following the player
*/
Follow = "Follow", Follow = "Follow",
/**
* Camera is focusing on certain point and will not break this focus even on player movement
*/
Focus = "Focus", Focus = "Focus",
} }
@ -17,12 +26,12 @@ export class CameraManager extends Phaser.Events.EventEmitter {
private cameraBounds: { x: number; y: number }; private cameraBounds: { x: number; y: number };
private waScaleManager: WaScaleManager; private waScaleManager: WaScaleManager;
private cameraMode: CameraMode = CameraMode.Free; private cameraMode: CameraMode = CameraMode.Positioned;
private restoreZoomTween?: Phaser.Tweens.Tween; private restoreZoomTween?: Phaser.Tweens.Tween;
private startFollowTween?: Phaser.Tweens.Tween; private startFollowTween?: Phaser.Tweens.Tween;
private cameraFollowTarget?: { x: number; y: number }; private playerToFollow?: Player;
constructor(scene: GameScene, cameraBounds: { x: number; y: number }, waScaleManager: WaScaleManager) { constructor(scene: GameScene, cameraBounds: { x: number; y: number }, waScaleManager: WaScaleManager) {
super(); super();
@ -47,6 +56,51 @@ export class CameraManager extends Phaser.Events.EventEmitter {
return this.camera; return this.camera;
} }
/**
* Set camera view to specific destination without changing current camera mode. Won't work if camera mode is set to Focus.
* @param setTo Viewport on which the camera should set the position
* @param duration Time for the transition im MS. If set to 0, transition will occur immediately
*/
public setPosition(setTo: { x: number; y: number; width: number; height: number }, duration: number = 1000): void {
if (this.cameraMode === CameraMode.Focus) {
return;
}
this.setCameraMode(CameraMode.Positioned);
const currentZoomModifier = this.waScaleManager.zoomModifier;
const zoomModifierChange = this.getZoomModifierChange(setTo.width, setTo.height);
this.camera.stopFollow();
this.camera.pan(
setTo.x + setTo.width * 0.5,
setTo.y + setTo.height * 0.5,
duration,
Easing.SineEaseOut,
true,
(camera, progress, x, y) => {
if (this.cameraMode === CameraMode.Positioned) {
this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange;
}
if (progress === 1) {
this.playerToFollow?.once(hasMovedEventName, () => {
if (this.playerToFollow) {
this.startFollowPlayer(this.playerToFollow, duration);
}
});
}
}
);
}
private getZoomModifierChange(width: number, height: number): number {
const targetZoomModifier = this.waScaleManager.getTargetZoomModifierFor(width, height);
const currentZoomModifier = this.waScaleManager.zoomModifier;
return targetZoomModifier - currentZoomModifier;
}
/**
* Set camera to focus mode. As long as the camera is in the Focus mode, its view cannot be changed.
* @param setTo Viewport on which the camera should focus on
* @param duration Time for the transition im MS. If set to 0, transition will occur immediately
*/
public enterFocusMode( public enterFocusMode(
focusOn: { x: number; y: number; width: number; height: number }, focusOn: { x: number; y: number; width: number; height: number },
margin: number = 0, margin: number = 0,
@ -59,14 +113,10 @@ export class CameraManager extends Phaser.Events.EventEmitter {
this.restoreZoomTween?.stop(); this.restoreZoomTween?.stop();
this.startFollowTween?.stop(); this.startFollowTween?.stop();
const marginMult = 1 + margin; const marginMult = 1 + margin;
const targetZoomModifier = this.waScaleManager.getTargetZoomModifierFor(
focusOn.width * marginMult,
focusOn.height * marginMult
);
const currentZoomModifier = this.waScaleManager.zoomModifier; const currentZoomModifier = this.waScaleManager.zoomModifier;
const zoomModifierChange = targetZoomModifier - currentZoomModifier; const zoomModifierChange = this.getZoomModifierChange(focusOn.width * marginMult, focusOn.height * marginMult);
this.camera.stopFollow(); this.camera.stopFollow();
this.cameraFollowTarget = undefined; this.playerToFollow = undefined;
this.camera.pan( this.camera.pan(
focusOn.x + focusOn.width * 0.5 * marginMult, focusOn.x + focusOn.width * 0.5 * marginMult,
focusOn.y + focusOn.height * 0.5 * marginMult, focusOn.y + focusOn.height * 0.5 * marginMult,
@ -81,15 +131,15 @@ export class CameraManager extends Phaser.Events.EventEmitter {
public leaveFocusMode(player: Player, duration: number = 1000): void { public leaveFocusMode(player: Player, duration: number = 1000): void {
this.waScaleManager.setFocusTarget(); this.waScaleManager.setFocusTarget();
this.startFollow(player, duration); this.startFollowPlayer(player, duration);
this.restoreZoom(duration); this.restoreZoom(duration);
} }
public startFollow(target: object | Phaser.GameObjects.GameObject, duration: number = 0): void { public startFollowPlayer(player: Player, duration: number = 0): void {
this.cameraFollowTarget = target as { x: number; y: number }; this.playerToFollow = player;
this.setCameraMode(CameraMode.Follow); this.setCameraMode(CameraMode.Follow);
if (duration === 0) { if (duration === 0) {
this.camera.startFollow(target, true); this.camera.startFollow(player, true);
return; return;
} }
const oldPos = { x: this.camera.scrollX, y: this.camera.scrollY }; const oldPos = { x: this.camera.scrollX, y: this.camera.scrollY };
@ -99,17 +149,17 @@ export class CameraManager extends Phaser.Events.EventEmitter {
duration, duration,
ease: Easing.SineEaseOut, ease: Easing.SineEaseOut,
onUpdate: (tween: Phaser.Tweens.Tween) => { onUpdate: (tween: Phaser.Tweens.Tween) => {
if (!this.cameraFollowTarget) { if (!this.playerToFollow) {
return; return;
} }
const shiftX = const shiftX =
(this.cameraFollowTarget.x - this.camera.worldView.width * 0.5 - oldPos.x) * tween.getValue(); (this.playerToFollow.x - this.camera.worldView.width * 0.5 - oldPos.x) * tween.getValue();
const shiftY = const shiftY =
(this.cameraFollowTarget.y - this.camera.worldView.height * 0.5 - oldPos.y) * tween.getValue(); (this.playerToFollow.y - this.camera.worldView.height * 0.5 - oldPos.y) * tween.getValue();
this.camera.setScroll(oldPos.x + shiftX, oldPos.y + shiftY); this.camera.setScroll(oldPos.x + shiftX, oldPos.y + shiftY);
}, },
onComplete: () => { onComplete: () => {
this.camera.startFollow(target, true); this.camera.startFollow(player, true);
}, },
}); });
} }
@ -131,8 +181,8 @@ export class CameraManager extends Phaser.Events.EventEmitter {
); );
} }
public isCameraLocked(): boolean { public isCameraZoomLocked(): boolean {
return this.cameraMode === CameraMode.Focus; return [CameraMode.Focus, CameraMode.Positioned].includes(this.cameraMode);
} }
private setCameraMode(mode: CameraMode): void { private setCameraMode(mode: CameraMode): void {

View File

@ -561,7 +561,7 @@ export class GameScene extends DirtyScene {
waScaleManager waScaleManager
); );
biggestAvailableAreaStore.recompute(); biggestAvailableAreaStore.recompute();
this.cameraManager.startFollow(this.CurrentPlayer); this.cameraManager.startFollowPlayer(this.CurrentPlayer);
this.animatedTiles.init(this.Map); this.animatedTiles.init(this.Map);
this.events.on("tileanimationupdate", () => (this.dirty = true)); this.events.on("tileanimationupdate", () => (this.dirty = true));
@ -1072,8 +1072,7 @@ ${escapedMessage}
this.iframeSubscriptionList.push( this.iframeSubscriptionList.push(
iframeListener.cameraSetPositionStream.subscribe((cameraSetPositionEvent) => { iframeListener.cameraSetPositionStream.subscribe((cameraSetPositionEvent) => {
// this.cameraManager.enterFocusMode({ ...cameraSetPositionEvent }, undefined, cameraSetPositionEvent.smooth ? 1000 : 0); this.cameraManager.setPosition({ ...cameraSetPositionEvent }, cameraSetPositionEvent.smooth ? 1000 : 0);
console.log("camera set position");
}) })
); );
@ -2045,7 +2044,7 @@ ${escapedMessage}
} }
zoomByFactor(zoomFactor: number) { zoomByFactor(zoomFactor: number) {
if (this.cameraManager.isCameraLocked()) { if (this.cameraManager.isCameraZoomLocked()) {
return; return;
} }
waScaleManager.zoomModifier *= zoomFactor; waScaleManager.zoomModifier *= zoomFactor;