Merge branch 'develop' of github.com:thecodingmachine/workadventure into develop
This commit is contained in:
@@ -15,6 +15,7 @@ import { TexturesHelper } from "../Helpers/TexturesHelper";
|
||||
import type { PictureStore } from "../../Stores/PictureStore";
|
||||
import { Unsubscriber, Writable, writable } from "svelte/store";
|
||||
import { createColorStore } from "../../Stores/OutlineColorStore";
|
||||
import type { OutlineableInterface } from "../Game/OutlineableInterface";
|
||||
import type CancelablePromise from "cancelable-promise";
|
||||
|
||||
const playerNameY = -25;
|
||||
@@ -29,14 +30,15 @@ interface AnimationData {
|
||||
|
||||
const interactiveRadius = 35;
|
||||
|
||||
export abstract class Character extends Container {
|
||||
export abstract class Character extends Container implements OutlineableInterface {
|
||||
private bubble: SpeechBubble | null = null;
|
||||
private readonly playerName: Text;
|
||||
public PlayerValue: string;
|
||||
private readonly playerNameText: Text;
|
||||
public playerName: string;
|
||||
public sprites: Map<string, Sprite>;
|
||||
protected lastDirection: PlayerAnimationDirections = PlayerAnimationDirections.Down;
|
||||
//private teleportation: Sprite;
|
||||
private invisible: boolean;
|
||||
private clickable: boolean;
|
||||
public companion?: Companion;
|
||||
private emote: Phaser.GameObjects.Text | null = null;
|
||||
private emoteTween: Phaser.Tweens.Tween | null = null;
|
||||
@@ -61,8 +63,9 @@ export abstract class Character extends Container {
|
||||
) {
|
||||
super(scene, x, y /*, texture, frame*/);
|
||||
this.scene = scene;
|
||||
this.PlayerValue = name;
|
||||
this.playerName = name;
|
||||
this.invisible = true;
|
||||
this.clickable = false;
|
||||
|
||||
this.sprites = new Map<string, Sprite>();
|
||||
this._pictureStore = writable(undefined);
|
||||
@@ -88,7 +91,7 @@ export abstract class Character extends Container {
|
||||
this.texturePromise = undefined;
|
||||
});
|
||||
|
||||
this.playerName = new Text(scene, 0, playerNameY, name, {
|
||||
this.playerNameText = new Text(scene, 0, playerNameY, name, {
|
||||
fontFamily: '"Press Start 2P"',
|
||||
fontSize: "8px",
|
||||
strokeThickness: 2,
|
||||
@@ -99,30 +102,17 @@ export abstract class Character extends Container {
|
||||
fontSize: 35,
|
||||
},
|
||||
});
|
||||
this.playerName.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX);
|
||||
this.add(this.playerName);
|
||||
this.playerNameText.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX);
|
||||
this.add(this.playerNameText);
|
||||
|
||||
if (isClickable) {
|
||||
this.setInteractive({
|
||||
hitArea: new Phaser.Geom.Circle(0, 0, interactiveRadius),
|
||||
hitAreaCallback: Phaser.Geom.Circle.Contains, //eslint-disable-line @typescript-eslint/unbound-method
|
||||
useHandCursor: true,
|
||||
});
|
||||
|
||||
this.on("pointerover", () => {
|
||||
this.outlineColorStore.pointerOver();
|
||||
});
|
||||
this.on("pointerout", () => {
|
||||
this.outlineColorStore.pointerOut();
|
||||
});
|
||||
}
|
||||
this.setClickable(isClickable);
|
||||
|
||||
this.outlineColorStoreUnsubscribe = this.outlineColorStore.subscribe((color) => {
|
||||
if (color === undefined) {
|
||||
this.getOutlinePlugin()?.remove(this.playerName);
|
||||
this.getOutlinePlugin()?.remove(this.playerNameText);
|
||||
} else {
|
||||
this.getOutlinePlugin()?.remove(this.playerName);
|
||||
this.getOutlinePlugin()?.add(this.playerName, {
|
||||
this.getOutlinePlugin()?.remove(this.playerNameText);
|
||||
this.getOutlinePlugin()?.add(this.playerNameText, {
|
||||
thickness: 2,
|
||||
outlineColor: color,
|
||||
});
|
||||
@@ -145,6 +135,34 @@ export abstract class Character extends Container {
|
||||
}
|
||||
}
|
||||
|
||||
public setClickable(clickable: boolean = true): void {
|
||||
if (this.clickable === clickable) {
|
||||
return;
|
||||
}
|
||||
this.clickable = clickable;
|
||||
if (clickable) {
|
||||
this.setInteractive({
|
||||
hitArea: new Phaser.Geom.Circle(0, 0, interactiveRadius),
|
||||
hitAreaCallback: Phaser.Geom.Circle.Contains, //eslint-disable-line @typescript-eslint/unbound-method
|
||||
useHandCursor: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.disableInteractive();
|
||||
}
|
||||
|
||||
public isClickable() {
|
||||
return this.clickable;
|
||||
}
|
||||
|
||||
public getPosition(): { x: number; y: number } {
|
||||
return { x: this.x, y: this.y };
|
||||
}
|
||||
|
||||
public getObjectToOutline(): Phaser.GameObjects.GameObject {
|
||||
return this.playerNameText;
|
||||
}
|
||||
|
||||
private async getSnapshot(): Promise<string> {
|
||||
const sprites = Array.from(this.sprites.values()).map((sprite) => {
|
||||
return { sprite, frame: 1 };
|
||||
@@ -411,18 +429,42 @@ export abstract class Character extends Container {
|
||||
private destroyEmote() {
|
||||
this.emote?.destroy();
|
||||
this.emote = null;
|
||||
this.playerName.setVisible(true);
|
||||
this.playerNameText.setVisible(true);
|
||||
}
|
||||
|
||||
public get pictureStore(): PictureStore {
|
||||
return this._pictureStore;
|
||||
}
|
||||
|
||||
public setOutlineColor(color: number): void {
|
||||
this.outlineColorStore.setColor(color);
|
||||
public setFollowOutlineColor(color: number): void {
|
||||
this.outlineColorStore.setFollowColor(color);
|
||||
}
|
||||
|
||||
public removeOutlineColor(): void {
|
||||
this.outlineColorStore.removeColor();
|
||||
public removeFollowOutlineColor(): void {
|
||||
this.outlineColorStore.removeFollowColor();
|
||||
}
|
||||
|
||||
public setApiOutlineColor(color: number): void {
|
||||
this.outlineColorStore.setApiColor(color);
|
||||
}
|
||||
|
||||
public removeApiOutlineColor(): void {
|
||||
this.outlineColorStore.removeApiColor();
|
||||
}
|
||||
|
||||
public pointerOverOutline(): void {
|
||||
this.outlineColorStore.pointerOver();
|
||||
}
|
||||
|
||||
public pointerOutOutline(): void {
|
||||
this.outlineColorStore.pointerOut();
|
||||
}
|
||||
|
||||
public characterCloseByOutline(): void {
|
||||
this.outlineColorStore.characterCloseBy();
|
||||
}
|
||||
|
||||
public characterFarAwayOutline(): void {
|
||||
this.outlineColorStore.characterFarAway();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import { requestVisitCardsStore } from "../../Stores/GameStore";
|
||||
import { ActionsMenuData, actionsMenuStore } from "../../Stores/ActionsMenuStore";
|
||||
import { Character } from "../Entity/Character";
|
||||
import type { GameScene } from "../Game/GameScene";
|
||||
import type { PointInterface } from "../../Connexion/ConnexionModels";
|
||||
import { Character } from "../Entity/Character";
|
||||
import type { PlayerAnimationDirections } from "../Player/Animation";
|
||||
import { requestVisitCardsStore } from "../../Stores/GameStore";
|
||||
import type { Unsubscriber } from "svelte/store";
|
||||
import type { ActivatableInterface } from "../Game/ActivatableInterface";
|
||||
import type CancelablePromise from "cancelable-promise";
|
||||
|
||||
/**
|
||||
* Class representing the sprite of a remote player (a player that plays on another computer)
|
||||
*/
|
||||
export class RemotePlayer extends Character {
|
||||
userId: number;
|
||||
export class RemotePlayer extends Character implements ActivatableInterface {
|
||||
public userId: number;
|
||||
public readonly activationRadius: number;
|
||||
|
||||
private registeredActions: { actionName: string; callback: Function }[];
|
||||
private visitCardUrl: string | null;
|
||||
private isActionsMenuInitialized: boolean = false;
|
||||
private actionsMenuStoreUnsubscriber: Unsubscriber;
|
||||
|
||||
constructor(
|
||||
userId: number,
|
||||
@@ -23,34 +31,26 @@ export class RemotePlayer extends Character {
|
||||
moving: boolean,
|
||||
visitCardUrl: string | null,
|
||||
companion: string | null,
|
||||
companionTexturePromise?: Promise<string>
|
||||
companionTexturePromise?: Promise<string>,
|
||||
activationRadius?: number
|
||||
) {
|
||||
super(
|
||||
Scene,
|
||||
x,
|
||||
y,
|
||||
texturesPromise,
|
||||
name,
|
||||
direction,
|
||||
moving,
|
||||
1,
|
||||
!!visitCardUrl,
|
||||
companion,
|
||||
companionTexturePromise
|
||||
);
|
||||
super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise);
|
||||
|
||||
//set data
|
||||
this.userId = userId;
|
||||
this.registeredActions = [];
|
||||
this.registerDefaultActionsMenuActions();
|
||||
this.setClickable(this.registeredActions.length > 0);
|
||||
this.activationRadius = activationRadius ?? 96;
|
||||
this.visitCardUrl = visitCardUrl;
|
||||
|
||||
this.on("pointerdown", (event: Phaser.Input.Pointer) => {
|
||||
if (event.downElement.nodeName === "CANVAS") {
|
||||
requestVisitCardsStore.set(this.visitCardUrl);
|
||||
}
|
||||
this.actionsMenuStoreUnsubscriber = actionsMenuStore.subscribe((value: ActionsMenuData | undefined) => {
|
||||
this.isActionsMenuInitialized = value ? true : false;
|
||||
});
|
||||
|
||||
this.bindEventHandlers();
|
||||
}
|
||||
|
||||
updatePosition(position: PointInterface): void {
|
||||
public updatePosition(position: PointInterface): void {
|
||||
this.playAnimation(position.direction as PlayerAnimationDirections, position.moving);
|
||||
this.setX(position.x);
|
||||
this.setY(position.y);
|
||||
@@ -61,4 +61,66 @@ export class RemotePlayer extends Character {
|
||||
this.companion.setTarget(position.x, position.y, position.direction as PlayerAnimationDirections);
|
||||
}
|
||||
}
|
||||
|
||||
public registerActionsMenuAction(action: { actionName: string; callback: Function }): void {
|
||||
this.registeredActions.push(action);
|
||||
this.updateIsClickable();
|
||||
}
|
||||
|
||||
public unregisterActionsMenuAction(actionName: string) {
|
||||
const index = this.registeredActions.findIndex((action) => action.actionName === actionName);
|
||||
if (index !== -1) {
|
||||
this.registeredActions.splice(index, 1);
|
||||
}
|
||||
this.updateIsClickable();
|
||||
}
|
||||
|
||||
public activate(): void {
|
||||
this.toggleActionsMenu();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.actionsMenuStoreUnsubscriber();
|
||||
actionsMenuStore.clear();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public isActivatable(): boolean {
|
||||
return this.isClickable();
|
||||
}
|
||||
|
||||
private updateIsClickable(): void {
|
||||
this.setClickable(this.registeredActions.length > 0);
|
||||
}
|
||||
|
||||
private toggleActionsMenu(): void {
|
||||
if (this.isActionsMenuInitialized) {
|
||||
actionsMenuStore.clear();
|
||||
return;
|
||||
}
|
||||
actionsMenuStore.initialize(this.playerName);
|
||||
for (const action of this.registeredActions) {
|
||||
actionsMenuStore.addAction(action.actionName, action.callback);
|
||||
}
|
||||
}
|
||||
|
||||
private registerDefaultActionsMenuActions(): void {
|
||||
if (this.visitCardUrl) {
|
||||
this.registeredActions.push({
|
||||
actionName: "Visiting Card",
|
||||
callback: () => {
|
||||
requestVisitCardsStore.set(this.visitCardUrl);
|
||||
actionsMenuStore.clear();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private bindEventHandlers(): void {
|
||||
this.on(Phaser.Input.Events.POINTER_DOWN, (event: Phaser.Input.Pointer) => {
|
||||
if (event.downElement.nodeName === "CANVAS") {
|
||||
this.toggleActionsMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user