diff --git a/src/babylon_setup.js b/src/babylon_setup.js index 66f6fa8..456dd2d 100644 --- a/src/babylon_setup.js +++ b/src/babylon_setup.js @@ -43,13 +43,6 @@ sphereMaterial.diffuseColor = new BABYLON.Color3(0.2, 0.55, 0.95); sphereMaterial.emissiveColor = new BABYLON.Color3(0.05, 0.12, 0.2); sphere.material = sphereMaterial; -// Ground -const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 14, height: 14 }, scene); -const groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene); -groundMaterial.diffuseColor = new BABYLON.Color3(0.12, 0.14, 0.17); -groundMaterial.specularColor = BABYLON.Color3.Black(); -ground.material = groundMaterial; - // Main render loop engine.runRenderLoop(() => { const level = sharedState.config.level; @@ -71,6 +64,7 @@ let levelMeshes = []; let chestMap = new Map(); // key: "x,y" -> {mesh, opened} let keyChestKey = null; let exitBox = null; +let exitGridPos = null; // track exit grid position for collision checking const cellSize = 2; function clearLevelMeshes() { @@ -81,6 +75,7 @@ function clearLevelMeshes() { chestMap.clear(); keyChestKey = null; if (exitBox) { try { exitBox.dispose(); } catch(e){}; exitBox = null; } + exitGridPos = null; } // Simple seeded RNG @@ -220,8 +215,23 @@ function placeExit(grid, seed) { const dead = findDeadEnds(grid); const rng = seededRng(seed+1); if (dead.length === 0) return; - const idx = Math.floor(rng() * dead.length); - const [x,y] = dead[idx]; + + // Filter out dead ends that have chests + const availableDead = dead.filter(([x, y]) => !chestMap.has(`${x},${y}`)); + if (availableDead.length === 0) { + // Fallback: use any dead end if no chest-free spot available + // This shouldn't happen in normal cases + const idx = Math.floor(rng() * dead.length); + const [x,y] = dead[idx]; + exitGridPos = { x, y }; + // Continue below + } else { + const idx = Math.floor(rng() * availableDead.length); + const [x,y] = availableDead[idx]; + exitGridPos = { x, y }; + } + + const [x,y] = exitGridPos; const halfW = (grid[0].length * cellSize) / 2; const halfH = (grid.length * cellSize) / 2; const ex = x*cellSize - halfW + cellSize/2; @@ -238,18 +248,26 @@ function spawnCameraAt(grid) { const h = grid.length, w = grid[0].length; for (let y = 1; y < h-1; y++) { for (let x = 1; x < w-1; x++) { - if (grid[y][x] === 0) { - const halfW = (w * cellSize) / 2; - const halfH = (h * cellSize) / 2; - const px = x*cellSize - halfW + cellSize/2; - const pz = y*cellSize - halfH + cellSize/2; - try { - if (camera && camera.position) { - camera.position = new BABYLON.Vector3(px, 1.6, pz); - } - } catch (e) {} - return; - } + // Skip walls + if (grid[y][x] !== 0) continue; + + // Skip chests + if (chestMap.has(`${x},${y}`)) continue; + + // Skip exit + if (exitGridPos && exitGridPos.x === x && exitGridPos.y === y) continue; + + // Found valid spawn point + const halfW = (w * cellSize) / 2; + const halfH = (h * cellSize) / 2; + const px = x*cellSize - halfW + cellSize/2; + const pz = y*cellSize - halfH + cellSize/2; + try { + if (camera && camera.position) { + camera.position = new BABYLON.Vector3(px, 1.6, pz); + } + } catch (e) {} + return; } } }