Add levelling up mechanics through experience gained via killing enemies
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import Phaser from "phaser";
|
||||
import { type World, type EntityId } from "../core/types";
|
||||
import { type World, type EntityId, type Stats } from "../core/types";
|
||||
import { GAME_CONFIG } from "../core/config/GameConfig";
|
||||
|
||||
export default class GameUI extends Phaser.Scene {
|
||||
// HUD
|
||||
private levelText!: Phaser.GameObjects.Text;
|
||||
private floorText!: Phaser.GameObjects.Text;
|
||||
private healthBar!: Phaser.GameObjects.Graphics;
|
||||
private expBar!: Phaser.GameObjects.Graphics;
|
||||
|
||||
|
||||
// Menu
|
||||
private menuOpen = false;
|
||||
@@ -31,22 +33,23 @@ export default class GameUI extends Phaser.Scene {
|
||||
|
||||
// Listen for updates from GameScene
|
||||
const gameScene = this.scene.get("GameScene");
|
||||
gameScene.events.on("update-ui", (data: { world: World; playerId: EntityId; levelIndex: number }) => {
|
||||
this.updateUI(data.world, data.playerId, data.levelIndex);
|
||||
gameScene.events.on("update-ui", (data: { world: World; playerId: EntityId; floorIndex: number }) => {
|
||||
this.updateUI(data.world, data.playerId, data.floorIndex);
|
||||
});
|
||||
|
||||
|
||||
gameScene.events.on("toggle-menu", () => this.toggleMenu());
|
||||
gameScene.events.on("close-menu", () => this.setMenuOpen(false));
|
||||
}
|
||||
|
||||
private createHud() {
|
||||
this.levelText = this.add.text(10, 10, "Level 1", {
|
||||
this.floorText = this.add.text(10, 10, "Floor 1", {
|
||||
fontSize: "20px",
|
||||
color: "#ffffff",
|
||||
fontStyle: "bold"
|
||||
}).setDepth(100);
|
||||
|
||||
this.healthBar = this.add.graphics().setDepth(100);
|
||||
this.expBar = this.add.graphics().setDepth(100);
|
||||
}
|
||||
|
||||
private createMenu() {
|
||||
@@ -163,11 +166,13 @@ export default class GameUI extends Phaser.Scene {
|
||||
this.deathContainer.setVisible(false);
|
||||
}
|
||||
|
||||
showDeathScreen(data: { level: number; gold: number; stats: any }) {
|
||||
showDeathScreen(data: { floor: number; gold: number; stats: Stats }) {
|
||||
const lines = [
|
||||
`Dungeon Level: ${data.level}`,
|
||||
`Dungeon Floor: ${data.floor}`,
|
||||
`Gold Collected: ${data.gold}`,
|
||||
|
||||
"",
|
||||
`Experience gained: ${data.stats.exp}`,
|
||||
`Final HP: 0 / ${data.stats.maxHp}`,
|
||||
`Attack: ${data.stats.attack}`,
|
||||
`Defense: ${data.stats.defense}`
|
||||
@@ -211,28 +216,40 @@ export default class GameUI extends Phaser.Scene {
|
||||
gameScene.events.emit("toggle-minimap");
|
||||
}
|
||||
|
||||
private updateUI(world: World, playerId: EntityId, levelIndex: number) {
|
||||
this.updateHud(world, playerId, levelIndex);
|
||||
private updateUI(world: World, playerId: EntityId, floorIndex: number) {
|
||||
this.updateHud(world, playerId, floorIndex);
|
||||
if (this.menuOpen) {
|
||||
this.updateMenuText(world, playerId, levelIndex);
|
||||
this.updateMenuText(world, playerId, floorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private updateHud(world: World, playerId: EntityId, levelIndex: number) {
|
||||
this.levelText.setText(`Level ${levelIndex}`);
|
||||
private updateHud(world: World, playerId: EntityId, floorIndex: number) {
|
||||
this.floorText.setText(`Floor ${floorIndex}`);
|
||||
|
||||
|
||||
const p = world.actors.get(playerId);
|
||||
if (!p || !p.stats) return;
|
||||
|
||||
const barX = 10;
|
||||
const barX = 40;
|
||||
const barY = 40;
|
||||
const barW = 200;
|
||||
const barW = 180;
|
||||
const barH = 16;
|
||||
|
||||
this.healthBar.clear();
|
||||
|
||||
// Heart Icon
|
||||
const iconX = 20;
|
||||
const iconY = barY + barH / 2;
|
||||
this.healthBar.fillStyle(0xff0000, 1);
|
||||
// Draw simple heart
|
||||
this.healthBar.fillCircle(iconX - 4, iconY - 2, 5);
|
||||
this.healthBar.fillCircle(iconX + 4, iconY - 2, 5);
|
||||
this.healthBar.fillTriangle(iconX - 9, iconY - 1, iconX + 9, iconY - 1, iconX, iconY + 9);
|
||||
|
||||
this.healthBar.fillStyle(0x444444, 1);
|
||||
this.healthBar.fillRect(barX, barY, barW, barH);
|
||||
|
||||
|
||||
const hp = Math.max(0, p.stats.hp);
|
||||
const maxHp = Math.max(1, p.stats.maxHp);
|
||||
const pct = Phaser.Math.Clamp(hp / maxHp, 0, 1);
|
||||
@@ -243,21 +260,54 @@ export default class GameUI extends Phaser.Scene {
|
||||
|
||||
this.healthBar.lineStyle(2, 0xffffff, 1);
|
||||
this.healthBar.strokeRect(barX, barY, barW, barH);
|
||||
|
||||
// EXP Bar
|
||||
const expY = barY + barH + 6;
|
||||
const expH = 10;
|
||||
this.expBar.clear();
|
||||
|
||||
// EXP Icon (Star/Orb)
|
||||
const expIconY = expY + expH / 2;
|
||||
this.expBar.fillStyle(GAME_CONFIG.rendering.expOrbColor, 1);
|
||||
this.expBar.fillCircle(iconX, expIconY, 6);
|
||||
this.expBar.fillStyle(0xffffff, 0.5);
|
||||
this.expBar.fillCircle(iconX - 2, expIconY - 2, 2);
|
||||
|
||||
this.expBar.fillStyle(0x444444, 1);
|
||||
this.expBar.fillRect(barX, expY, barW, expH);
|
||||
|
||||
const exp = p.stats.exp;
|
||||
const nextExp = Math.max(1, p.stats.expToNextLevel);
|
||||
|
||||
const expPct = Phaser.Math.Clamp(exp / nextExp, 0, 1);
|
||||
const expFillW = Math.floor(barW * expPct);
|
||||
|
||||
this.expBar.fillStyle(GAME_CONFIG.rendering.expOrbColor, 1);
|
||||
this.expBar.fillRect(barX, expY, expFillW, expH);
|
||||
|
||||
this.expBar.lineStyle(1, 0xffffff, 0.8);
|
||||
this.expBar.strokeRect(barX, expY, barW, expH);
|
||||
|
||||
}
|
||||
|
||||
private updateMenuText(world: World, playerId: EntityId, levelIndex: number) {
|
||||
|
||||
private updateMenuText(world: World, playerId: EntityId, _floorIndex: number) {
|
||||
|
||||
|
||||
const p = world.actors.get(playerId);
|
||||
const stats = p?.stats;
|
||||
const inv = p?.inventory;
|
||||
|
||||
const lines: string[] = [];
|
||||
lines.push(`Level ${levelIndex}`);
|
||||
lines.push(`Level ${stats?.level ?? 1}`);
|
||||
lines.push("");
|
||||
lines.push("Stats");
|
||||
lines.push(` HP: ${stats?.hp ?? 0}/${stats?.maxHp ?? 0}`);
|
||||
lines.push(` EXP: ${stats?.exp ?? 0}/${stats?.expToNextLevel ?? 0}`);
|
||||
lines.push(` Attack: ${stats?.attack ?? 0}`);
|
||||
lines.push(` Defense: ${stats?.defense ?? 0}`);
|
||||
lines.push(` Speed: ${p?.speed ?? 0}`);
|
||||
|
||||
lines.push("");
|
||||
lines.push("Inventory");
|
||||
lines.push(` Gold: ${inv?.gold ?? 0}`);
|
||||
|
||||
Reference in New Issue
Block a user