Add in throwable items (dagger) from pixel dungeon

This commit is contained in:
Peter Stockings
2026-01-06 20:58:53 +11:00
parent 3b29180a00
commit 9b1fc78409
18 changed files with 659 additions and 155 deletions

View File

@@ -3,6 +3,7 @@ import { type World, type EntityId, type Vec2, type ActorType } from "../core/ty
import { TILE_SIZE } from "../core/constants";
import { idx, isWall } from "../engine/world/world-logic";
import { GAME_CONFIG } from "../core/config/GameConfig";
import { ITEMS } from "../core/config/Items";
import { FovManager } from "./FovManager";
import { MinimapRenderer } from "./MinimapRenderer";
import { FxRenderer } from "./FxRenderer";
@@ -15,6 +16,7 @@ export class DungeonRenderer {
private playerSprite?: Phaser.GameObjects.Sprite;
private enemySprites: Map<EntityId, Phaser.GameObjects.Sprite> = new Map();
private orbSprites: Map<EntityId, Phaser.GameObjects.Arc> = new Map();
private itemSprites: Map<EntityId, Phaser.GameObjects.Sprite> = new Map();
private fovManager: FovManager;
private minimapRenderer: MinimapRenderer;
@@ -97,6 +99,12 @@ export class DungeonRenderer {
return this.fovManager.isSeen(x, y);
}
updateTile(x: number, y: number) {
if (!this.map || !this.world) return;
const t = this.world.tiles[idx(this.world, x, y)];
this.map.putTileAt(t, x, y);
}
get seenArray() {
return this.fovManager.seenArray;
}
@@ -139,6 +147,7 @@ export class DungeonRenderer {
// Actors (Combatants)
const activeEnemyIds = new Set<EntityId>();
const activeOrbIds = new Set<EntityId>();
const activeItemIds = new Set<EntityId>();
for (const a of this.world.actors.values()) {
const i = idx(this.world, a.pos.x, a.pos.y);
@@ -215,6 +224,23 @@ export class DungeonRenderer {
orb.setPosition(a.pos.x * TILE_SIZE + TILE_SIZE / 2, a.pos.y * TILE_SIZE + TILE_SIZE / 2);
orb.setVisible(true);
}
} else if (a.category === "item_drop") {
if (!isVis) continue;
activeItemIds.add(a.id);
let itemSprite = this.itemSprites.get(a.id);
if (!itemSprite) {
itemSprite = this.scene.add.sprite(0, 0, a.item.textureKey, a.item.spriteIndex);
itemSprite.setDepth(40);
this.itemSprites.set(a.id, itemSprite);
}
const tx = a.pos.x * TILE_SIZE + TILE_SIZE / 2;
const ty = a.pos.y * TILE_SIZE + TILE_SIZE / 2;
itemSprite.setPosition(tx, ty);
itemSprite.setVisible(true);
// bobbing effect?
itemSprite.y += Math.sin(this.scene.time.now / 300) * 2;
}
}
@@ -239,6 +265,16 @@ export class DungeonRenderer {
}
}
for (const [id, item] of this.itemSprites.entries()) {
if (!activeItemIds.has(id)) {
item.setVisible(false);
if (!this.world.actors.has(id)) {
item.destroy();
this.itemSprites.delete(id);
}
}
}
this.minimapRenderer.render(this.world, seen, visible);
}
@@ -278,4 +314,46 @@ export class DungeonRenderer {
showAlert(x: number, y: number) {
this.fxRenderer.showAlert(x, y);
}
showProjectile(from: Vec2, to: Vec2, itemId: string, onComplete: () => void) {
// World coords
const startX = from.x * TILE_SIZE + TILE_SIZE / 2;
const startY = from.y * TILE_SIZE + TILE_SIZE / 2;
const endX = to.x * TILE_SIZE + TILE_SIZE / 2;
const endY = to.y * TILE_SIZE + TILE_SIZE / 2;
// Create sprite
// Look up sprite index from config
const itemConfig = ITEMS[itemId];
const texture = itemConfig?.textureKey ?? "items";
const frame = itemConfig?.spriteIndex ?? 0;
// Use 'items' spritesheet
const sprite = this.scene.add.sprite(startX, startY, texture, frame);
sprite.setDepth(2000);
// Rotate?
const angle = Phaser.Math.Angle.Between(startX, startY, endX, endY);
sprite.setRotation(angle + Math.PI / 4); // Adjust for sprite orientation (diagonal usually)
const dist = Phaser.Math.Distance.Between(startX, startY, endX, endY);
const duration = dist * 2; // speed
this.scene.tweens.add({
targets: sprite,
x: endX,
y: endY,
rotation: sprite.rotation + 4 * Math.PI, // Spin effect
duration: duration,
ease: 'Linear',
onComplete: () => {
sprite.destroy();
onComplete();
}
});
}
shakeCamera() {
this.scene.cameras.main.shake(100, 0.01);
}
}