From 33b38a3b4d7375209e6b69e39a3053e99ce3fe3f Mon Sep 17 00:00:00 2001 From: pobadoba Date: Wed, 6 May 2026 01:27:12 +0900 Subject: [PATCH] feat(babylon_setup): add first person camera Co-authored-by: Copilot --- src/babylon_setup.js | 58 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/src/babylon_setup.js b/src/babylon_setup.js index 456dd2d..2aa1797 100644 --- a/src/babylon_setup.js +++ b/src/babylon_setup.js @@ -24,16 +24,29 @@ const engine = new BABYLON.Engine(canvas, true); const scene = new BABYLON.Scene(engine); scene.clearColor = new BABYLON.Color4(0.05, 0.07, 0.1, 1); -const camera = new BABYLON.ArcRotateCamera( - "cam", - -Math.PI / 2, - Math.PI / 2.4, - 10, - BABYLON.Vector3.Zero(), - scene, -); +const camera = new BABYLON.UniversalCamera("cam", new BABYLON.Vector3(0, 1.6, 0), scene); +camera.minZ = 0.1; +camera.speed = 1.12; +camera.angularSensibility = 1000; +camera.inertia = 0.6; +camera.keysUp = [87]; // W +camera.keysDown = [83]; // S +camera.keysLeft = [65]; // A +camera.keysRight = [68]; // D +camera.checkCollisions = true; +camera.applyGravity = true; +camera.ellipsoid = new BABYLON.Vector3(0.35, 0.9, 0.35); camera.attachControl(canvas, true); +scene.gravity = new BABYLON.Vector3(0, -0.2, 0); +scene.collisionsEnabled = true; + +canvas.addEventListener("click", () => { + if (document.pointerLockElement !== canvas) { + canvas.requestPointerLock(); + } +}); + new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene); // Placeholder sphere @@ -65,6 +78,7 @@ 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 +let spawnMarker = null; const cellSize = 2; function clearLevelMeshes() { @@ -75,6 +89,7 @@ function clearLevelMeshes() { chestMap.clear(); keyChestKey = null; if (exitBox) { try { exitBox.dispose(); } catch(e){}; exitBox = null; } + if (spawnMarker) { try { spawnMarker.dispose(); } catch(e){}; spawnMarker = null; } exitGridPos = null; } @@ -155,6 +170,7 @@ function buildLevelFromGrid(grid) { const floor = BABYLON.MeshBuilder.CreateGround('levelGround', { width: w*cellSize, height: h*cellSize }, scene); floor.position = new BABYLON.Vector3(0, 0, 0); + floor.checkCollisions = true; const fm = new BABYLON.StandardMaterial('floorMat', scene); fm.diffuseColor = new BABYLON.Color3(0.08, 0.08, 0.09); floor.material = fm; @@ -236,12 +252,23 @@ function placeExit(grid, seed) { const halfH = (grid.length * cellSize) / 2; const ex = x*cellSize - halfW + cellSize/2; const ez = y*cellSize - halfH + cellSize/2; + + // Ground plane indicator const plane = BABYLON.MeshBuilder.CreateGround('exitZone', { width: cellSize*0.9, height: cellSize*0.9 }, scene); plane.material = new BABYLON.StandardMaterial('exitMat', scene); plane.material.emissiveColor = new BABYLON.Color3(0.9, 0.8, 0.2); plane.position = new BABYLON.Vector3(ex, 0.01, ez); exitBox = plane; levelMeshes.push(plane); + + // Tall pillar for visibility + const pillar = BABYLON.MeshBuilder.CreateCylinder('exitPillar', { diameter: cellSize*0.3, height: cellSize*3.0 }, scene); + const pillarMat = new BABYLON.StandardMaterial('exitPillarMat', scene); + pillarMat.diffuseColor = new BABYLON.Color3(0.95, 0.8, 0.1); + pillarMat.emissiveColor = new BABYLON.Color3(0.3, 0.25, 0.05); + pillar.material = pillarMat; + pillar.position = new BABYLON.Vector3(ex, cellSize*0.75, ez); + levelMeshes.push(pillar); } function spawnCameraAt(grid) { @@ -262,11 +289,26 @@ function spawnCameraAt(grid) { 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) {} + + // Add spawn marker sphere + if (spawnMarker) { + try { spawnMarker.dispose(); } catch(e) {} + } + const marker = BABYLON.MeshBuilder.CreateSphere('spawnMarker', { diameter: cellSize*0.4 }, scene); + const markerMat = new BABYLON.StandardMaterial('spawnMarkerMat', scene); + markerMat.diffuseColor = new BABYLON.Color3(0.2, 0.6, 0.95); + markerMat.emissiveColor = new BABYLON.Color3(0.1, 0.3, 0.5); + marker.material = markerMat; + marker.position = new BABYLON.Vector3(px, cellSize*0.2, pz); + spawnMarker = marker; + levelMeshes.push(marker); + return; } }