Use wall + floor assets from Pixel dungeon

This commit is contained in:
Peter Stockings
2026-01-04 16:46:49 +11:00
parent 6a050ac7a9
commit 42cd77998d
7 changed files with 152 additions and 131 deletions

View File

@@ -19,7 +19,7 @@ interface Room {
export function generateWorld(level: number, runState: RunState): { world: World; playerId: EntityId } {
const width = GAME_CONFIG.map.width;
const height = GAME_CONFIG.map.height;
const tiles: Tile[] = new Array(width * height).fill(1); // Start with all walls
const tiles: Tile[] = new Array(width * height).fill(GAME_CONFIG.terrain.wall); // Start with all walls
const random = seededRandom(level * 12345);
@@ -52,6 +52,8 @@ export function generateWorld(level: number, runState: RunState): { world: World
placeEnemies(level, rooms, actors, random);
decorate(width, height, tiles, random, exit);
return { world: { width, height, tiles, actors, exit }, playerId };
}
@@ -99,7 +101,7 @@ function doesOverlap(newRoom: Room, rooms: Room[]): boolean {
function carveRoom(room: Room, tiles: Tile[], world: any): void {
for (let x = room.x; x < room.x + room.width; x++) {
for (let y = room.y; y < room.y + room.height; y++) {
tiles[idx(world, x, y)] = 0;
tiles[idx(world, x, y)] = GAME_CONFIG.terrain.empty;
}
}
}
@@ -113,22 +115,95 @@ function carveCorridor(room1: Room, room2: Room, tiles: Tile[], world: any, rand
if (random() < 0.5) {
// Horizontal then vertical
for (let x = Math.min(x1, x2); x <= Math.max(x1, x2); x++) {
tiles[idx(world, x, y1)] = 0;
tiles[idx(world, x, y1)] = GAME_CONFIG.terrain.empty;
}
for (let y = Math.min(y1, y2); y <= Math.max(y1, y2); y++) {
tiles[idx(world, x2, y)] = 0;
tiles[idx(world, x2, y)] = GAME_CONFIG.terrain.empty;
}
} else {
// Vertical then horizontal
for (let y = Math.min(y1, y2); y <= Math.max(y1, y2); y++) {
tiles[idx(world, x1, y)] = 0;
tiles[idx(world, x1, y)] = GAME_CONFIG.terrain.empty;
}
for (let x = Math.min(x1, x2); x <= Math.max(x1, x2); x++) {
tiles[idx(world, x, y2)] = 0;
tiles[idx(world, x, y2)] = GAME_CONFIG.terrain.empty;
}
}
}
function decorate(width: number, height: number, tiles: Tile[], random: () => number, exit: Vec2): void {
const world = { width, height };
// Set exit tile
tiles[idx(world as any, exit.x, exit.y)] = GAME_CONFIG.terrain.exit;
// Add water patches (similar to PD Sewers)
const waterMask = generatePatch(width, height, 0.45, 5, random);
for (let i = 0; i < tiles.length; i++) {
if (tiles[i] === GAME_CONFIG.terrain.empty && waterMask[i]) {
tiles[i] = GAME_CONFIG.terrain.water;
}
}
// Wall decorations
for (let y = 0; y < height - 1; y++) {
for (let x = 0; x < width; x++) {
const i = idx(world as any, x, y);
const nextY = idx(world as any, x, y + 1);
if (tiles[i] === GAME_CONFIG.terrain.wall &&
tiles[nextY] === GAME_CONFIG.terrain.water &&
random() < 0.25) {
tiles[i] = GAME_CONFIG.terrain.wallDeco;
}
}
}
// Floor decorations (moss)
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
const i = idx(world as any, x, y);
if (tiles[i] === GAME_CONFIG.terrain.empty) {
let wallCount = 0;
if (tiles[idx(world as any, x + 1, y)] === GAME_CONFIG.terrain.wall) wallCount++;
if (tiles[idx(world as any, x - 1, y)] === GAME_CONFIG.terrain.wall) wallCount++;
if (tiles[idx(world as any, x, y + 1)] === GAME_CONFIG.terrain.wall) wallCount++;
if (tiles[idx(world as any, x, y - 1)] === GAME_CONFIG.terrain.wall) wallCount++;
if (random() * 16 < wallCount * wallCount) {
tiles[i] = GAME_CONFIG.terrain.emptyDeco;
}
}
}
}
}
/**
* Simple cellular automata for generating patches of terrain
*/
function generatePatch(width: number, height: number, fillChance: number, iterations: number, random: () => number): boolean[] {
let map = new Array(width * height).fill(false).map(() => random() < fillChance);
for (let step = 0; step < iterations; step++) {
const nextMap = new Array(width * height).fill(false);
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
let neighbors = 0;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
if (map[(y + dy) * width + (x + dx)]) neighbors++;
}
}
if (neighbors > 4) nextMap[y * width + x] = true;
else if (neighbors < 4) nextMap[y * width + x] = false;
else nextMap[y * width + x] = map[y * width + x];
}
}
map = nextMap;
}
return map;
}
function placeEnemies(level: number, rooms: Room[], actors: Map<EntityId, Actor>, random: () => number): void {
let enemyId = 2;
const numEnemies = GAME_CONFIG.enemy.baseCount + level * GAME_CONFIG.enemy.baseCountPerLevel + Math.floor(random() * GAME_CONFIG.enemy.randomBonus);