feat(babylon_setup): add first person camera

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
pobadoba
2026-05-06 01:27:12 +09:00
parent dd0e106bea
commit 33b38a3b4d

View File

@@ -24,16 +24,29 @@ const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine); const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0.05, 0.07, 0.1, 1); scene.clearColor = new BABYLON.Color4(0.05, 0.07, 0.1, 1);
const camera = new BABYLON.ArcRotateCamera( const camera = new BABYLON.UniversalCamera("cam", new BABYLON.Vector3(0, 1.6, 0), scene);
"cam", camera.minZ = 0.1;
-Math.PI / 2, camera.speed = 1.12;
Math.PI / 2.4, camera.angularSensibility = 1000;
10, camera.inertia = 0.6;
BABYLON.Vector3.Zero(), camera.keysUp = [87]; // W
scene, 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); 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); new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// Placeholder sphere // Placeholder sphere
@@ -65,6 +78,7 @@ let chestMap = new Map(); // key: "x,y" -> {mesh, opened}
let keyChestKey = null; let keyChestKey = null;
let exitBox = null; let exitBox = null;
let exitGridPos = null; // track exit grid position for collision checking let exitGridPos = null; // track exit grid position for collision checking
let spawnMarker = null;
const cellSize = 2; const cellSize = 2;
function clearLevelMeshes() { function clearLevelMeshes() {
@@ -75,6 +89,7 @@ function clearLevelMeshes() {
chestMap.clear(); chestMap.clear();
keyChestKey = null; keyChestKey = null;
if (exitBox) { try { exitBox.dispose(); } catch(e){}; exitBox = null; } if (exitBox) { try { exitBox.dispose(); } catch(e){}; exitBox = null; }
if (spawnMarker) { try { spawnMarker.dispose(); } catch(e){}; spawnMarker = null; }
exitGridPos = null; exitGridPos = null;
} }
@@ -155,6 +170,7 @@ function buildLevelFromGrid(grid) {
const floor = BABYLON.MeshBuilder.CreateGround('levelGround', { width: w*cellSize, height: h*cellSize }, scene); const floor = BABYLON.MeshBuilder.CreateGround('levelGround', { width: w*cellSize, height: h*cellSize }, scene);
floor.position = new BABYLON.Vector3(0, 0, 0); floor.position = new BABYLON.Vector3(0, 0, 0);
floor.checkCollisions = true;
const fm = new BABYLON.StandardMaterial('floorMat', scene); const fm = new BABYLON.StandardMaterial('floorMat', scene);
fm.diffuseColor = new BABYLON.Color3(0.08, 0.08, 0.09); fm.diffuseColor = new BABYLON.Color3(0.08, 0.08, 0.09);
floor.material = fm; floor.material = fm;
@@ -236,12 +252,23 @@ function placeExit(grid, seed) {
const halfH = (grid.length * cellSize) / 2; const halfH = (grid.length * cellSize) / 2;
const ex = x*cellSize - halfW + cellSize/2; const ex = x*cellSize - halfW + cellSize/2;
const ez = y*cellSize - halfH + 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); const plane = BABYLON.MeshBuilder.CreateGround('exitZone', { width: cellSize*0.9, height: cellSize*0.9 }, scene);
plane.material = new BABYLON.StandardMaterial('exitMat', scene); plane.material = new BABYLON.StandardMaterial('exitMat', scene);
plane.material.emissiveColor = new BABYLON.Color3(0.9, 0.8, 0.2); plane.material.emissiveColor = new BABYLON.Color3(0.9, 0.8, 0.2);
plane.position = new BABYLON.Vector3(ex, 0.01, ez); plane.position = new BABYLON.Vector3(ex, 0.01, ez);
exitBox = plane; exitBox = plane;
levelMeshes.push(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) { function spawnCameraAt(grid) {
@@ -262,11 +289,26 @@ function spawnCameraAt(grid) {
const halfH = (h * cellSize) / 2; const halfH = (h * cellSize) / 2;
const px = x*cellSize - halfW + cellSize/2; const px = x*cellSize - halfW + cellSize/2;
const pz = y*cellSize - halfH + cellSize/2; const pz = y*cellSize - halfH + cellSize/2;
try { try {
if (camera && camera.position) { if (camera && camera.position) {
camera.position = new BABYLON.Vector3(px, 1.6, pz); camera.position = new BABYLON.Vector3(px, 1.6, pz);
} }
} catch (e) {} } 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; return;
} }
} }