From fd012d6c699c65bd18fbf3d27f6fd02a6cf53bec Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Mon, 24 Jan 2022 16:27:57 +0100 Subject: [PATCH 01/20] ActionsMenu WIP --- .../Components/ActionsMenu/ActionsMenu.svelte | 69 +++++++++++++++++++ front/src/Components/App.svelte | 6 +- front/src/Phaser/Entity/RemotePlayer.ts | 5 +- front/src/Phaser/Game/GameScene.ts | 1 + front/src/Stores/GameStore.ts | 2 + 5 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 front/src/Components/ActionsMenu/ActionsMenu.svelte diff --git a/front/src/Components/ActionsMenu/ActionsMenu.svelte b/front/src/Components/ActionsMenu/ActionsMenu.svelte new file mode 100644 index 00000000..3f60e4d8 --- /dev/null +++ b/front/src/Components/ActionsMenu/ActionsMenu.svelte @@ -0,0 +1,69 @@ + + + + +
+ +

Actions

+ +
+ + \ No newline at end of file diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index a1277ed2..ef097ce3 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -17,7 +17,7 @@ import { loginSceneVisibleStore } from "../Stores/LoginSceneStore"; import EnableCameraScene from "./EnableCamera/EnableCameraScene.svelte"; import VisitCard from "./VisitCard/VisitCard.svelte"; - import { requestVisitCardsStore } from "../Stores/GameStore"; + import { requestVisitCardsStore, requestActionsMenuStore } from "../Stores/GameStore"; import type { Game } from "../Phaser/Game/Game"; import { chatVisibilityStore } from "../Stores/ChatStore"; @@ -48,6 +48,7 @@ import { followStateStore } from "../Stores/FollowStore"; import { peerStore } from "../Stores/PeerStore"; import FollowMenu from "./FollowMenu/FollowMenu.svelte"; +import ActionsMenu from './ActionsMenu/ActionsMenu.svelte'; export let game: Game; @@ -152,6 +153,9 @@ {#if $requestVisitCardsStore} {/if} + {#if $requestActionsMenuStore} + + {/if} {#if $errorStore.length > 0}
diff --git a/front/src/Phaser/Entity/RemotePlayer.ts b/front/src/Phaser/Entity/RemotePlayer.ts index 1cd03d12..428bd8aa 100644 --- a/front/src/Phaser/Entity/RemotePlayer.ts +++ b/front/src/Phaser/Entity/RemotePlayer.ts @@ -2,7 +2,7 @@ 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 { requestVisitCardsStore, requestActionsMenuStore } from "../../Stores/GameStore"; /** * Class representing the sprite of a remote player (a player that plays on another computer) @@ -44,7 +44,8 @@ export class RemotePlayer extends Character { this.on("pointerdown", (event: Phaser.Input.Pointer) => { if (event.downElement.nodeName === "CANVAS") { - requestVisitCardsStore.set(this.visitCardUrl); + // requestVisitCardsStore.set(this.visitCardUrl); + requestActionsMenuStore.set(true); } }); } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 05c0483f..f530af81 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1915,6 +1915,7 @@ ${escapedMessage} } const texturesPromise = lazyLoadPlayerCharacterTextures(this.load, addPlayerData.characterLayers); + console.log(addPlayerData); const player = new RemotePlayer( addPlayerData.userId, this, diff --git a/front/src/Stores/GameStore.ts b/front/src/Stores/GameStore.ts index e5298b7c..a8000bab 100644 --- a/front/src/Stores/GameStore.ts +++ b/front/src/Stores/GameStore.ts @@ -4,6 +4,8 @@ export const userMovingStore = writable(false); export const requestVisitCardsStore = writable(null); +export const requestActionsMenuStore = writable(true); + export const userIsAdminStore = writable(false); export const limitMapStore = writable(false); From 67627637aaeb0492c8234669c36ec1d94fdfd9a9 Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Tue, 25 Jan 2022 13:42:41 +0100 Subject: [PATCH 02/20] added store with actions for actionsMenu --- .../Components/ActionsMenu/ActionsMenu.svelte | 26 +++++++------- front/src/Phaser/Entity/RemotePlayer.ts | 26 +++++++++++++- front/src/Stores/ActionsMenuStore.ts | 36 +++++++++++++++++++ front/src/Stores/GameStore.ts | 2 +- 4 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 front/src/Stores/ActionsMenuStore.ts diff --git a/front/src/Components/ActionsMenu/ActionsMenu.svelte b/front/src/Components/ActionsMenu/ActionsMenu.svelte index 3f60e4d8..06eee23d 100644 --- a/front/src/Components/ActionsMenu/ActionsMenu.svelte +++ b/front/src/Components/ActionsMenu/ActionsMenu.svelte @@ -1,8 +1,12 @@ @@ -26,13 +26,15 @@

Actions

diff --git a/front/src/Phaser/Entity/RemotePlayer.ts b/front/src/Phaser/Entity/RemotePlayer.ts index 428bd8aa..8e162632 100644 --- a/front/src/Phaser/Entity/RemotePlayer.ts +++ b/front/src/Phaser/Entity/RemotePlayer.ts @@ -3,6 +3,7 @@ import type { PointInterface } from "../../Connexion/ConnexionModels"; import { Character } from "../Entity/Character"; import type { PlayerAnimationDirections } from "../Player/Animation"; import { requestVisitCardsStore, requestActionsMenuStore } from "../../Stores/GameStore"; +import { actionsMenuStore } from '../../Stores/ActionsMenuStore'; /** * Class representing the sprite of a remote player (a player that plays on another computer) @@ -44,7 +45,30 @@ export class RemotePlayer extends Character { this.on("pointerdown", (event: Phaser.Input.Pointer) => { if (event.downElement.nodeName === "CANVAS") { - // requestVisitCardsStore.set(this.visitCardUrl); + actionsMenuStore.addPossibleAction( + "visit-card", + "Visiting Card", () => { + requestVisitCardsStore.set(this.visitCardUrl); + actionsMenuStore.clearActions(); + requestActionsMenuStore.set(false); + }); + actionsMenuStore.addPossibleAction( + "log-hello", + "Log Hello", () => { + console.log('HELLO'); + // requestActionsMenuStore.set(false); + }); + actionsMenuStore.addPossibleAction( + "log-goodbye", + "Log Goodbye", () => { + console.log('GOODBYE'); + // requestActionsMenuStore.set(false); + }); + actionsMenuStore.addPossibleAction( + "clear", + "Clear Actions", () => { + actionsMenuStore.clearActions(); + }); requestActionsMenuStore.set(true); } }); diff --git a/front/src/Stores/ActionsMenuStore.ts b/front/src/Stores/ActionsMenuStore.ts new file mode 100644 index 00000000..c3c2b56b --- /dev/null +++ b/front/src/Stores/ActionsMenuStore.ts @@ -0,0 +1,36 @@ +import { writable } from "svelte/store"; + +export interface ActionsMenuInterface { + displayName: string; + callback: Function; +} + +function createActionsMenuStore() { + + const actions = new Map(); + const { subscribe, update, set } = writable>(actions); + + return { + subscribe, + addPossibleAction: (key: string, displayName: string, callback: Function) => { + update((actions) => { + actions.set(key, { displayName, callback }); + return actions; + }); + }, + removePossibleAction: (key: string) => { + update((actions) => { + actions.delete(key); + return actions; + }); + }, + /** + * Hides menu + */ + clearActions: () => { + set(new Map()); + } + }; +} + +export const actionsMenuStore = createActionsMenuStore(); \ No newline at end of file diff --git a/front/src/Stores/GameStore.ts b/front/src/Stores/GameStore.ts index a8000bab..4260f548 100644 --- a/front/src/Stores/GameStore.ts +++ b/front/src/Stores/GameStore.ts @@ -4,7 +4,7 @@ export const userMovingStore = writable(false); export const requestVisitCardsStore = writable(null); -export const requestActionsMenuStore = writable(true); +export const requestActionsMenuStore = writable(false); export const userIsAdminStore = writable(false); From 907026463d2ca7b0150a21a9cfd02a33ee084a1f Mon Sep 17 00:00:00 2001 From: Hanusiak Piotr Date: Tue, 25 Jan 2022 15:09:34 +0100 Subject: [PATCH 03/20] scrollable actions --- .../Components/ActionsMenu/ActionsMenu.svelte | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/front/src/Components/ActionsMenu/ActionsMenu.svelte b/front/src/Components/ActionsMenu/ActionsMenu.svelte index 06eee23d..04e9c381 100644 --- a/front/src/Components/ActionsMenu/ActionsMenu.svelte +++ b/front/src/Components/ActionsMenu/ActionsMenu.svelte @@ -4,6 +4,7 @@ import { requestActionsMenuStore, requestVisitCardsStore } from '../../Stores/GameStore'; let possibleActions: Map; + let backgroundHeight = 100; const unsubscribe = actionsMenuStore.subscribe(value => { possibleActions = value; }); @@ -22,10 +23,10 @@ -
+

Actions

- +
\ No newline at end of file + diff --git a/front/src/Components/MainLayout.svelte b/front/src/Components/MainLayout.svelte index 238fbf67..54fa9d3b 100644 --- a/front/src/Components/MainLayout.svelte +++ b/front/src/Components/MainLayout.svelte @@ -36,8 +36,8 @@ import LimitRoomModal from "./Modal/LimitRoomModal.svelte"; import ShareLinkMapModal from "./Modal/ShareLinkMapModal.svelte"; import { LayoutMode } from "../WebRtc/LayoutManager"; -import { actionsMenuStore } from '../Stores/ActionsMenuStore'; -import ActionsMenu from './ActionsMenu/ActionsMenu.svelte'; + import { actionsMenuStore } from "../Stores/ActionsMenuStore"; + import ActionsMenu from "./ActionsMenu/ActionsMenu.svelte"; let mainLayout: HTMLDivElement; @@ -107,7 +107,7 @@ import ActionsMenu from './ActionsMenu/ActionsMenu.svelte'; {#if $followStateStore !== "off" || $peerStore.size > 0} {/if} - + {#if $actionsMenuStore} {/if} diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index 378db15d..4465a6b6 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -15,7 +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 { OutlineableInterface } from "../Game/OutlineableInterface"; import type CancelablePromise from "cancelable-promise"; const playerNameY = -25; @@ -155,7 +155,7 @@ export abstract class Character extends Container implements OutlineableInterfac return this.clickable; } - public getPosition(): { x: number, y: number } { + public getPosition(): { x: number; y: number } { return { x: this.x, y: this.y }; } diff --git a/front/src/Phaser/Entity/RemotePlayer.ts b/front/src/Phaser/Entity/RemotePlayer.ts index 5937b4c1..df496896 100644 --- a/front/src/Phaser/Entity/RemotePlayer.ts +++ b/front/src/Phaser/Entity/RemotePlayer.ts @@ -1,23 +1,21 @@ - import { requestVisitCardsStore } from "../../Stores/GameStore"; -import { ActionsMenuData, actionsMenuStore } from '../../Stores/ActionsMenuStore'; +import { ActionsMenuData, actionsMenuStore } from "../../Stores/ActionsMenuStore"; import { Character } from "../Entity/Character"; import type { GameScene } from "../Game/GameScene"; import type { PointInterface } from "../../Connexion/ConnexionModels"; import type { PlayerAnimationDirections } from "../Player/Animation"; -import type { Unsubscriber } from 'svelte/store'; -import type { ActivatableInterface } from '../Game/ActivatableInterface'; +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 implements ActivatableInterface { - public userId: number; public readonly activationRadius: number; - - private registeredActions: { actionName: string, callback: Function }[]; + + private registeredActions: { actionName: string; callback: Function }[]; private visitCardUrl: string | null; private isActionsMenuInitialized: boolean = false; private actionsMenuStoreUnsubscriber: Unsubscriber; @@ -34,21 +32,9 @@ export class RemotePlayer extends Character implements ActivatableInterface { visitCardUrl: string | null, companion: string | null, companionTexturePromise?: Promise, - activationRadius?: number, + activationRadius?: number ) { - super( - Scene, - x, - y, - texturesPromise, - name, - direction, - moving, - 1, - true, - companion, - companionTexturePromise - ); + super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise); //set data this.userId = userId; @@ -76,13 +62,13 @@ export class RemotePlayer extends Character implements ActivatableInterface { } } - public registerActionsMenuAction(action: { actionName: string, callback: Function }): void { + 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); + const index = this.registeredActions.findIndex((action) => action.actionName === actionName); if (index !== -1) { this.registeredActions.splice(index, 1); } @@ -125,7 +111,7 @@ export class RemotePlayer extends Character implements ActivatableInterface { callback: () => { requestVisitCardsStore.set(this.visitCardUrl); actionsMenuStore.clear(); - } + }, }); } } diff --git a/front/src/Phaser/Game/ActivatableInterface.ts b/front/src/Phaser/Game/ActivatableInterface.ts index dda53c89..809a09b6 100644 --- a/front/src/Phaser/Game/ActivatableInterface.ts +++ b/front/src/Phaser/Game/ActivatableInterface.ts @@ -1,7 +1,6 @@ - export interface ActivatableInterface { readonly activationRadius: number; isActivatable: () => boolean; activate: () => void; - getPosition: () => { x: number, y: number }; + getPosition: () => { x: number; y: number }; } diff --git a/front/src/Phaser/Game/ActivatablesManager.ts b/front/src/Phaser/Game/ActivatablesManager.ts index ee801167..60e967d9 100644 --- a/front/src/Phaser/Game/ActivatablesManager.ts +++ b/front/src/Phaser/Game/ActivatablesManager.ts @@ -1,17 +1,16 @@ -import { isOutlineable } from '../../Utils/CustomTypeGuards'; -import { MathUtils } from '../../Utils/MathUtils'; -import type { Player } from '../Player/Player'; -import type { ActivatableInterface } from './ActivatableInterface'; +import { isOutlineable } from "../../Utils/CustomTypeGuards"; +import { MathUtils } from "../../Utils/MathUtils"; +import type { Player } from "../Player/Player"; +import type { ActivatableInterface } from "./ActivatableInterface"; export class ActivatablesManager { - // The item that can be selected by pressing the space key. private selectedActivatableObjectByDistance?: ActivatableInterface; private selectedActivatableObjectByPointer?: ActivatableInterface; private activatableObjectsDistances: Map = new Map(); private currentPlayer: Player; - + constructor(currentPlayer: Player) { this.currentPlayer = currentPlayer; } @@ -54,7 +53,7 @@ export class ActivatablesManager { // update value but do not change the outline if (this.selectedActivatableObjectByPointer) { this.selectedActivatableObjectByDistance = newNearestObject; - return; + return; } if (isOutlineable(this.selectedActivatableObjectByDistance)) { this.selectedActivatableObjectByDistance?.characterFarAwayOutline(); @@ -88,7 +87,7 @@ export class ActivatablesManager { public updateDistanceForSingleActivatableObject(object: ActivatableInterface): void { this.activatableObjectsDistances.set( object, - MathUtils.distanceBetween(this.currentPlayer.getPosition(), object.getPosition()), + MathUtils.distanceBetween(this.currentPlayer.getPosition(), object.getPosition()) ); } } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 6bf251c8..242d97c8 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -49,7 +49,7 @@ import { GameMapPropertiesListener } from "./GameMapPropertiesListener"; import { analyticsClient } from "../../Administration/AnalyticsClient"; import { GameMapProperties } from "./GameMapProperties"; import { PathfindingManager } from "../../Utils/PathfindingManager"; -import { ActivatablesManager } from './ActivatablesManager'; +import { ActivatablesManager } from "./ActivatablesManager"; import type { GroupCreatedUpdatedMessageInterface, MessageUserMovedInterface, @@ -805,10 +805,9 @@ export class GameScene extends DirtyScene { this.simplePeer = new SimplePeer(this.connection); userMessageManager.setReceiveBanListener(this.bannedUser.bind(this)); - this.CurrentPlayer.on( - hasMovedEventName, - (event: HasPlayerMovedEvent) => { this.handleCurrentPlayerHasMovedEvent(event); }, - ); + this.CurrentPlayer.on(hasMovedEventName, (event: HasPlayerMovedEvent) => { + this.handleCurrentPlayerHasMovedEvent(event); + }); // Set up variables manager this.sharedVariablesManager = new SharedVariablesManager( @@ -1685,7 +1684,10 @@ ${escapedMessage} //listen event to share position of user this.pushPlayerPosition(event); this.gameMap.setPosition(event.x, event.y); - this.activatablesManager.updateActivatableObjectsDistances([...Array.from(this.MapPlayersByKey.values()), ...this.actionableItems.values()]); + this.activatablesManager.updateActivatableObjectsDistances([ + ...Array.from(this.MapPlayersByKey.values()), + ...this.actionableItems.values(), + ]); this.activatablesManager.deduceSelectedActivatableObjectByDistance(); } diff --git a/front/src/Phaser/Game/OutlineableInterface.ts b/front/src/Phaser/Game/OutlineableInterface.ts index b73b2413..bee560cc 100644 --- a/front/src/Phaser/Game/OutlineableInterface.ts +++ b/front/src/Phaser/Game/OutlineableInterface.ts @@ -1,11 +1,10 @@ - export interface OutlineableInterface { - setFollowOutlineColor(color: number): void - removeFollowOutlineColor(): void - setApiOutlineColor(color: number): void - removeApiOutlineColor(): void - pointerOverOutline(): void - pointerOutOutline(): void - characterCloseByOutline(): void - characterFarAwayOutline(): void + setFollowOutlineColor(color: number): void; + removeFollowOutlineColor(): void; + setApiOutlineColor(color: number): void; + removeApiOutlineColor(): void; + pointerOverOutline(): void; + pointerOutOutline(): void; + characterCloseByOutline(): void; + characterFarAwayOutline(): void; } diff --git a/front/src/Phaser/Items/ActionableItem.ts b/front/src/Phaser/Items/ActionableItem.ts index 417c6973..ff85e232 100644 --- a/front/src/Phaser/Items/ActionableItem.ts +++ b/front/src/Phaser/Items/ActionableItem.ts @@ -5,11 +5,11 @@ import Sprite = Phaser.GameObjects.Sprite; import type { GameScene } from "../Game/GameScene"; import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js"; -import type { ActivatableInterface } from '../Game/ActivatableInterface'; +import type { ActivatableInterface } from "../Game/ActivatableInterface"; type EventCallback = (state: unknown, parameters: unknown) => void; -export class ActionableItem implements ActivatableInterface{ +export class ActionableItem implements ActivatableInterface { private readonly activationRadiusSquared: number; private isSelectable: boolean = false; private callbacks: Map> = new Map>(); @@ -41,7 +41,7 @@ export class ActionableItem implements ActivatableInterface{ } } - public getPosition(): { x: number, y: number } { + public getPosition(): { x: number; y: number } { return { x: this.sprite.x, y: this.sprite.y }; } diff --git a/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts b/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts index 489abbd2..6ffd69db 100644 --- a/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts +++ b/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts @@ -1,5 +1,5 @@ -import { Player } from '../Player/Player'; -import { RemotePlayer } from '../Entity/RemotePlayer'; +import { Player } from "../Player/Player"; +import { RemotePlayer } from "../Entity/RemotePlayer"; import type { UserInputHandlerInterface } from "../../Interfaces/UserInputHandlerInterface"; import type { GameScene } from "../Game/GameScene"; @@ -55,7 +55,7 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface { public handleSpaceKeyUpEvent(event: Event): Event { const activatable = this.gameScene.getActivatablesManager().getSelectedActivatableObject(); if (activatable && activatable.isActivatable()) { - activatable.activate(); + activatable.activate(); } return event; } diff --git a/front/src/Stores/ActionsMenuStore.ts b/front/src/Stores/ActionsMenuStore.ts index d2d7ae9a..f891dad8 100644 --- a/front/src/Stores/ActionsMenuStore.ts +++ b/front/src/Stores/ActionsMenuStore.ts @@ -2,11 +2,10 @@ import { writable } from "svelte/store"; export interface ActionsMenuData { playerName: string; - actions: {actionName: string, callback: Function }[]; + actions: { actionName: string; callback: Function }[]; } function createActionsMenuStore() { - const { subscribe, update, set } = writable(undefined); return { @@ -25,7 +24,7 @@ function createActionsMenuStore() { }, removeAction: (actionName: string) => { update((data) => { - const actionIndex = data?.actions.findIndex(action => action.actionName === actionName); + const actionIndex = data?.actions.findIndex((action) => action.actionName === actionName); if (actionIndex !== undefined && actionIndex != -1) { data?.actions.splice(actionIndex, 1); } @@ -37,7 +36,7 @@ function createActionsMenuStore() { */ clear: () => { set(undefined); - } + }, }; } diff --git a/front/src/Stores/OutlineColorStore.ts b/front/src/Stores/OutlineColorStore.ts index 1bb6fd66..a35cc9c9 100644 --- a/front/src/Stores/OutlineColorStore.ts +++ b/front/src/Stores/OutlineColorStore.ts @@ -5,7 +5,7 @@ export function createColorStore() { let followColor: number | undefined = undefined; let apiColor: number | undefined = undefined; - + let pointedByPointer: boolean = false; let pointedByCharacter: boolean = false; diff --git a/front/src/Utils/CustomTypeGuards.ts b/front/src/Utils/CustomTypeGuards.ts index 7c2c9f21..f2bdb0f9 100644 --- a/front/src/Utils/CustomTypeGuards.ts +++ b/front/src/Utils/CustomTypeGuards.ts @@ -1,4 +1,4 @@ -import type { OutlineableInterface } from '../Phaser/Game/OutlineableInterface'; +import type { OutlineableInterface } from "../Phaser/Game/OutlineableInterface"; export function isOutlineable(object: unknown): object is OutlineableInterface { return (object as OutlineableInterface)?.pointerOverOutline !== undefined;