Multidirectional map generation
This commit is contained in:
@@ -177,6 +177,7 @@ export type Inventory = {
|
||||
export type RunState = {
|
||||
stats: Stats;
|
||||
inventory: Inventory;
|
||||
seed: number;
|
||||
lastReloadableWeaponId?: string | null;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user