feat: integrate NPC portrait panel with follow mode in GameScene
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import Phaser from 'phaser';
|
||||
import type { SocketClient } from '../network/SocketClient.js';
|
||||
import { CharacterCompositor } from '../sprites/CharacterCompositor.js';
|
||||
import { PortraitCompositor } from '../sprites/PortraitCompositor.js';
|
||||
import { NpcInfoPanel } from '../ui/NpcInfoPanel.js';
|
||||
import type { WorldState, StateUpdate, EntityState, Appearance } from '@dflike/shared';
|
||||
import { TILE_SIZE, SPRITE_FRAME_WIDTH, SPRITE_FRAME_HEIGHT, SPRITE_COLS, Direction } from '@dflike/shared';
|
||||
|
||||
@@ -21,6 +23,8 @@ export class GameScene extends Phaser.Scene {
|
||||
private moveThrottle = 0;
|
||||
private followTargetIndex = 0;
|
||||
private followThrottle = 0;
|
||||
private portraitCompositor!: PortraitCompositor;
|
||||
private npcInfoPanel!: NpcInfoPanel;
|
||||
|
||||
constructor() {
|
||||
super({ key: 'GameScene' });
|
||||
@@ -33,6 +37,8 @@ export class GameScene extends Phaser.Scene {
|
||||
|
||||
create(): void {
|
||||
this.compositor = new CharacterCompositor(this);
|
||||
this.portraitCompositor = new PortraitCompositor();
|
||||
this.npcInfoPanel = new NpcInfoPanel();
|
||||
|
||||
// Draw tile grid
|
||||
this.drawWorld();
|
||||
@@ -53,6 +59,7 @@ export class GameScene extends Phaser.Scene {
|
||||
|
||||
// Tab to toggle mode
|
||||
this.input.keyboard!.addKey('TAB').on('down', () => {
|
||||
const prevMode = this.mode;
|
||||
if (this.mode === 'camera') {
|
||||
this.mode = 'avatar';
|
||||
} else if (this.mode === 'avatar') {
|
||||
@@ -62,6 +69,13 @@ export class GameScene extends Phaser.Scene {
|
||||
}
|
||||
this.client.sendInput({ type: 'toggle-mode' });
|
||||
this.updateModeText();
|
||||
|
||||
// Panel visibility
|
||||
if (this.mode === 'follow') {
|
||||
this.showFollowPanel();
|
||||
} else if (prevMode === 'follow') {
|
||||
this.npcInfoPanel.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// UI text
|
||||
@@ -221,6 +235,19 @@ export class GameScene extends Phaser.Scene {
|
||||
this.entitySprites.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Live-update the follow panel if visible
|
||||
if (this.mode === 'follow' && this.npcInfoPanel.isVisible()) {
|
||||
const npcIds = this.getNpcIds();
|
||||
const followedId = npcIds[this.followTargetIndex];
|
||||
const followed = this.entitySprites.get(followedId);
|
||||
if (followed) {
|
||||
this.npcInfoPanel.updateInfo(followed.lastState);
|
||||
if (followed.lastState.needs) {
|
||||
this.npcInfoPanel.updateNeeds(followed.lastState.needs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update(_time: number, delta: number): void {
|
||||
@@ -285,10 +312,12 @@ export class GameScene extends Phaser.Scene {
|
||||
this.followTargetIndex = (this.followTargetIndex - 1 + npcIds.length) % npcIds.length;
|
||||
this.followThrottle = 150;
|
||||
this.updateModeText();
|
||||
this.updateFollowPanel();
|
||||
} else if (right) {
|
||||
this.followTargetIndex = (this.followTargetIndex + 1) % npcIds.length;
|
||||
this.followThrottle = 150;
|
||||
this.updateModeText();
|
||||
this.updateFollowPanel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +330,29 @@ export class GameScene extends Phaser.Scene {
|
||||
}
|
||||
}
|
||||
|
||||
private async showFollowPanel(): Promise<void> {
|
||||
const npcIds = this.getNpcIds();
|
||||
if (npcIds.length === 0) return;
|
||||
const targetId = npcIds[this.followTargetIndex];
|
||||
const es = this.entitySprites.get(targetId);
|
||||
if (!es) return;
|
||||
|
||||
const portraitUrl = await this.portraitCompositor.compositePortrait(es.lastState.appearance);
|
||||
this.npcInfoPanel.show(es.lastState, portraitUrl);
|
||||
}
|
||||
|
||||
private async updateFollowPanel(): Promise<void> {
|
||||
const npcIds = this.getNpcIds();
|
||||
if (npcIds.length === 0) return;
|
||||
const targetId = npcIds[this.followTargetIndex];
|
||||
const es = this.entitySprites.get(targetId);
|
||||
if (!es) return;
|
||||
|
||||
const portraitUrl = await this.portraitCompositor.compositePortrait(es.lastState.appearance);
|
||||
this.npcInfoPanel.updatePortrait(portraitUrl);
|
||||
this.npcInfoPanel.updateInfo(es.lastState);
|
||||
}
|
||||
|
||||
private getNpcIds(): number[] {
|
||||
return [...this.entitySprites.keys()].sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user