diff --git a/front/src/Components/selectCharacter/SelectCharacterScene.svelte b/front/src/Components/selectCharacter/SelectCharacterScene.svelte
index 807cf88f..ecf00828 100644
--- a/front/src/Components/selectCharacter/SelectCharacterScene.svelte
+++ b/front/src/Components/selectCharacter/SelectCharacterScene.svelte
@@ -2,18 +2,19 @@
import type { Game } from "../../Phaser/Game/Game";
import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
import LL from "../../i18n/i18n-svelte";
- import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore";
+ import { customizeAvailableStore, selectedCollection } from "../../Stores/SelectCharacterSceneStore";
export let game: Game;
const selectCharacterScene = game.scene.getScene(SelectCharacterSceneName) as SelectCharacterScene;
+ const showArrows = selectCharacterScene.getCollectionKeysSize() > 1;
function selectLeft() {
- selectCharacterScene.moveToLeft();
+ selectCharacterScene.selectPreviousCollection();
}
function selectRight() {
- selectCharacterScene.moveToRight();
+ selectCharacterScene.selectNextCollection();
}
function cameraScene() {
@@ -25,83 +26,72 @@
}
-
+ {/if}
+
diff --git a/front/src/Phaser/Components/SelectWoka/WokaSlot.ts b/front/src/Phaser/Components/SelectWoka/WokaSlot.ts
new file mode 100644
index 00000000..696a9db7
--- /dev/null
+++ b/front/src/Phaser/Components/SelectWoka/WokaSlot.ts
@@ -0,0 +1,35 @@
+import { GridItem } from "@home-based-studio/phaser3-utils";
+
+export class WokaSlot extends GridItem {
+ private sprite: Phaser.GameObjects.Sprite;
+ private selection: Phaser.GameObjects.Rectangle;
+
+ private readonly SIZE: number = 50;
+
+ constructor(scene: Phaser.Scene, spriteKey: string, id?: string) {
+ super(scene, id);
+
+ this.sprite = this.scene.add.sprite(0, 0, spriteKey);
+ this.selection = this.scene.add
+ .rectangle(0, 0, this.SIZE, this.SIZE)
+ .setStrokeStyle(1, 0xffffff)
+ .setVisible(false);
+
+ this.add([this.selection, this.sprite]);
+ this.setSize(this.SIZE, this.SIZE);
+ this.setInteractive({ cursor: "pointer" });
+ this.scene.input.setDraggable(this);
+
+ this.bindEventHandlers();
+
+ this.scene.add.existing(this);
+ }
+
+ public getSprite(): Phaser.GameObjects.Sprite {
+ return this.sprite;
+ }
+
+ public select(select: boolean = true): void {
+ this.selection.setVisible(select);
+ }
+}
diff --git a/front/src/Phaser/Entity/PlayerTextures.ts b/front/src/Phaser/Entity/PlayerTextures.ts
index e1413f6d..66e02c7b 100644
--- a/front/src/Phaser/Entity/PlayerTextures.ts
+++ b/front/src/Phaser/Entity/PlayerTextures.ts
@@ -36,14 +36,16 @@ export enum PlayerTexturesKey {
}
export class PlayerTextures {
- private PLAYER_RESOURCES: BodyResourceDescriptionListInterface = {};
- private COLOR_RESOURCES: BodyResourceDescriptionListInterface = {};
- private EYES_RESOURCES: BodyResourceDescriptionListInterface = {};
- private HAIR_RESOURCES: BodyResourceDescriptionListInterface = {};
- private CLOTHES_RESOURCES: BodyResourceDescriptionListInterface = {};
- private HATS_RESOURCES: BodyResourceDescriptionListInterface = {};
- private ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = {};
- private LAYERS: BodyResourceDescriptionListInterface[] = [];
+ private wokaResources: BodyResourceDescriptionListInterface = {};
+ private colorResources: BodyResourceDescriptionListInterface = {};
+ private eyesResources: BodyResourceDescriptionListInterface = {};
+ private hairResources: BodyResourceDescriptionListInterface = {};
+ private clothesResources: BodyResourceDescriptionListInterface = {};
+ private hatsResources: BodyResourceDescriptionListInterface = {};
+ private accessoriesResources: BodyResourceDescriptionListInterface = {};
+ private layers: BodyResourceDescriptionListInterface[] = [];
+
+ private wokaCollections = new Map();
public loadPlayerTexturesMetadata(metadata: WokaList): void {
this.mapTexturesMetadataIntoResources(metadata);
@@ -52,43 +54,53 @@ export class PlayerTextures {
public getTexturesResources(key: PlayerTexturesKey): BodyResourceDescriptionListInterface {
switch (key) {
case PlayerTexturesKey.Accessory:
- return this.ACCESSORIES_RESOURCES;
+ return this.accessoriesResources;
case PlayerTexturesKey.Body:
- return this.COLOR_RESOURCES;
+ return this.colorResources;
case PlayerTexturesKey.Clothes:
- return this.CLOTHES_RESOURCES;
+ return this.clothesResources;
case PlayerTexturesKey.Eyes:
- return this.EYES_RESOURCES;
+ return this.eyesResources;
case PlayerTexturesKey.Hair:
- return this.HAIR_RESOURCES;
+ return this.hairResources;
case PlayerTexturesKey.Hat:
- return this.HATS_RESOURCES;
+ return this.hatsResources;
case PlayerTexturesKey.Woka:
- return this.PLAYER_RESOURCES;
+ return this.wokaResources;
}
}
public getLayers(): BodyResourceDescriptionListInterface[] {
- return this.LAYERS;
+ return this.layers;
+ }
+
+ public getCollectionsKeys(): string[] {
+ return Array.from(this.wokaCollections.keys());
+ }
+
+ public getWokaCollectionTextures(key: string): BodyResourceDescriptionInterface[] {
+ return this.wokaCollections.get(key) ?? [];
}
private mapTexturesMetadataIntoResources(metadata: WokaList): void {
- this.PLAYER_RESOURCES = this.getMappedResources(metadata.woka);
- this.COLOR_RESOURCES = this.getMappedResources(metadata.body);
- this.EYES_RESOURCES = this.getMappedResources(metadata.eyes);
- this.HAIR_RESOURCES = this.getMappedResources(metadata.hair);
- this.CLOTHES_RESOURCES = this.getMappedResources(metadata.clothes);
- this.HATS_RESOURCES = this.getMappedResources(metadata.hat);
- this.ACCESSORIES_RESOURCES = this.getMappedResources(metadata.accessory);
+ this.wokaResources = this.getMappedResources(metadata.woka);
+ this.colorResources = this.getMappedResources(metadata.body);
+ this.eyesResources = this.getMappedResources(metadata.eyes);
+ this.hairResources = this.getMappedResources(metadata.hair);
+ this.clothesResources = this.getMappedResources(metadata.clothes);
+ this.hatsResources = this.getMappedResources(metadata.hat);
+ this.accessoriesResources = this.getMappedResources(metadata.accessory);
- this.LAYERS = [
- this.COLOR_RESOURCES,
- this.EYES_RESOURCES,
- this.HAIR_RESOURCES,
- this.CLOTHES_RESOURCES,
- this.HATS_RESOURCES,
- this.ACCESSORIES_RESOURCES,
+ this.layers = [
+ this.colorResources,
+ this.eyesResources,
+ this.hairResources,
+ this.clothesResources,
+ this.hatsResources,
+ this.accessoriesResources,
];
+
+ this.mapWokaCollections(metadata.woka);
}
private getMappedResources(category: WokaPartType): BodyResourceDescriptionListInterface {
@@ -103,6 +115,19 @@ export class PlayerTextures {
}
return resources;
}
+
+ private mapWokaCollections(category: WokaPartType): void {
+ if (!category) {
+ return;
+ }
+ for (const collection of category.collections) {
+ const textures: BodyResourceDescriptionInterface[] = [];
+ for (const texture of collection.textures) {
+ textures.push({ id: texture.id, img: texture.url });
+ }
+ this.wokaCollections.set(collection.name, textures);
+ }
+ }
}
export const OBJECTS: BodyResourceDescriptionInterface[] = [
diff --git a/front/src/Phaser/Login/AbstractCharacterScene.ts b/front/src/Phaser/Login/AbstractCharacterScene.ts
index 27a4aeab..7545e26c 100644
--- a/front/src/Phaser/Login/AbstractCharacterScene.ts
+++ b/front/src/Phaser/Login/AbstractCharacterScene.ts
@@ -11,4 +11,8 @@ export abstract class AbstractCharacterScene extends ResizableScene {
this.playerTextures = new PlayerTextures();
this.superLoad = new SuperLoaderPlugin(this);
}
+
+ preload() {
+ this.input.dragDistanceThreshold = 10;
+ }
}
diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts
index e03863c0..59bbfeed 100644
--- a/front/src/Phaser/Login/CustomizeScene.ts
+++ b/front/src/Phaser/Login/CustomizeScene.ts
@@ -54,7 +54,7 @@ export class CustomizeScene extends AbstractCharacterScene {
}
public preload(): void {
- this.input.dragDistanceThreshold = 10;
+ super.preload();
this.load.image("iconClothes", "/resources/icons/icon_clothes.png");
this.load.image("iconAccessory", "/resources/icons/icon_accessory.png");
diff --git a/front/src/Phaser/Login/SelectCharacterMobileScene.ts b/front/src/Phaser/Login/SelectCharacterMobileScene.ts
deleted file mode 100644
index c04d6fb3..00000000
--- a/front/src/Phaser/Login/SelectCharacterMobileScene.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { SelectCharacterScene } from "./SelectCharacterScene";
-
-export class SelectCharacterMobileScene extends SelectCharacterScene {
- create() {
- super.create();
- this.onResize();
- this.selectedRectangle.destroy();
- }
-
- protected defineSetupPlayer(num: number) {
- const deltaX = 30;
- const deltaY = 2;
- let [playerX, playerY] = this.getCharacterPosition();
- let playerVisible = true;
- let playerScale = 1.5;
- let playerOpacity = 1;
-
- if (this.currentSelectUser !== num) {
- playerVisible = false;
- }
- if (num === this.currentSelectUser + 1) {
- playerY -= deltaY;
- playerX += deltaX;
- playerScale = 0.8;
- playerOpacity = 0.6;
- playerVisible = true;
- }
- if (num === this.currentSelectUser + 2) {
- playerY -= deltaY;
- playerX += deltaX * 2;
- playerScale = 0.8;
- playerOpacity = 0.6;
- playerVisible = true;
- }
- if (num === this.currentSelectUser - 1) {
- playerY -= deltaY;
- playerX -= deltaX;
- playerScale = 0.8;
- playerOpacity = 0.6;
- playerVisible = true;
- }
- if (num === this.currentSelectUser - 2) {
- playerY -= deltaY;
- playerX -= deltaX * 2;
- playerScale = 0.8;
- playerOpacity = 0.6;
- playerVisible = true;
- }
- return { playerX, playerY, playerScale, playerOpacity, playerVisible };
- }
-
- /**
- * Returns pixel position by on column and row number
- */
- protected getCharacterPosition(): [number, number] {
- return [this.game.renderer.width / 2, this.game.renderer.height / 3];
- }
-}
diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts
index 13bc1e75..30323463 100644
--- a/front/src/Phaser/Login/SelectCharacterScene.ts
+++ b/front/src/Phaser/Login/SelectCharacterScene.ts
@@ -1,5 +1,4 @@
import { gameManager } from "../Game/GameManager";
-import Rectangle = Phaser.GameObjects.Rectangle;
import { EnableCameraSceneName } from "./EnableCameraScene";
import { CustomizeSceneName } from "./CustomizeScene";
import { localUserStore } from "../../Connexion/LocalUserStore";
@@ -13,25 +12,25 @@ import { PinchManager } from "../UserInput/PinchManager";
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
import { waScaleManager } from "../Services/WaScaleManager";
import { analyticsClient } from "../../Administration/AnalyticsClient";
-import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
import { PUSHER_URL } from "../../Enum/EnvironmentVariable";
-import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore";
+import { customizeAvailableStore, selectedCollection } from "../../Stores/SelectCharacterSceneStore";
+import { DraggableGrid } from "@home-based-studio/phaser3-utils";
+import { WokaSlot } from "../Components/SelectWoka/WokaSlot";
+import { DraggableGridEvent } from "@home-based-studio/phaser3-utils/lib/utils/gui/containers/grids/DraggableGrid";
import { wokaList } from "../../Messages/JsonMessages/PlayerTextures";
//todo: put this constants in a dedicated file
export const SelectCharacterSceneName = "SelectCharacterScene";
export class SelectCharacterScene extends AbstractCharacterScene {
- protected readonly nbCharactersPerRow = 6;
- protected selectedPlayer!: Phaser.Physics.Arcade.Sprite | null; // null if we are selecting the "customize" option
- protected players: Array = new Array();
+ protected selectedWoka!: Phaser.GameObjects.Sprite | null; // null if we are selecting the "customize" option
protected playerModels!: BodyResourceDescriptionInterface[];
- protected selectedRectangle!: Rectangle;
-
- protected currentSelectUser = 0;
- protected pointerClicked: boolean = false;
- protected pointerTimer: number = 0;
+ private charactersDraggableGrid!: DraggableGrid;
+ private collectionKeys!: string[];
+ private selectedCollectionIndex!: number;
+ private selectedGridItemIndex?: number;
+ private gridRowsCount: number = 1;
protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
private loader: Loader;
@@ -44,7 +43,8 @@ export class SelectCharacterScene extends AbstractCharacterScene {
this.playerTextures = new PlayerTextures();
}
- preload() {
+ public preload() {
+ super.preload();
const wokaMetadataKey = "woka-list" + gameManager.currentStartedRoom.href;
this.cache.json.remove(wokaMetadataKey);
@@ -67,228 +67,236 @@ export class SelectCharacterScene extends AbstractCharacterScene {
}
)
.catch((e) => console.error(e));
+ this.playerModels = loadAllDefaultModels(this.load, this.playerTextures);
+ this.lazyloadingAttempt = false;
//this function must stay at the end of preload function
this.loader.addLoader();
}
- create() {
+ public create() {
+ waScaleManager.zoomModifier = 1;
+ this.selectedWoka = null;
+ this.selectedCollectionIndex = 0;
+ this.collectionKeys = this.playerTextures.getCollectionsKeys();
+ selectedCollection.set(this.getSelectedCollectionName());
+
customizeAvailableStore.set(this.isCustomizationAvailable());
selectCharacterSceneVisibleStore.set(true);
- this.events.addListener("wake", () => {
- waScaleManager.saveZoom();
- waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
- selectCharacterSceneVisibleStore.set(true);
- });
if (touchScreenManager.supportTouchScreen) {
new PinchManager(this);
}
- waScaleManager.saveZoom();
- waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
-
- const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
- this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xffffff);
- this.selectedRectangle.setDepth(2);
-
- /*create user*/
- this.createCurrentPlayer();
-
- this.input.keyboard.on("keyup-ENTER", () => {
- return this.nextSceneToCameraScene();
+ this.charactersDraggableGrid = new DraggableGrid(this, {
+ position: { x: 0, y: 0 },
+ maskPosition: { x: 0, y: 0 },
+ dimension: { x: 485, y: 165 },
+ horizontal: true,
+ repositionToCenter: true,
+ itemsInRow: 1,
+ margin: {
+ left: ((innerWidth - 200) / waScaleManager.getActualZoom()) * 0.5,
+ right: ((innerWidth - 200) / waScaleManager.getActualZoom()) * 0.5,
+ },
+ spacing: 5,
+ debug: {
+ showDraggableSpace: false,
+ },
});
- this.input.keyboard.on("keydown-RIGHT", () => {
- this.moveToRight();
- });
- this.input.keyboard.on("keydown-LEFT", () => {
- this.moveToLeft();
- });
- this.input.keyboard.on("keydown-UP", () => {
- this.moveToUp();
- });
- this.input.keyboard.on("keydown-DOWN", () => {
- this.moveToDown();
- });
+ this.bindEventHandlers();
+
+ this.onResize();
}
public nextSceneToCameraScene(): void {
- if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
+ if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) {
return;
}
- if (!this.selectedPlayer) {
+ if (!this.selectedWoka) {
return;
}
analyticsClient.validationWoka("SelectWoka");
+ gameManager.setCharacterLayers([this.selectedWoka.texture.key]);
+ this.selectedWoka = null;
this.scene.stop(SelectCharacterSceneName);
- waScaleManager.restoreZoom();
- gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
gameManager.tryResumingGame(EnableCameraSceneName);
- this.players = [];
selectCharacterSceneVisibleStore.set(false);
this.events.removeListener("wake");
}
public nextSceneToCustomizeScene(): void {
- if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
+ if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) {
return;
}
+ this.selectedWoka = null;
this.scene.sleep(SelectCharacterSceneName);
- waScaleManager.restoreZoom();
this.scene.run(CustomizeSceneName);
selectCharacterSceneVisibleStore.set(false);
}
- createCurrentPlayer(): void {
- 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;
- }
-
- const [middleX, middleY] = this.getCharacterPosition();
- const player = this.physics.add.sprite(middleX, middleY, playerResource.id, 0);
- this.setUpPlayer(player, i);
- this.anims.create({
- key: playerResource.id,
- frames: this.anims.generateFrameNumbers(playerResource.id, { start: 0, end: 11 }),
- frameRate: 8,
- repeat: -1,
- });
- player.setInteractive().on("pointerdown", () => {
- if (this.pointerClicked) {
- return;
- }
- if (this.currentSelectUser === i) {
- return;
- }
- //To not trigger two time the pointerdown events :
- // We set a boolean to true so that pointerdown events does nothing when the boolean is true
- // We set a timer that we decrease in update function to not trigger the pointerdown events twice
- this.pointerClicked = true;
- this.pointerTimer = 250;
- this.currentSelectUser = i;
- this.moveUser();
- });
- this.players.push(player);
- }
- if (this.currentSelectUser >= this.players.length) {
- this.currentSelectUser = 0;
- }
- this.selectedPlayer = this.players[this.currentSelectUser];
- this.selectedPlayer.play(this.playerModels[this.currentSelectUser].id);
- }
-
- protected moveUser() {
- for (let i = 0; i < this.players.length; i++) {
- const player = this.players[i];
- this.setUpPlayer(player, i);
- }
- this.updateSelectedPlayer();
- }
-
- public moveToLeft() {
- if (this.currentSelectUser === 0) {
- return;
- }
- this.currentSelectUser -= 1;
- this.moveUser();
- }
-
- public moveToRight() {
- if (this.currentSelectUser === this.players.length - 1) {
- return;
- }
- this.currentSelectUser += 1;
- this.moveUser();
- }
-
- protected moveToUp() {
- if (this.currentSelectUser < this.nbCharactersPerRow) {
- return;
- }
- this.currentSelectUser -= this.nbCharactersPerRow;
- this.moveUser();
- }
-
- protected moveToDown() {
- if (this.currentSelectUser + this.nbCharactersPerRow > this.players.length - 1) {
- return;
- }
- this.currentSelectUser += this.nbCharactersPerRow;
- this.moveUser();
- }
-
- protected defineSetupPlayer(num: number) {
- const deltaX = 32;
- const deltaY = 32;
- let [playerX, playerY] = this.getCharacterPosition(); // player X and player y are middle of the
-
- playerX = playerX - deltaX * 2.5 + deltaX * (num % this.nbCharactersPerRow); // calcul position on line users
- playerY = playerY - deltaY * 2 + deltaY * Math.floor(num / this.nbCharactersPerRow); // calcul position on column users
-
- const playerVisible = true;
- const playerScale = 1;
- const playerOpacity = 1;
-
- // if selected
- if (num === this.currentSelectUser) {
- this.selectedRectangle.setX(playerX);
- this.selectedRectangle.setY(playerY);
- }
-
- return { playerX, playerY, playerScale, playerOpacity, playerVisible };
- }
-
- protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, num: number) {
- const { playerX, playerY, playerScale, playerOpacity, playerVisible } = this.defineSetupPlayer(num);
- player.setBounce(0.2);
- player.setCollideWorldBounds(false);
- player.setVisible(playerVisible);
- player.setScale(playerScale, playerScale);
- player.setAlpha(playerOpacity);
- player.setX(playerX);
- player.setY(playerY);
- }
-
- /**
- * Returns pixel position by on column and row number
- */
- protected getCharacterPosition(): [number, number] {
- return [this.game.renderer.width / 2, this.game.renderer.height / 2.5];
- }
-
- protected updateSelectedPlayer(): void {
- this.selectedPlayer?.anims?.pause(this.selectedPlayer?.anims.currentAnim.frames[0]);
- const player = this.players[this.currentSelectUser];
- player?.play(this.playerModels[this.currentSelectUser].id);
- this.selectedPlayer = player;
- localUserStore.setPlayerCharacterIndex(this.currentSelectUser);
- }
-
- update(time: number, delta: number): void {
- // pointerTimer is set to 250 when pointerdown events is trigger
- // After 250ms, pointerClicked is set to false and the pointerdown events can be trigger again
- this.pointerTimer -= delta;
- if (this.pointerTimer <= 0) {
- this.pointerClicked = false;
- }
-
+ public update(): void {
if (this.lazyloadingAttempt) {
- //re-render players list
- this.createCurrentPlayer();
- this.moveUser();
this.lazyloadingAttempt = false;
}
}
public onResize(): void {
- //move position of user
- this.moveUser();
+ this.handleCharactersGridOnResize();
+ }
+
+ public getSelectedCollectionName(): string {
+ return this.collectionKeys[this.selectedCollectionIndex] ?? "";
+ }
+
+ public getCollectionKeysSize(): number {
+ return this.playerTextures.getCollectionsKeys().length;
+ }
+
+ public selectPreviousCollection(): void {
+ this.selectedCollectionIndex = (this.selectedCollectionIndex + 1) % this.collectionKeys.length;
+ selectedCollection.set(this.getSelectedCollectionName());
+ this.populateGrid();
+ }
+
+ public selectNextCollection(): void {
+ if (this.collectionKeys.length === 1) {
+ return;
+ }
+ this.selectedCollectionIndex =
+ this.selectedCollectionIndex - 1 < 0 ? this.collectionKeys.length - 1 : this.selectedCollectionIndex - 1;
+ selectedCollection.set(this.getSelectedCollectionName());
+ this.populateGrid();
+ }
+
+ private handleCharactersGridOnResize(): void {
+ const ratio = innerHeight / innerWidth;
+ this.gridRowsCount = ratio > 1 || innerHeight > 900 ? 2 : 1;
+ const gridHeight = this.gridRowsCount === 2 ? 210 : 105;
+ const gridWidth = innerWidth / 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 * (ratio > 1 ? 0.5 : 0.575),
+ };
+
+ try {
+ this.charactersDraggableGrid.changeDraggableSpacePosAndSize(
+ gridPos,
+ { x: gridWidth, y: gridHeight },
+ gridPos
+ );
+ } catch (error) {
+ console.warn(error);
+ }
+ this.charactersDraggableGrid.setItemsInRow(this.gridRowsCount);
+ this.populateGrid();
+ }
+
+ private populateGrid(): void {
+ const wokaDimension = 100;
+
+ this.selectedWoka = null;
+ this.charactersDraggableGrid.clearAllItems();
+ const textures = this.playerTextures.getWokaCollectionTextures(this.getSelectedCollectionName());
+ for (let i = 0; i < textures.length; i += 1) {
+ const slot = new WokaSlot(this, textures[i].id).setDisplaySize(wokaDimension, wokaDimension);
+ this.charactersDraggableGrid.addItem(slot);
+ }
+ this.charactersDraggableGrid.moveContentToBeginning();
+ void this.charactersDraggableGrid.moveContentTo(0.5, textures.length * 50);
+ }
+
+ private bindEventHandlers(): void {
+ this.bindKeyboardEventHandlers();
+ this.events.addListener("wake", () => {
+ selectCharacterSceneVisibleStore.set(true);
+ });
+
+ this.input.keyboard.on("keyup-ENTER", () => {
+ return this.nextSceneToCameraScene();
+ });
+
+ this.charactersDraggableGrid.on(DraggableGridEvent.ItemClicked, (item: WokaSlot) => {
+ this.selectGridItem(item);
+ });
+ }
+
+ private selectGridItem(item: WokaSlot): void {
+ this.selectedGridItemIndex = this.charactersDraggableGrid.getAllItems().indexOf(item);
+ if (this.charactersDraggableGrid.getDraggableSpaceWidth() < this.charactersDraggableGrid.getGridSize().x) {
+ void this.charactersDraggableGrid.centerOnItem(this.selectedGridItemIndex, 500);
+ }
+ this.charactersDraggableGrid.getAllItems().forEach((slot) => (slot as WokaSlot).select(false));
+ this.selectedWoka?.stop()?.setFrame(0);
+ this.selectedWoka = item.getSprite();
+ const wokaKey = this.selectedWoka.texture.key;
+ this.createWokaAnimation(wokaKey);
+ this.selectedWoka.play(wokaKey);
+ item.select(true);
+ }
+
+ private bindKeyboardEventHandlers(): void {
+ this.input.keyboard.on("keyup-SPACE", () => {
+ this.selectNextCollection();
+ });
+ this.input.keyboard.on("keydown-LEFT", () => {
+ this.selectNextGridItem(true, true);
+ });
+ this.input.keyboard.on("keydown-RIGHT", () => {
+ this.selectNextGridItem(false, true);
+ });
+ this.input.keyboard.on("keydown-UP", () => {
+ this.selectNextGridItem(true, false);
+ });
+ this.input.keyboard.on("keydown-DOWN", () => {
+ this.selectNextGridItem(false, false);
+ });
+ this.input.keyboard.on("keydown-W", () => {
+ this.selectNextGridItem(true, false);
+ });
+ this.input.keyboard.on("keydown-S", () => {
+ this.selectNextGridItem(false, false);
+ });
+ this.input.keyboard.on("keydown-A", () => {
+ this.selectNextGridItem(true, true);
+ });
+ this.input.keyboard.on("keydown-D", () => {
+ this.selectNextGridItem(false, true);
+ });
+ }
+
+ private selectNextGridItem(previous: boolean = false, horizontally: boolean): void {
+ if (this.selectedGridItemIndex === undefined) {
+ this.selectedGridItemIndex = 0;
+ }
+ if (
+ previous
+ ? this.selectedGridItemIndex > 0
+ : this.selectedGridItemIndex < this.charactersDraggableGrid.getAllItems().length - 1
+ ) {
+ // NOTE: getItemsInRowCount() not working properly. Fix on lib side needed
+ const jump = horizontally ? this.gridRowsCount : 1;
+ const item = this.charactersDraggableGrid.getAllItems()[
+ this.selectedGridItemIndex + (previous ? -jump : jump)
+ ] as WokaSlot;
+ if (!item) {
+ return;
+ }
+ this.selectedGridItemIndex += previous ? -1 : 1;
+ this.selectGridItem(item);
+ }
+ }
+
+ private createWokaAnimation(key: string): void {
+ this.anims.create({
+ key,
+ frames: this.anims.generateFrameNumbers(key, { start: 0, end: 11 }),
+ frameRate: 8,
+ repeat: -1,
+ });
}
private isCustomizationAvailable(): boolean {
diff --git a/front/src/Stores/SelectCharacterSceneStore.ts b/front/src/Stores/SelectCharacterSceneStore.ts
index 654da03c..34ca93d4 100644
--- a/front/src/Stores/SelectCharacterSceneStore.ts
+++ b/front/src/Stores/SelectCharacterSceneStore.ts
@@ -1,3 +1,5 @@
import { writable } from "svelte/store";
export const customizeAvailableStore = writable(false);
+
+export const selectedCollection = writable();
diff --git a/front/src/index.ts b/front/src/index.ts
index d45829b5..11929f8d 100644
--- a/front/src/index.ts
+++ b/front/src/index.ts
@@ -17,14 +17,12 @@ import { localUserStore } from "./Connexion/LocalUserStore";
import { ErrorScene } from "./Phaser/Reconnecting/ErrorScene";
import { iframeListener } from "./Api/IframeListener";
import { desktopApi } from "./Api/desktop/index";
-import { SelectCharacterMobileScene } from "./Phaser/Login/SelectCharacterMobileScene";
import { HdpiManager } from "./Phaser/Services/HdpiManager";
import { waScaleManager } from "./Phaser/Services/WaScaleManager";
import { Game } from "./Phaser/Game/Game";
import App from "./Components/App.svelte";
import { HtmlUtils } from "./WebRtc/HtmlUtils";
import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer;
-import { isMediaBreakpointUp } from "./Utils/BreakpointsUtils";
const { width, height } = coWebsiteManager.getGameSize();
const valueGameQuality = localUserStore.getGameQualityValue();
@@ -91,7 +89,7 @@ const config: GameConfig = {
scene: [
EntryScene,
LoginScene,
- isMediaBreakpointUp("md") ? SelectCharacterMobileScene : SelectCharacterScene,
+ SelectCharacterScene,
SelectCompanionScene,
EnableCameraScene,
ReconnectingScene,
diff --git a/package.json b/package.json
index 038edf2c..ff6c2a33 100644
--- a/package.json
+++ b/package.json
@@ -4,5 +4,6 @@
},
"scripts": {
"prepare": "husky install"
- }
+ },
+ "dependencies": {}
}
diff --git a/tests/tests/utils/roles.ts b/tests/tests/utils/roles.ts
index b4d3b8af..7e8ebe20 100644
--- a/tests/tests/utils/roles.ts
+++ b/tests/tests/utils/roles.ts
@@ -11,8 +11,9 @@ export async function login(
await page.fill('input[name="loginSceneName"]', userName);
await page.click('button.loginSceneFormSubmit');
+ await page.waitForTimeout(1000);
for (let i = 0; i < characterNumber; i++) {
- await page.click('button.selectCharacterButtonRight');
+ await page.keyboard.press('ArrowRight');
}
await page.click('button.selectCharacterSceneFormSubmit');