diff --git a/front/public/resources/icons/icon_status_indicator_inside.png b/front/public/resources/icons/icon_status_indicator_inside.png new file mode 100644 index 00000000..29a2daad Binary files /dev/null and b/front/public/resources/icons/icon_status_indicator_inside.png differ diff --git a/front/public/resources/icons/icon_status_indicator_outline.png b/front/public/resources/icons/icon_status_indicator_outline.png new file mode 100644 index 00000000..67f86ec5 Binary files /dev/null and b/front/public/resources/icons/icon_status_indicator_outline.png differ diff --git a/front/src/Phaser/Components/PlayerStatusDot.ts b/front/src/Phaser/Components/PlayerStatusDot.ts index af893b2f..4e09451a 100644 --- a/front/src/Phaser/Components/PlayerStatusDot.ts +++ b/front/src/Phaser/Components/PlayerStatusDot.ts @@ -1,36 +1,46 @@ import { Easing } from "../../types"; -export class PlayerStatusDot extends Phaser.GameObjects.Container { - private graphics: Phaser.GameObjects.Graphics; +export enum PlayerStatus { + Online = "Online", + Silenced = "Silenced", + Away = "Away", +} - private away: boolean; +export class PlayerStatusDot extends Phaser.GameObjects.Container { + private statusImage: Phaser.GameObjects.Image; + private statusImageOutline: Phaser.GameObjects.Image; + + private status: PlayerStatus; private readonly COLORS = { - // online: 0x00ff00, - // away: 0xffff00, online: 0x8cc43f, onlineOutline: 0x427a25, away: 0xf5931e, awayOutline: 0x875d13, + silenced: 0xe74c3c, + silencedOutline: 0xc0392b, }; constructor(scene: Phaser.Scene, x: number, y: number) { super(scene, x, y); - this.away = false; + this.status = PlayerStatus.Online; + + this.statusImage = this.scene.add.image(0, 0, "iconStatusIndicatorInside"); + this.statusImageOutline = this.scene.add.image(0, 0, "iconStatusIndicatorOutline"); + + this.add([this.statusImage, this.statusImageOutline]); - this.graphics = this.scene.add.graphics(); - this.add(this.graphics); this.redraw(); this.scene.add.existing(this); } - public setAway(away: boolean = true, instant: boolean = false): void { - if (this.away === away) { + public setStatus(status: PlayerStatus, instant: boolean = false): void { + if (this.status === status) { return; } - this.away = away; + this.status = status; if (instant) { this.redraw(); } else { @@ -56,10 +66,19 @@ export class PlayerStatusDot extends Phaser.GameObjects.Container { } private redraw(): void { - this.graphics.clear(); - this.graphics.fillStyle(this.away ? this.COLORS.away : this.COLORS.online); - this.graphics.lineStyle(1, this.away ? this.COLORS.awayOutline : this.COLORS.onlineOutline); - this.graphics.fillCircle(0, 0, 3); - this.graphics.strokeCircle(0, 0, 3); + const colors = this.getColors(); + this.statusImage.setTintFill(colors.filling); + this.statusImageOutline.setTintFill(colors.outline); + } + + private getColors(): { filling: number; outline: number } { + switch (this.status) { + case PlayerStatus.Online: + return { filling: this.COLORS.online, outline: this.COLORS.onlineOutline }; + case PlayerStatus.Away: + return { filling: this.COLORS.away, outline: this.COLORS.awayOutline }; + case PlayerStatus.Silenced: + return { filling: this.COLORS.silenced, outline: this.COLORS.silencedOutline }; + } } } diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index 681efd29..0982351e 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -19,7 +19,7 @@ import type { OutlineableInterface } from "../Game/OutlineableInterface"; import type CancelablePromise from "cancelable-promise"; import { TalkIcon } from "../Components/TalkIcon"; import { Deferred } from "ts-deferred"; -import { PlayerStatusDot } from "../Components/PlayerStatusDot"; +import { PlayerStatus, PlayerStatusDot } from "../Components/PlayerStatusDot"; const playerNameY = -25; const interactiveRadius = 35; @@ -236,8 +236,8 @@ export abstract class Character extends Container implements OutlineableInterfac this.talkIcon.show(show, forceClose); } - public setAwayStatus(away: boolean = true, instant: boolean = false): void { - this.statusDot.setAway(away, instant); + public setStatus(status: PlayerStatus, instant: boolean = false): void { + this.statusDot.setStatus(status, instant); } public addCompanion(name: string, texturePromise?: CancelablePromise): void { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index a2bd5279..5fa11d4b 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -102,6 +102,7 @@ import { Deferred } from "ts-deferred"; import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin"; import { PlayerDetailsUpdatedMessage } from "../../Messages/ts-proto-generated/protos/messages"; import { privacyShutdownStore } from "../../Stores/PrivacyShutdownStore"; +import { PlayerStatus } from "../Components/PlayerStatusDot"; export interface GameSceneInitInterface { initPosition: PointInterface | null; reconnecting: boolean; @@ -250,6 +251,8 @@ export class GameScene extends DirtyScene { this.listenToIframeEvents(); this.load.image("iconTalk", "/resources/icons/icon_talking.png"); + this.load.image("iconStatusIndicatorInside", "/resources/icons/icon_status_indicator_inside.png"); + this.load.image("iconStatusIndicatorOutline", "/resources/icons/icon_status_indicator_outline.png"); if (touchScreenManager.supportTouchScreen) { this.load.image(joystickBaseKey, joystickBaseImg); @@ -1954,7 +1957,7 @@ ${escapedMessage} player.setApiOutlineColor(addPlayerData.outlineColor); } if (addPlayerData.away !== undefined) { - player.setAwayStatus(addPlayerData.away, true); + player.setStatus(addPlayerData.away ? PlayerStatus.Away : PlayerStatus.Online, true); } this.MapPlayers.add(player); this.MapPlayersByKey.set(player.userId, player); @@ -2106,7 +2109,7 @@ ${escapedMessage} character.showTalkIcon(message.details?.showVoiceIndicator); } if (message.details?.away !== undefined) { - character.setAwayStatus(message.details?.away); + character.setStatus(message.details?.away ? PlayerStatus.Away : PlayerStatus.Online); } } diff --git a/front/src/Phaser/Game/PlayerMovement.ts b/front/src/Phaser/Game/PlayerMovement.ts index fc14078d..80b4ddcc 100644 --- a/front/src/Phaser/Game/PlayerMovement.ts +++ b/front/src/Phaser/Game/PlayerMovement.ts @@ -34,7 +34,6 @@ export class PlayerMovement { const y = (this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.y; - //console.log('Computed position ', x, y) return { x, y, diff --git a/front/src/Phaser/Helpers/TexturesHelper.ts b/front/src/Phaser/Helpers/TexturesHelper.ts index 6c0f1aab..4476461f 100644 --- a/front/src/Phaser/Helpers/TexturesHelper.ts +++ b/front/src/Phaser/Helpers/TexturesHelper.ts @@ -67,4 +67,20 @@ export class TexturesHelper { rectangleTexture.generateTexture(textureKey, width, height); rectangleTexture.destroy(); } + + public static createCircleTexture( + scene: Phaser.Scene, + textureKey: string, + radius: number, + color: number, + outlineColor?: number, + outlineThickness?: number + ): void { + const circleTexture = scene.add.graphics().fillStyle(color, 1).fillCircle(radius, radius, radius); + if (outlineColor) { + circleTexture.lineStyle(outlineThickness ?? 1, outlineColor).strokeCircle(radius, radius, radius); + } + circleTexture.generateTexture(textureKey, radius * 2, radius * 2); + circleTexture.destroy(); + } } diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index cae7b496..65e423a4 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -28,7 +28,6 @@ export class Player extends Character { companionTexturePromise?: CancelablePromise ) { super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise); - this.statusDot.setVisible(false); //the current player model should be push away by other players to prevent conflict this.getBody().setImmovable(false); } diff --git a/maps/tests/index.html b/maps/tests/index.html index e625aa6d..c7db9456 100644 --- a/maps/tests/index.html +++ b/maps/tests/index.html @@ -471,6 +471,14 @@ Away mode settings + + + Success Failure Pending + + + Test Status Indicator + +