From 138e8aece4b6fee5e423f32028f078c69d48a49d Mon Sep 17 00:00:00 2001 From: Piotr 'pwh' Hanusiak Date: Fri, 11 Mar 2022 13:36:55 +0100 Subject: [PATCH] better woka preview, wip --- .../CustomizeWoka/CustomWokaPreviewer.ts | 28 +++ front/src/Phaser/Entity/Character.ts | 82 +------- .../src/Phaser/Entity/CustomizedCharacter.ts | 38 +++- front/src/Phaser/Login/CustomizeScene.ts | 184 +++++++++--------- front/src/Phaser/Login/EntryScene.ts | 8 +- .../src/Phaser/Login/SelectCharacterScene.ts | 2 +- front/src/Phaser/Player/Animation.ts | 69 +++++++ 7 files changed, 240 insertions(+), 171 deletions(-) create mode 100644 front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts diff --git a/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts b/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts new file mode 100644 index 00000000..cb01f0dc --- /dev/null +++ b/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts @@ -0,0 +1,28 @@ +import { CustomizedCharacter } from "../../Entity/CustomizedCharacter"; +import { PlayerAnimationDirections } from "../../Player/Animation"; + +export class CustomWokaPreviewer extends Phaser.GameObjects.Container { + private background: Phaser.GameObjects.Rectangle; + private character: CustomizedCharacter; + + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y); + + this.background = this.createBackground(); + this.character = new CustomizedCharacter(scene, 0, 0, ["body19", "clothes4"]); + this.character.setScale(4); + this.setSize(this.background.displayWidth, this.background.displayHeight); + + this.add([this.background, this.character]); + + this.scene.add.existing(this); + } + + public update(): void { + this.character.playAnimation(PlayerAnimationDirections.Down, true); + } + + private createBackground(): Phaser.GameObjects.Rectangle { + return this.scene.add.rectangle(0, 0, 150, 300, 0xbfbfbf, 0.5); + } +} diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index 37d92b89..1a276b1d 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -1,4 +1,9 @@ -import { PlayerAnimationDirections, PlayerAnimationTypes } from "../Player/Animation"; +import { + AnimationData, + getPlayerAnimations, + PlayerAnimationDirections, + PlayerAnimationTypes, +} from "../Player/Animation"; import { SpeechBubble } from "./SpeechBubble"; import Text = Phaser.GameObjects.Text; import Container = Phaser.GameObjects.Container; @@ -20,15 +25,6 @@ import type CancelablePromise from "cancelable-promise"; import { TalkIcon } from "../Components/TalkIcon"; const playerNameY = -25; - -interface AnimationData { - key: string; - frameRate: number; - repeat: number; - frameModel: string; //todo use an enum - frames: number[]; -} - const interactiveRadius = 35; export abstract class Character extends Container implements OutlineableInterface { @@ -232,7 +228,7 @@ export abstract class Character extends Container implements OutlineableInterfac } } - public addTextures(textures: string[], frame?: string | number): void { + private addTextures(textures: string[], frame?: string | number): void { if (textures.length < 1) { throw new TextureError("no texture given"); } @@ -243,7 +239,8 @@ export abstract class Character extends Container implements OutlineableInterfac } const sprite = new Sprite(this.scene, 0, 0, texture, frame); this.add(sprite); - this.getPlayerAnimations(texture).forEach((d) => { + console.log(texture); + getPlayerAnimations(texture).forEach((d) => { this.scene.anims.create({ key: d.key, frames: this.scene.anims.generateFrameNumbers(d.frameModel, { frames: d.frames }), @@ -263,67 +260,6 @@ export abstract class Character extends Container implements OutlineableInterfac return this.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined; } - private getPlayerAnimations(name: string): AnimationData[] { - return [ - { - key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [0, 1, 2, 1], - frameRate: 10, - repeat: -1, - }, - { - key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [3, 4, 5, 4], - frameRate: 10, - repeat: -1, - }, - { - key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [6, 7, 8, 7], - frameRate: 10, - repeat: -1, - }, - { - key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [9, 10, 11, 10], - frameRate: 10, - repeat: -1, - }, - { - key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [1], - frameRate: 10, - repeat: 1, - }, - { - key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [4], - frameRate: 10, - repeat: 1, - }, - { - key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [7], - frameRate: 10, - repeat: 1, - }, - { - key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [10], - frameRate: 10, - repeat: 1, - }, - ]; - } - protected playAnimation(direction: PlayerAnimationDirections, moving: boolean): void { if (this.invisible) return; for (const [texture, sprite] of this.sprites.entries()) { diff --git a/front/src/Phaser/Entity/CustomizedCharacter.ts b/front/src/Phaser/Entity/CustomizedCharacter.ts index 79ac8ebc..5d91964f 100644 --- a/front/src/Phaser/Entity/CustomizedCharacter.ts +++ b/front/src/Phaser/Entity/CustomizedCharacter.ts @@ -1,20 +1,54 @@ import Container = Phaser.GameObjects.Container; import type { Scene } from "phaser"; import Sprite = Phaser.GameObjects.Sprite; +import { getPlayerAnimations, PlayerAnimationDirections, PlayerAnimationTypes } from "../Player/Animation"; /** * A sprite of a customized character (used in the Customize Scene only) */ export class CustomizedCharacter extends Container { + private sprites: Phaser.GameObjects.Sprite[]; + public constructor(scene: Scene, x: number, y: number, layers: string[]) { super(scene, x, y); + this.sprites = []; this.updateSprites(layers); } public updateSprites(layers: string[]): void { + this.sprites = []; this.removeAll(true); - for (const layer of layers) { - this.add(new Sprite(this.scene, 0, 0, layer)); + for (const texture of layers) { + const newSprite = new Sprite(this.scene, 0, 0, texture); + this.sprites.push(newSprite); + getPlayerAnimations(texture).forEach((d) => { + this.scene.anims.create({ + key: d.key, + frames: this.scene.anims.generateFrameNumbers(d.frameModel, { frames: d.frames }), + frameRate: d.frameRate, + repeat: d.repeat, + }); + }); + // Needed, otherwise, animations are not handled correctly. + if (this.scene) { + this.scene.sys.updateList.add(newSprite); + } + } + this.add(this.sprites); + } + + public playAnimation(direction: PlayerAnimationDirections, moving: boolean): void { + for (const sprite of this.sprites) { + if (!sprite.anims) { + console.error("ANIMS IS NOT DEFINED!!!"); + return; + } + const textureKey = sprite.texture.key; + if (moving && (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== direction)) { + sprite.play(textureKey + "-" + direction + "-" + PlayerAnimationTypes.Walk, true); + } else if (!moving) { + sprite.anims.play(textureKey + "-" + direction + "-" + PlayerAnimationTypes.Idle, true); + } } } } diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts index 918cf9cf..8f94ab69 100644 --- a/front/src/Phaser/Login/CustomizeScene.ts +++ b/front/src/Phaser/Login/CustomizeScene.ts @@ -9,19 +9,22 @@ import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures" import { AbstractCharacterScene } from "./AbstractCharacterScene"; import { areCharacterLayersValid } from "../../Connexion/LocalUser"; import { SelectCharacterSceneName } from "./SelectCharacterScene"; -import { activeRowStore, customCharacterSceneVisibleStore } from "../../Stores/CustomCharacterStore"; +import { activeRowStore } from "../../Stores/CustomCharacterStore"; import { waScaleManager } from "../Services/WaScaleManager"; import { CustomizedCharacter } from "../Entity/CustomizedCharacter"; import { get } from "svelte/store"; import { analyticsClient } from "../../Administration/AnalyticsClient"; import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils"; import { PUSHER_URL } from "../../Enum/EnvironmentVariable"; +import { CustomWokaPreviewer } from "../Components/CustomizeWoka/CustomWokaPreviewer"; export const CustomizeSceneName = "CustomizeScene"; export class CustomizeScene extends AbstractCharacterScene { private Rectangle!: Rectangle; + private customWokaPreviewer: CustomWokaPreviewer; + private selectedLayers: number[] = [0]; private containersRow: CustomizedCharacter[][] = []; private layers: BodyResourceDescriptionInterface[][] = []; @@ -40,7 +43,7 @@ export class CustomizeScene extends AbstractCharacterScene { this.loader = new Loader(this); } - preload() { + public preload(): void { const wokaMetadataKey = "woka-list"; this.cache.json.remove(wokaMetadataKey); // FIXME: window.location.href is wrong. We need the URL of the main room (so we need to apply any redirect before!) @@ -82,13 +85,8 @@ export class CustomizeScene extends AbstractCharacterScene { }); } - create() { - customCharacterSceneVisibleStore.set(true); - this.events.addListener("wake", () => { - waScaleManager.saveZoom(); - waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 3 : 1; - customCharacterSceneVisibleStore.set(true); - }); + public create(): void { + console.log(this.layers); waScaleManager.saveZoom(); waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 3 : 1; @@ -100,7 +98,6 @@ export class CustomizeScene extends AbstractCharacterScene { 33 ); this.Rectangle.setStrokeStyle(2, 0xffffff); - this.add.existing(this.Rectangle); this.createCustomizeLayer(0, 0, 0); this.createCustomizeLayer(0, 0, 1); @@ -110,6 +107,91 @@ export class CustomizeScene extends AbstractCharacterScene { this.createCustomizeLayer(0, 0, 5); this.moveLayers(); + + const customCursorPosition = localUserStore.getCustomCursorPosition(); + if (customCursorPosition) { + activeRowStore.set(customCursorPosition.activeRow); + this.selectedLayers = customCursorPosition.selectedLayers; + this.moveLayers(); + this.updateSelectedLayer(); + } + + this.customWokaPreviewer = new CustomWokaPreviewer(this, 300, 300); + + this.onResize(); + + this.bindEventHandlers(); + } + + public update(time: number, dt: number): void { + this.customWokaPreviewer.update(); + if (this.lazyloadingAttempt) { + this.moveLayers(); + this.doMoveCursorHorizontally(this.moveHorizontally); + this.lazyloadingAttempt = false; + } + + if (this.moveHorizontally !== 0) { + this.doMoveCursorHorizontally(this.moveHorizontally); + this.moveHorizontally = 0; + } + if (this.moveVertically !== 0) { + this.doMoveCursorVertically(this.moveVertically); + this.moveVertically = 0; + } + } + + public moveCursorHorizontally(index: number): void { + this.moveHorizontally = index; + } + + public moveCursorVertically(index: number): void { + this.moveVertically = index; + } + + public onResize(): void { + this.moveLayers(); + + this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2; + this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3; + + this.customWokaPreviewer.x = this.cameras.main.worldView.x + this.cameras.main.width / 2; + this.customWokaPreviewer.y = this.cameras.main.worldView.y + this.cameras.main.height / 2; + } + + public nextSceneToCamera() { + const layers: string[] = []; + let i = 0; + for (const layerItem of this.selectedLayers) { + if (layerItem !== undefined) { + layers.push(this.layers[i][layerItem].id); + } + i++; + } + if (!areCharacterLayersValid(layers)) { + return; + } + + analyticsClient.validationWoka("CustomizeWoka"); + + gameManager.setCharacterLayers(layers); + this.scene.stop(CustomizeSceneName); + waScaleManager.restoreZoom(); + gameManager.tryResumingGame(EnableCameraSceneName); + } + + public backToPreviousScene() { + this.scene.stop(CustomizeSceneName); + waScaleManager.restoreZoom(); + this.scene.run(SelectCharacterSceneName); + } + + private bindEventHandlers(): void { + this.events.addListener("wake", () => { + waScaleManager.saveZoom(); + waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 3 : 1; + }); + this.input.keyboard.on("keyup-ENTER", () => { this.nextSceneToCamera(); }); @@ -124,24 +206,6 @@ export class CustomizeScene extends AbstractCharacterScene { this.input.keyboard.on("keyup-LEFT", () => (this.moveHorizontally = -1)); this.input.keyboard.on("keyup-DOWN", () => (this.moveVertically = 1)); this.input.keyboard.on("keyup-UP", () => (this.moveVertically = -1)); - - const customCursorPosition = localUserStore.getCustomCursorPosition(); - if (customCursorPosition) { - activeRowStore.set(customCursorPosition.activeRow); - this.selectedLayers = customCursorPosition.selectedLayers; - this.moveLayers(); - this.updateSelectedLayer(); - } - - this.onResize(); - } - - public moveCursorHorizontally(index: number): void { - this.moveHorizontally = index; - } - - public moveCursorVertically(index: number): void { - this.moveVertically = index; } private doMoveCursorHorizontally(index: number): void { @@ -246,17 +310,6 @@ export class CustomizeScene extends AbstractCharacterScene { } } - /** - * @param x, the sprite's vertical position - * @param y, the sprites's horizontal position - * @param name, the sprite's name - * @return a new sprite - */ - private generateLayers(x: number, y: number, name: string): Sprite { - //return new Sprite(this, x, y, name); - return this.add.sprite(0, 0, name); - } - private updateSelectedLayer() { for (let i = 0; i < this.containersRow.length; i++) { for (let j = 0; j < this.containersRow[i].length; j++) { @@ -265,57 +318,4 @@ export class CustomizeScene extends AbstractCharacterScene { } } } - - update(time: number, delta: number): void { - if (this.lazyloadingAttempt) { - this.moveLayers(); - this.doMoveCursorHorizontally(this.moveHorizontally); - this.lazyloadingAttempt = false; - } - - if (this.moveHorizontally !== 0) { - this.doMoveCursorHorizontally(this.moveHorizontally); - this.moveHorizontally = 0; - } - if (this.moveVertically !== 0) { - this.doMoveCursorVertically(this.moveVertically); - this.moveVertically = 0; - } - } - - public onResize(): void { - this.moveLayers(); - - this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2; - this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3; - } - - public nextSceneToCamera() { - const layers: string[] = []; - let i = 0; - for (const layerItem of this.selectedLayers) { - if (layerItem !== undefined) { - layers.push(this.layers[i][layerItem].id); - } - i++; - } - if (!areCharacterLayersValid(layers)) { - return; - } - - analyticsClient.validationWoka("CustomizeWoka"); - - gameManager.setCharacterLayers(layers); - this.scene.stop(CustomizeSceneName); - waScaleManager.restoreZoom(); - gameManager.tryResumingGame(EnableCameraSceneName); - customCharacterSceneVisibleStore.set(false); - } - - public backToPreviousScene() { - this.scene.stop(CustomizeSceneName); - waScaleManager.restoreZoom(); - this.scene.run(SelectCharacterSceneName); - customCharacterSceneVisibleStore.set(false); - } } diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index d86e3a2e..5a898ae0 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -7,8 +7,8 @@ import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene"; import LL from "../../i18n/i18n-svelte"; import { get } from "svelte/store"; import { localeDetector } from "../../i18n/locales"; -import { PlayerTextures } from "../Entity/PlayerTextures"; -import { PUSHER_URL } from "../../Enum/EnvironmentVariable"; +import { CustomizeSceneName } from "./CustomizeScene"; +import { SelectCharacterSceneName } from "./SelectCharacterScene"; export const EntrySceneName = "EntryScene"; @@ -46,7 +46,9 @@ export class EntryScene extends Scene { // Let's rescale before starting the game // We can do it at this stage. waScaleManager.applyNewSize(); - this.scene.start(nextSceneName); + // this.scene.start(nextSceneName); + // this.scene.start(CustomizeSceneName); + this.scene.start(SelectCharacterSceneName); }) .catch((err) => { const $LL = get(LL); diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index f7fd3c8a..d2f1e8f4 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -149,9 +149,9 @@ export class SelectCharacterScene extends AbstractCharacterScene { } createCurrentPlayer(): void { + console.log("CREATE CURRENT PLAYER"); for (let i = 0; i < this.playerModels.length; i++) { const playerResource = this.playerModels[i]; - //check already exist texture if (this.players.find((c) => c.texture.key === playerResource.id)) { continue; diff --git a/front/src/Phaser/Player/Animation.ts b/front/src/Phaser/Player/Animation.ts index cf13e087..868f9243 100644 --- a/front/src/Phaser/Player/Animation.ts +++ b/front/src/Phaser/Player/Animation.ts @@ -8,3 +8,72 @@ export enum PlayerAnimationTypes { Walk = "walk", Idle = "idle", } + +export interface AnimationData { + key: string; + frameRate: number; + repeat: number; + frameModel: string; //todo use an enum + frames: number[]; +} + +export function getPlayerAnimations(name: string): AnimationData[] { + return [ + { + key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [0, 1, 2, 1], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [3, 4, 5, 4], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [6, 7, 8, 7], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [9, 10, 11, 10], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [1], + frameRate: 10, + repeat: 1, + }, + { + key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [4], + frameRate: 10, + repeat: 1, + }, + { + key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [7], + frameRate: 10, + repeat: 1, + }, + { + key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [10], + frameRate: 10, + repeat: 1, + }, + ]; +}