better woka preview, wip

This commit is contained in:
Piotr 'pwh' Hanusiak 2022-03-11 13:36:55 +01:00
parent 9f823506b9
commit 138e8aece4
7 changed files with 240 additions and 171 deletions

View File

@ -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);
}
}

View File

@ -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()) {

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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,
},
];
}