diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index e9fc0bfa..c596c8ee 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -1,14 +1,12 @@ - -
-
-

{$LL.woka.customWoka.title()}

-
-
- - -
-
- {#if $activeRowStore === 0} - - {/if} - {#if $activeRowStore !== 0} - - {/if} - {#if $activeRowStore === 5} - - {/if} - {#if $activeRowStore !== 5} - - {/if} -
-
- - diff --git a/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts b/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts index f667ad27..6030a03e 100644 --- a/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts +++ b/front/src/Phaser/Components/CustomizeWoka/CustomWokaPreviewer.ts @@ -9,6 +9,15 @@ export enum CustomWokaBodyPart { Accessory = "Accessory", } +export enum CustomWokaBodyPartOrder { + Body = 0, + Eyes = 1, + Hair = 2, + Clothes = 3, + Hat = 4, + Accessory = 5, +} + export interface CustomWokaPreviewerConfig { color: number; borderThickness: number; @@ -33,20 +42,22 @@ export class CustomWokaPreviewer extends Phaser.GameObjects.Container { this.config = config; this.sprites = { - [CustomWokaBodyPart.Accessory]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, ""), - [CustomWokaBodyPart.Body]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, ""), - [CustomWokaBodyPart.Clothes]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, ""), - [CustomWokaBodyPart.Eyes]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, ""), - [CustomWokaBodyPart.Hair]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, ""), - [CustomWokaBodyPart.Hat]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, ""), + [CustomWokaBodyPart.Accessory]: this.scene.add + .sprite(this.config.bodyPartsOffsetX, 0, "") + .setVisible(false), + [CustomWokaBodyPart.Body]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, "").setVisible(false), + [CustomWokaBodyPart.Clothes]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, "").setVisible(false), + [CustomWokaBodyPart.Eyes]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, "").setVisible(false), + [CustomWokaBodyPart.Hair]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, "").setVisible(false), + [CustomWokaBodyPart.Hat]: this.scene.add.sprite(this.config.bodyPartsOffsetX, 0, "").setVisible(false), }; - this.updateSprite("accessory1", CustomWokaBodyPart.Accessory); - this.updateSprite("body1", CustomWokaBodyPart.Body); - this.updateSprite("clothes4", CustomWokaBodyPart.Clothes); - this.updateSprite("eyes5", CustomWokaBodyPart.Eyes); - this.updateSprite("hair3", CustomWokaBodyPart.Hair); - this.updateSprite("hat2", CustomWokaBodyPart.Hat); + // this.updateSprite("accessory1", CustomWokaBodyPart.Accessory); + // this.updateSprite("body1", CustomWokaBodyPart.Body); + // this.updateSprite("clothes4", CustomWokaBodyPart.Clothes); + // this.updateSprite("eyes5", CustomWokaBodyPart.Eyes); + // this.updateSprite("hair3", CustomWokaBodyPart.Hair); + // this.updateSprite("hat2", CustomWokaBodyPart.Hat); this.background = this.scene.add.graphics(); this.drawBackground(); @@ -74,36 +85,12 @@ export class CustomWokaPreviewer extends Phaser.GameObjects.Container { this.moving = moving; } - private drawBackground(): void { - this.background.clear(); - this.background.fillStyle(0xffffff); - this.background.lineStyle(this.config.borderThickness, 0xadafbc); - - this.background.fillRect(-this.SIZE / 2, -this.SIZE / 2, this.SIZE, this.SIZE); - this.background.strokeRect(-this.SIZE / 2, -this.SIZE / 2, this.SIZE, this.SIZE); - } - - private animate(): void { - for (const bodyPartKey in this.sprites) { - const sprite = this.sprites[bodyPartKey as CustomWokaBodyPart]; - if (!sprite.anims) { - console.error("ANIMS IS NOT DEFINED!!!"); - return; - } - const textureKey = sprite.texture.key; - if ( - this.moving && - (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== this.animationDirection) - ) { - sprite.play(textureKey + "-" + this.animationDirection + "-" + PlayerAnimationTypes.Walk, true); - } else if (!this.moving) { - sprite.anims.play(textureKey + "-" + this.animationDirection + "-" + PlayerAnimationTypes.Idle, true); - } - } - } - public updateSprite(textureKey: string, bodyPart: CustomWokaBodyPart): void { - this.sprites[bodyPart].setTexture(textureKey); + this.sprites[bodyPart].setTexture(textureKey).setVisible(textureKey !== ""); + console.log(this.sprites[bodyPart].texture.key); + if (textureKey === "") { + return; + } getPlayerAnimations(textureKey).forEach((d) => { this.scene.anims.create({ key: d.key, @@ -125,4 +112,35 @@ export class CustomWokaPreviewer extends Phaser.GameObjects.Container { public getAnimationDirection(): PlayerAnimationDirections { return this.animationDirection; } + + private drawBackground(): void { + this.background.clear(); + this.background.fillStyle(0xffffff); + this.background.lineStyle(this.config.borderThickness, 0xadafbc); + + this.background.fillRect(-this.SIZE / 2, -this.SIZE / 2, this.SIZE, this.SIZE); + this.background.strokeRect(-this.SIZE / 2, -this.SIZE / 2, this.SIZE, this.SIZE); + } + + private animate(): void { + for (const bodyPartKey in this.sprites) { + const sprite = this.sprites[bodyPartKey as CustomWokaBodyPart]; + if (!sprite.anims) { + console.error("ANIMS IS NOT DEFINED!!!"); + return; + } + const textureKey = sprite.texture.key; + if (textureKey === "__MISSING") { + continue; + } + if ( + this.moving && + (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== this.animationDirection) + ) { + sprite.play(textureKey + "-" + this.animationDirection + "-" + PlayerAnimationTypes.Walk, true); + } else if (!this.moving) { + sprite.anims.play(textureKey + "-" + this.animationDirection + "-" + PlayerAnimationTypes.Idle, true); + } + } + } } diff --git a/front/src/Phaser/Components/CustomizeWoka/WokaBodyPartSlot.ts b/front/src/Phaser/Components/CustomizeWoka/WokaBodyPartSlot.ts index cc7b77e3..6c37628d 100644 --- a/front/src/Phaser/Components/CustomizeWoka/WokaBodyPartSlot.ts +++ b/front/src/Phaser/Components/CustomizeWoka/WokaBodyPartSlot.ts @@ -37,15 +37,13 @@ export class WokaBodyPartSlot extends GridItem { .rectangle(0, 0, this.SIZE, this.SIZE, this.config.color) .setStrokeStyle(this.config.borderThickness, this.config.borderColor); - this.bodyImage = this.scene.add.image( - offsetX, - offsetY, - config.bodyImageKey ?? `body${Math.floor(Math.random() * 33) + 1}` - ); + this.bodyImage = this.scene.add + .image(offsetX, offsetY, config.bodyImageKey ?? "") + .setVisible(config.imageKey !== undefined); this.image = this.scene.add .image(offsetX, offsetY, config.imageKey ?? "") - .setVisible(config.imageKey !== undefined); + .setVisible(config.bodyImageKey !== undefined); this.setSize(this.SIZE + this.config.borderThickness, this.SIZE + this.config.borderThickness); @@ -59,14 +57,22 @@ export class WokaBodyPartSlot extends GridItem { this.scene.add.existing(this); } - public setBodyTexture(textureKey: string, frame?: string | number): void { - this.bodyImage.setTexture(textureKey, frame); + public setTextures(bodyTextureKey?: string, imageTextureKey?: string): void { + this.setBodyTexture(bodyTextureKey); + this.setImageTexture(imageTextureKey); + } + + public setBodyTexture(textureKey?: string, frame?: string | number): void { + this.bodyImage.setVisible(textureKey !== undefined && textureKey !== ""); + if (textureKey) { + this.bodyImage.setTexture(textureKey, frame); + } } public setImageTexture(textureKey?: string, frame?: string | number): void { - this.image.setVisible(textureKey !== undefined || textureKey !== ""); + this.image.setVisible(textureKey !== undefined && textureKey !== ""); if (textureKey) { - this.bodyImage.setTexture(textureKey, frame); + this.image.setTexture(textureKey, frame); } } diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts index a2c7ea0b..615ad220 100644 --- a/front/src/Phaser/Login/CustomizeScene.ts +++ b/front/src/Phaser/Login/CustomizeScene.ts @@ -7,15 +7,14 @@ import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures" import { AbstractCharacterScene } from "./AbstractCharacterScene"; import { areCharacterLayersValid } from "../../Connexion/LocalUser"; import { SelectCharacterSceneName } from "./SelectCharacterScene"; -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 { CustomWokaBodyPart, + CustomWokaBodyPartOrder, CustomWokaPreviewer, CustomWokaPreviewerConfig, } from "../Components/CustomizeWoka/CustomWokaPreviewer"; @@ -25,21 +24,18 @@ import { WokaBodyPartSlot, WokaBodyPartSlotConfig } from "../Components/Customiz export const CustomizeSceneName = "CustomizeScene"; export class CustomizeScene extends AbstractCharacterScene { - private Rectangle!: Phaser.GameObjects.Rectangle; - private customWokaPreviewer!: CustomWokaPreviewer; + private bodyPartsDraggableGridBackground!: Phaser.GameObjects.Rectangle; + private bodyPartsDraggableGridForeground!: Phaser.GameObjects.Rectangle; private bodyPartsDraggableGrid!: DraggableGrid; private bodyPartsSlots!: Record; - private selectedLayers: number[] = [0]; + private selectedLayers: number[] = [0, 1, 2, 3, 4, 5]; private containersRow: CustomizedCharacter[][] = []; private layers: BodyResourceDescriptionInterface[][] = []; protected lazyloadingAttempt = true; //permit to update texture loaded after renderer - private moveHorizontally: number = 0; - private moveVertically: number = 0; - private loader: Loader; constructor() { @@ -96,33 +92,9 @@ export class CustomizeScene extends AbstractCharacterScene { const isVertical = isMediaBreakpointUp("md"); - 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.createCustomizeLayer(0, 0, 0); - this.createCustomizeLayer(0, 0, 1); - this.createCustomizeLayer(0, 0, 2); - this.createCustomizeLayer(0, 0, 3); - this.createCustomizeLayer(0, 0, 4); - 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, 0, 0, this.getCustomWokaPreviewerConfig()); + this.bodyPartsDraggableGridBackground = this.add.rectangle(0, 0, 485, 165, 0xf9f9f9); this.bodyPartsDraggableGrid = new DraggableGrid(this, { position: { x: 0, y: 0 }, maskPosition: { x: 0, y: 0 }, @@ -136,9 +108,10 @@ export class CustomizeScene extends AbstractCharacterScene { }, spacing: 5, debug: { - showDraggableSpace: true, + showDraggableSpace: false, }, }); + this.bodyPartsDraggableGridForeground = this.add.rectangle(0, 0, 485, 165, 0xffffff, 0); this.bodyPartsSlots = { [CustomWokaBodyPart.Hair]: new WokaBodyPartSlot( @@ -179,6 +152,8 @@ export class CustomizeScene extends AbstractCharacterScene { ), }; + this.setPlayerCurrentOutfit(); + this.onResize(); this.bindEventHandlers(); @@ -186,37 +161,10 @@ export class CustomizeScene extends AbstractCharacterScene { 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 { const isVertical = this.cameras.main.width / this.cameras.main.height < 0.75; - 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.handleCustomWokaPreviewerOnResize(isVertical); this.handleBodyPartSlotsOnResize(isVertical); @@ -250,25 +198,42 @@ export class CustomizeScene extends AbstractCharacterScene { this.scene.run(SelectCharacterSceneName); } + private setPlayerCurrentOutfit(): void { + let i = 0; + for (const layerItem of this.selectedLayers) { + const bodyPart = CustomWokaBodyPart[CustomWokaBodyPartOrder[i] as CustomWokaBodyPart]; + this.customWokaPreviewer.updateSprite(this.layers[i][layerItem].id, bodyPart); + this.bodyPartsSlots[bodyPart].setTextures( + this.layers[CustomWokaBodyPartOrder.Body][this.selectedLayers[CustomWokaBodyPartOrder.Body]].id, + this.layers[i][layerItem].id + ); + i += 1; + } + } + private handleCustomWokaPreviewerOnResize(isVertical: boolean): void { + const slotDimension = + Math.min(innerWidth * (isVertical ? 0.2 : 0.15), innerHeight * (isVertical ? 0.2 : 0.15)) / + waScaleManager.getActualZoom(); + const boxDimension = Math.min(innerWidth * (isVertical ? 0.4 : 0.3), innerHeight * (isVertical ? 0.4 : 0.3)) / waScaleManager.getActualZoom(); - const boxScale = boxDimension / this.customWokaPreviewer.SIZE; - this.customWokaPreviewer.setScale(boxScale); + this.customWokaPreviewer.setDisplaySize(boxDimension, boxDimension); this.customWokaPreviewer.x = this.cameras.main.worldView.x + this.cameras.main.width / 2; - this.customWokaPreviewer.y = this.customWokaPreviewer.displayHeight * 0.5 + 10; + this.customWokaPreviewer.y = isVertical + ? this.customWokaPreviewer.displayHeight * 0.5 + 20 + : slotDimension * 1.5 + 20; } private handleBodyPartSlotsOnResize(isVertical: boolean): void { const slotDimension = Math.min(innerWidth * (isVertical ? 0.2 : 0.15), innerHeight * (isVertical ? 0.2 : 0.15)) / waScaleManager.getActualZoom(); - const slotScale = slotDimension / this.customWokaPreviewer.SIZE; for (const part in this.bodyPartsSlots) { - this.bodyPartsSlots[part as CustomWokaBodyPart].setScale(slotScale); + this.bodyPartsSlots[part as CustomWokaBodyPart].setDisplaySize(slotDimension, slotDimension); } const slotSize = this.bodyPartsSlots.Accessory.displayHeight; @@ -306,23 +271,28 @@ export class CustomizeScene extends AbstractCharacterScene { private handleBodyPartsDraggableGridOnResize(isVertical: boolean): void { const gridHeight = (innerHeight * (isVertical ? 0.3 : 0.35)) / waScaleManager.getActualZoom(); - const gridWidth = (innerWidth * (isVertical ? 0.9 : 0.8)) / waScaleManager.getActualZoom(); + const gridWidth = (innerWidth * (isVertical ? 1 : 0.8)) / waScaleManager.getActualZoom(); const gridPos = { x: this.cameras.main.worldView.x + this.cameras.main.width / 2, - y: this.cameras.main.worldView.y + this.cameras.main.height - gridHeight * 0.5 - 10, + y: this.cameras.main.worldView.y + this.cameras.main.height - gridHeight * 0.5, }; + this.bodyPartsDraggableGridBackground.setPosition(gridPos.x, gridPos.y).setDisplaySize(gridWidth, gridHeight); + this.bodyPartsDraggableGridForeground + .setPosition(gridPos.x, gridPos.y) + .setDisplaySize(gridWidth, gridHeight) + .setStrokeStyle(4, 0xaaaaaa); this.bodyPartsDraggableGrid.changeDraggableSpacePosAndSize(gridPos, { x: gridWidth, y: gridHeight }, gridPos); const slotDimension = (innerHeight * (isVertical ? 0.125 : 0.15)) / waScaleManager.getActualZoom(); const slotScale = slotDimension / this.customWokaPreviewer.SIZE; - this.bodyPartsDraggableGrid.clearAllItems(); - for (let i = 0; i < 50; i += 1) { - this.bodyPartsDraggableGrid.addItem( - new WokaBodyPartSlot(this, 0, 0, this.getDefaultWokaBodyPartSlotConfig(isVertical)).setScale(slotScale) - ); - } + // this.bodyPartsDraggableGrid.clearAllItems(); + // for (let i = 0; i < 50; i += 1) { + // this.bodyPartsDraggableGrid.addItem( + // new WokaBodyPartSlot(this, 0, 0, this.getDefaultWokaBodyPartSlotConfig(isVertical)).setScale(slotScale) + // ); + // } this.bodyPartsDraggableGrid.moveContentToBeginning(); } @@ -363,14 +333,6 @@ export class CustomizeScene extends AbstractCharacterScene { this.backToPreviousScene(); }); - // Note: the key bindings are not directly put on the moveCursorVertically or moveCursorHorizontally methods - // because if 2 such events are fired close to one another, it makes the whole application crawl to a halt (for a reason I cannot - // explain, the list of sprites managed by the update list become immense - this.input.keyboard.on("keyup-RIGHT", () => (this.moveHorizontally = 1)); - 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)); - this.input.keyboard.on("keydown-R", () => { this.randomizeOutfit(); }); @@ -402,115 +364,4 @@ export class CustomizeScene extends AbstractCharacterScene { CustomWokaBodyPart.Accessory ); } - - private doMoveCursorHorizontally(index: number): void { - this.selectedLayers[get(activeRowStore)] += index; - if (this.selectedLayers[get(activeRowStore)] < 0) { - this.selectedLayers[get(activeRowStore)] = 0; - } else if (this.selectedLayers[get(activeRowStore)] > this.layers[get(activeRowStore)].length - 1) { - this.selectedLayers[get(activeRowStore)] = this.layers[get(activeRowStore)].length - 1; - } - this.moveLayers(); - this.updateSelectedLayer(); - this.saveInLocalStorage(); - } - - private doMoveCursorVertically(index: number): void { - activeRowStore.set(get(activeRowStore) + index); - if (get(activeRowStore) < 0) { - activeRowStore.set(0); - } else if (get(activeRowStore) > this.layers.length - 1) { - activeRowStore.set(this.layers.length - 1); - } - this.moveLayers(); - this.saveInLocalStorage(); - } - - private saveInLocalStorage() { - localUserStore.setCustomCursorPosition(get(activeRowStore), this.selectedLayers); - } - - /** - * @param x, the layer's vertical position - * @param y, the layer's horizontal position - * @param layerNumber, index of the this.layers array - * create the layer and display it on the scene - */ - private createCustomizeLayer(x: number, y: number, layerNumber: number): void { - this.containersRow[layerNumber] = []; - this.selectedLayers[layerNumber] = 0; - let alpha = 0; - let layerPosX = 0; - for (let i = 0; i < this.layers[layerNumber].length; i++) { - const container = this.generateCharacter(300 + x + layerPosX, y, layerNumber, i); - - this.containersRow[layerNumber][i] = container; - this.add.existing(container); - layerPosX += 30; - alpha += 0.1; - } - } - - /** - * Generates a character from the current selected items BUT replaces - * one layer item with an item we pass in parameter. - * - * Current selected items are fetched from this.selectedLayers - * - * @param x, - * @param y, - * @param layerNumber, The selected layer number (0 for body...) - * @param selectedItem, The number of the item select (0 for black body...) - */ - private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) { - return new CustomizedCharacter(this, x, y, this.getContainerChildren(layerNumber, selectedItem)); - } - - private getContainerChildren(layerNumber: number, selectedItem: number): Array { - const children: Array = new Array(); - for (let j = 0; j <= layerNumber; j++) { - if (j === layerNumber) { - children.push(this.layers[j][selectedItem].id); - } else { - const layer = this.selectedLayers[j]; - if (layer === undefined) { - continue; - } - children.push(this.layers[j][layer].id); - } - } - return children; - } - - /** - * Move the layer left, right, up and down and update the selected layer - */ - 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 / 3; - const screenWidth = this.game.renderer.width; - const screenHeight = this.game.renderer.height; - for (let i = 0; i < this.containersRow.length; i++) { - for (let j = 0; j < this.containersRow[i].length; j++) { - let selectedX = this.selectedLayers[i]; - if (selectedX === undefined) { - selectedX = 0; - } - this.containersRow[i][j].x = screenCenterX + (j - selectedX) * 40; - this.containersRow[i][j].y = screenCenterY + (i - get(activeRowStore)) * 40; - const alpha1 = (Math.abs(selectedX - j) * 47 * 2) / screenWidth; - const alpha2 = (Math.abs(get(activeRowStore) - i) * 49 * 2) / screenHeight; - this.containersRow[i][j].setAlpha((1 - alpha1) * (1 - alpha2)); - } - } - } - - private updateSelectedLayer() { - for (let i = 0; i < this.containersRow.length; i++) { - for (let j = 0; j < this.containersRow[i].length; j++) { - const children = this.getContainerChildren(i, j); - this.containersRow[i][j].updateSprites(children); - } - } - } } diff --git a/front/src/Stores/CustomCharacterStore.ts b/front/src/Stores/CustomCharacterStore.ts index 2c7d75e8..0ade6ea8 100644 --- a/front/src/Stores/CustomCharacterStore.ts +++ b/front/src/Stores/CustomCharacterStore.ts @@ -1,5 +1,3 @@ import { derived, writable, Writable } from "svelte/store"; -export const customCharacterSceneVisibleStore = writable(false); - export const activeRowStore = writable(0);