Randomly generate large track loop with multiple curves in Track exploration scene
This commit is contained in:
@@ -8,8 +8,9 @@ export class TrackExplorationScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private tracks: Set<string> = new Set();
|
||||
private trackSprites: Phaser.GameObjects.Sprite[] = [];
|
||||
private cart?: Phaser.GameObjects.Sprite;
|
||||
private cartPos = { x: 5, y: 5 };
|
||||
private cartPos = { x: 0, y: 0 };
|
||||
private cartDir = { dx: 1, dy: 0 };
|
||||
private moveTimer?: Phaser.Time.TimerEvent;
|
||||
|
||||
@@ -30,29 +31,28 @@ export class TrackExplorationScene extends Phaser.Scene {
|
||||
this.scene.start("MenuScene");
|
||||
});
|
||||
|
||||
// Silence lint warning if needed
|
||||
backBtn.setAlpha(0.8);
|
||||
|
||||
// Create a smaller track loop to test all corners clearly
|
||||
const startX = 5;
|
||||
const startY = 5;
|
||||
const size = 5; // 5x5 loop
|
||||
for (let x = startX; x < startX + size; x++) {
|
||||
this.tracks.add(`${x},${startY}`);
|
||||
this.tracks.add(`${x},${startY + size - 1}`);
|
||||
}
|
||||
for (let y = startY + 1; y < startY + size - 1; y++) {
|
||||
this.tracks.add(`${startX},${y}`);
|
||||
this.tracks.add(`${startX + size - 1},${y}`);
|
||||
}
|
||||
const regenBtn = this.add.text(width / 2, height - 70, "REGENERATE LOOP", {
|
||||
fontSize: "24px",
|
||||
color: "#00ff88"
|
||||
}).setOrigin(0.5)
|
||||
.setInteractive({ useHandCursor: true })
|
||||
.on("pointerdown", () => {
|
||||
this.generateRandomLoop();
|
||||
});
|
||||
|
||||
regenBtn.setAlpha(0.8);
|
||||
|
||||
// Render tracks
|
||||
this.renderTracks();
|
||||
// Initial generation
|
||||
this.generateRandomLoop();
|
||||
|
||||
// Add Mine Cart
|
||||
const { mineCarts } = GAME_CONFIG.rendering;
|
||||
this.cart = this.add.sprite(5 * 32 + 16, 5 * 32 + 16, "kennys_dungeon", mineCarts.horizontal);
|
||||
this.cart.setScale(2); // Make it visible
|
||||
this.cart = this.add.sprite(0, 0, "kennys_dungeon", mineCarts.horizontal);
|
||||
this.cart.setScale(2);
|
||||
this.cart.setDepth(10);
|
||||
this.resetCart();
|
||||
|
||||
// Movement Loop
|
||||
this.moveTimer = this.time.addEvent({
|
||||
@@ -67,17 +67,131 @@ export class TrackExplorationScene extends Phaser.Scene {
|
||||
});
|
||||
}
|
||||
|
||||
private generateRandomLoop() {
|
||||
// Clear existing
|
||||
this.trackSprites.forEach(s => s.destroy());
|
||||
this.trackSprites = [];
|
||||
this.tracks.clear();
|
||||
|
||||
// Start with a 6x6 rectangle
|
||||
const startX = 6;
|
||||
const startY = 6;
|
||||
const initialSize = 15;
|
||||
|
||||
for (let x = startX; x < startX + initialSize; x++) {
|
||||
this.tracks.add(`${x},${startY}`);
|
||||
this.tracks.add(`${x},${startY + initialSize - 1}`);
|
||||
}
|
||||
for (let y = startY + 1; y < startY + initialSize - 1; y++) {
|
||||
this.tracks.add(`${startX},${y}`);
|
||||
this.tracks.add(`${startX + initialSize - 1},${y}`);
|
||||
}
|
||||
|
||||
// Apply "perturbations" to create curves
|
||||
for (let i = 0; i < 100; i++) {
|
||||
this.expandLoop();
|
||||
}
|
||||
|
||||
this.renderTracks();
|
||||
this.resetCart();
|
||||
}
|
||||
|
||||
private expandLoop() {
|
||||
const trackArray = Array.from(this.tracks);
|
||||
const posKey = trackArray[Math.floor(Math.random() * trackArray.length)];
|
||||
const [x, y] = posKey.split(',').map(Number);
|
||||
|
||||
const directions = [
|
||||
{ dx: 1, dy: 0 }, { dx: -1, dy: 0 },
|
||||
{ dx: 0, dy: 1 }, { dx: 0, dy: -1 }
|
||||
];
|
||||
|
||||
for (const dir of directions) {
|
||||
const isH = this.tracks.has(`${x-1},${y}`) && this.tracks.has(`${x+1},${y}`);
|
||||
const isV = this.tracks.has(`${x},${y-1}`) && this.tracks.has(`${x},${y+1}`);
|
||||
|
||||
if (isH && !isV && Math.abs(dir.dy) === 1) {
|
||||
const ny = y + dir.dy;
|
||||
const newTiles = [`${x-1},${ny}`, `${x},${ny}`, `${x+1},${ny}`];
|
||||
|
||||
if (newTiles.some(k => this.tracks.has(k))) continue;
|
||||
|
||||
const tempTracks = new Set(this.tracks);
|
||||
tempTracks.delete(`${x},${y}`);
|
||||
newTiles.forEach(k => tempTracks.add(k));
|
||||
|
||||
// Check rule: Every modified/new tile must have exactly 2 neighbors
|
||||
const affected = [...newTiles, `${x-1},${y}`, `${x+1},${y}`];
|
||||
const isValid = affected.every(posKey => {
|
||||
const [px, py] = posKey.split(',').map(Number);
|
||||
const count = [[px+1,py],[px-1,py],[px,py+1],[px,py-1]]
|
||||
.filter(([nx, ny]) => tempTracks.has(`${nx},${ny}`)).length;
|
||||
return count === 2;
|
||||
});
|
||||
|
||||
if (isValid) {
|
||||
this.tracks = tempTracks;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isV && !isH && Math.abs(dir.dx) === 1) {
|
||||
const nx = x + dir.dx;
|
||||
const newTiles = [`${nx},${y-1}`, `${nx},${y}`, `${nx},${y+1}`];
|
||||
|
||||
if (newTiles.some(k => this.tracks.has(k))) continue;
|
||||
|
||||
const tempTracks = new Set(this.tracks);
|
||||
tempTracks.delete(`${x},${y}`);
|
||||
newTiles.forEach(k => tempTracks.add(k));
|
||||
|
||||
const affected = [...newTiles, `${x},${y-1}`, `${x},${y+1}`];
|
||||
const isValid = affected.every(posKey => {
|
||||
const [px, py] = posKey.split(',').map(Number);
|
||||
const count = [[px+1,py],[px-1,py],[px,py+1],[px,py-1]]
|
||||
.filter(([nx, ny]) => tempTracks.has(`${nx},${ny}`)).length;
|
||||
return count === 2;
|
||||
});
|
||||
|
||||
if (isValid) {
|
||||
this.tracks = tempTracks;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resetCart() {
|
||||
if (!this.cart) return;
|
||||
const first = Array.from(this.tracks)[0];
|
||||
const [x, y] = first.split(',').map(Number);
|
||||
this.cartPos = { x, y };
|
||||
this.cart.setPosition(x * 32 + 16, y * 32 + 16);
|
||||
|
||||
// Find a valid initial direction
|
||||
const neighbors = [
|
||||
{ dx: 1, dy: 0 }, { dx: -1, dy: 0 },
|
||||
{ dx: 0, dy: 1 }, { dx: 0, dy: -1 }
|
||||
];
|
||||
for (const n of neighbors) {
|
||||
if (this.tracks.has(`${x + n.dx},${y + n.dy}`)) {
|
||||
this.cartDir = { dx: n.dx, dy: n.dy };
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private renderTracks() {
|
||||
this.tracks.forEach(posKey => {
|
||||
const [x, y] = posKey.split(',').map(Number);
|
||||
const connections = TrackSystem.getConnectionsFromNeighbors(x, y, (nx: number, ny: number) => this.tracks.has(`${nx},${ny}`));
|
||||
const frame = TrackSystem.getTrackFrame(connections);
|
||||
this.add.sprite(x * 32 + 16, y * 32 + 16, "kennys_dungeon", frame).setScale(2);
|
||||
const sprite = this.add.sprite(x * 32 + 16, y * 32 + 16, "kennys_dungeon", frame).setScale(2);
|
||||
this.trackSprites.push(sprite);
|
||||
});
|
||||
}
|
||||
|
||||
private moveCart() {
|
||||
if (!this.cart) return;
|
||||
if (!this.cart || this.tracks.size === 0) return;
|
||||
|
||||
const next = MineCartSystem.getNextPosition(this.cartPos, this.cartDir.dx, this.cartDir.dy, (nx: number, ny: number) => this.tracks.has(`${nx},${ny}`));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user