Multidirectional map generation

This commit is contained in:
2026-02-07 15:24:11 +11:00
parent 88017add92
commit b0dd090a60
3 changed files with 47 additions and 10 deletions

View File

@@ -177,6 +177,7 @@ export type Inventory = {
export type RunState = {
stats: Stats;
inventory: Inventory;
seed: number;
lastReloadableWeaponId?: string | null;
};

View File

@@ -38,13 +38,13 @@ export function generateWorld(floor: number, runState: RunState): { world: World
const height = GAME_CONFIG.map.height;
const tiles: Tile[] = new Array(width * height).fill(TileType.WALL);
const random = seededRandom(floor * 12345);
const random = seededRandom(runState.seed + floor * 12345);
// Create ECS World first
const ecsWorld = new ECSWorld(); // Starts at ID 1 by default
// Set ROT's RNG seed for consistent dungeon generation
ROT.RNG.setSeed(floor * 12345);
ROT.RNG.setSeed(runState.seed + floor * 12345);
// Replace generateRooms call with track-first logic for mine cart mechanic
const { rooms, trackPath } = generateTrackLevel(width, height, tiles, floor, random);
@@ -156,19 +156,52 @@ function generateTrackLevel(width: number, height: number, tiles: Tile[], _floor
// 1. Generate a winding path of "Anchor Points" for rooms
const anchors: Vec2[] = [];
let currA = { x: 10, y: Math.floor(height / 2) };
anchors.push({ ...currA });
const startDir = Math.floor(random() * 4); // 0: East, 1: West, 2: South, 3: North
const targetX = width - 10;
let currA: Vec2;
const margin = 10;
const stepSize = 12;
while (currA.x < targetX) {
const nextX = currA.x + Math.floor(stepSize * (0.8 + random() * 0.4));
const nextY = currA.y + Math.floor((random() - 0.5) * height * 0.6);
if (startDir === 0) { // East (Left to Right)
currA = { x: margin, y: margin + Math.floor(random() * (height - margin * 2)) };
} else if (startDir === 1) { // West (Right to Left)
currA = { x: width - margin, y: margin + Math.floor(random() * (height - margin * 2)) };
} else if (startDir === 2) { // South (Top to Bottom)
currA = { x: margin + Math.floor(random() * (width - margin * 2)), y: margin };
} else { // North (Bottom to Top)
currA = { x: margin + Math.floor(random() * (width - margin * 2)), y: height - margin };
}
anchors.push({ ...currA });
const isFinished = () => {
if (startDir === 0) return currA.x >= width - margin;
if (startDir === 1) return currA.x <= margin;
if (startDir === 2) return currA.y >= height - margin;
return currA.y <= margin;
};
while (!isFinished()) {
let nextX = currA.x;
let nextY = currA.y;
if (startDir === 0) { // East
nextX += Math.floor(stepSize * (0.8 + random() * 0.4));
nextY += Math.floor((random() - 0.5) * height * 0.4);
} else if (startDir === 1) { // West
nextX -= Math.floor(stepSize * (0.8 + random() * 0.4));
nextY += Math.floor((random() - 0.5) * height * 0.4);
} else if (startDir === 2) { // South
nextY += Math.floor(stepSize * (0.8 + random() * 0.4));
nextX += Math.floor((random() - 0.5) * width * 0.4);
} else { // North
nextY -= Math.floor(stepSize * (0.8 + random() * 0.4));
nextX += Math.floor((random() - 0.5) * width * 0.4);
}
currA = {
x: Math.min(width - 5, nextX),
y: Math.max(5, Math.min(height - 5, nextY))
x: Math.max(margin / 2, Math.min(width - margin / 2, nextX)),
y: Math.max(margin / 2, Math.min(height - margin / 2, nextY))
};
anchors.push({ ...currA });
}

View File

@@ -50,6 +50,7 @@ export class GameScene extends Phaser.Scene {
public runState: RunState = {
stats: { ...GAME_CONFIG.player.initialStats },
inventory: { gold: 0, items: [] },
seed: Math.floor(Math.random() * 1000000),
lastReloadableWeaponId: null
};
@@ -478,6 +479,7 @@ export class GameScene extends Phaser.Scene {
this.runState = {
stats: { ...p.stats },
inventory: { gold: p.inventory.gold, items: [...p.inventory.items] },
seed: this.runState.seed,
lastReloadableWeaponId: this.runState.lastReloadableWeaponId
};
}
@@ -486,6 +488,7 @@ export class GameScene extends Phaser.Scene {
this.runState = {
stats: { ...GAME_CONFIG.player.initialStats },
inventory: { gold: 0, items: [] },
seed: Math.floor(Math.random() * 1000000),
lastReloadableWeaponId: null
};
this.floorIndex = 1;