shellquest
Version:
Terminal-based procedurally generated dungeon crawler
87 lines (74 loc) • 2.91 kB
text/typescript
import type {ZombieAttackGame} from '../ZombieAttackGame.ts';
import type {PixelCanvas} from '../drawing/pixelCanvas.ts';
import type {GameLevel} from '../level/types.ts';
import type {CollisionSystem} from '../collision/CollisionSystem.ts';
export interface EntityAttachment {
tileName: string;
offsetX: number; // Offset from parent entity in pixels
offsetY: number; // Offset from parent entity in pixels
rotation?: number; // Rotation in radians
scale?: number; // Scale multiplier
layer?: number; // Override layer (defaults to parent's layer)
facingLeft?: boolean; // Override facing direction
visible: boolean;
}
export abstract class Entity {
x: number = 0; // X position in pixels
y: number = 0; // Y position in pixels
width: number = 16; // Width in pixels
height: number = 16; // Height in pixels
tileName: string = '';
layer: number = 1; // Layer index to render on
facingLeft?: boolean; // Whether the sprite should be flipped horizontally
verticalAnimationOffset?: number; // Vertical offset in pixels for animation
// Attachments system
attachments: EntityAttachment[] = [];
constructor(protected game: ZombieAttackGame) {}
// Custom draw callback for UI elements like health bars
abstract render(ctx: PixelCanvas): void;
// Add an attachment to this entity
addAttachment(attachment: EntityAttachment): void {
this.attachments.push(attachment);
}
// Remove an attachment
removeAttachment(attachment: EntityAttachment): void {
const index = this.attachments.indexOf(attachment);
if (index !== -1) {
this.attachments.splice(index, 1);
}
}
// Get attachment by name
getAttachment(tileName: string): EntityAttachment | undefined {
return this.attachments.find((a) => a.tileName === tileName);
}
// Update attachments (for animations)
updateAttachments(deltaTime: number): void {
// Override in subclasses for attachment animations
}
abstract update(deltaTime: number, level: GameLevel, collisionSystem: CollisionSystem): void;
protected renderEntityAttachments(pixelBuffer: PixelCanvas): void {
for (const attachment of this.attachments) {
if (!attachment.visible) continue;
if (attachment.rotation && attachment.rotation !== 0) {
pixelBuffer.drawTileRotated(
this.game.tileMap,
attachment.tileName,
attachment.offsetX,
attachment.offsetY,
attachment.rotation,
attachment.facingLeft ?? this.facingLeft ?? false,
false,
);
} else {
pixelBuffer.drawTile(
this.game.tileMap,
attachment.tileName,
attachment.offsetX,
attachment.offsetY,
attachment.facingLeft ?? this.facingLeft ?? false,
false,
);
}
}
}
}