Files
partey_workadventure/front/src/Phaser/Login/SelectCharacterScene.ts
T
2022-04-25 17:16:21 +02:00

313 lines
12 KiB
TypeScript

import { gameManager } from "../Game/GameManager";
import { EnableCameraSceneName } from "./EnableCameraScene";
import { CustomizeSceneName } from "./CustomizeScene";
import { localUserStore } from "../../Connexion/LocalUserStore";
import { loadAllDefaultModels } from "../Entity/PlayerTexturesLoadingManager";
import { Loader } from "../Components/Loader";
import { BodyResourceDescriptionInterface, PlayerTextures } from "../Entity/PlayerTextures";
import { AbstractCharacterScene } from "./AbstractCharacterScene";
import { areCharacterLayersValid } from "../../Connexion/LocalUser";
import { touchScreenManager } from "../../Touch/TouchScreenManager";
import { PinchManager } from "../UserInput/PinchManager";
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
import { waScaleManager } from "../Services/WaScaleManager";
import { analyticsClient } from "../../Administration/AnalyticsClient";
import { PUSHER_URL } from "../../Enum/EnvironmentVariable";
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";
import { myCameraVisibilityStore } from "../../Stores/MyCameraStoreVisibility";
//todo: put this constants in a dedicated file
export const SelectCharacterSceneName = "SelectCharacterScene";
export class SelectCharacterScene extends AbstractCharacterScene {
protected selectedWoka!: Phaser.GameObjects.Sprite | null; // null if we are selecting the "customize" option
protected playerModels!: BodyResourceDescriptionInterface[];
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;
constructor() {
super({
key: SelectCharacterSceneName,
});
this.loader = new Loader(this);
this.playerTextures = new PlayerTextures();
}
public preload() {
super.preload();
const wokaMetadataKey = "woka-list" + gameManager.currentStartedRoom.href;
this.cache.json.remove(wokaMetadataKey);
this.superLoad
.json(
wokaMetadataKey,
`${PUSHER_URL}/woka/list?roomUrl=` + encodeURIComponent(gameManager.currentStartedRoom.href),
undefined,
{
responseType: "text",
headers: {
Authorization: localUserStore.getAuthToken() ?? "",
},
withCredentials: true,
},
(key, type, data) => {
this.playerTextures.loadPlayerTexturesMetadata(wokaList.parse(data));
this.playerModels = loadAllDefaultModels(this.load, this.playerTextures);
this.lazyloadingAttempt = false;
}
)
.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();
}
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);
if (touchScreenManager.supportTouchScreen) {
new PinchManager(this);
}
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.bindEventHandlers();
this.onResize();
}
public nextSceneToCameraScene(): void {
if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) {
return;
}
if (!this.selectedWoka) {
return;
}
analyticsClient.validationWoka("SelectWoka");
gameManager.setCharacterLayers([this.selectedWoka.texture.key]);
this.selectedWoka = null;
this.scene.stop(SelectCharacterSceneName);
gameManager.tryResumingGame(EnableCameraSceneName);
selectCharacterSceneVisibleStore.set(false);
this.events.removeListener("wake");
}
public nextSceneToCustomizeScene(): void {
if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) {
return;
}
this.selectedWoka = null;
myCameraVisibilityStore.set(false);
this.scene.sleep(SelectCharacterSceneName);
this.scene.run(CustomizeSceneName);
selectCharacterSceneVisibleStore.set(false);
}
public update(): void {
if (this.lazyloadingAttempt) {
this.lazyloadingAttempt = false;
}
}
public onResize(): void {
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 {
for (const layer of this.playerTextures.getLayers()) {
if (Object.keys(layer).length > 0) {
return true;
}
}
return false;
}
}