Skip to content

Instantly share code, notes, and snippets.

@EncodeTheCode
Created May 20, 2025 12:04
Show Gist options
  • Save EncodeTheCode/6fadcfb05d28c0d12d4ab66c72dd55b6 to your computer and use it in GitHub Desktop.
Save EncodeTheCode/6fadcfb05d28c0d12d4ab66c72dd55b6 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FPS Room - Combined WASD + Mouse Click Move</title>
<style>
html, body {
margin: 0;
padding: 0;
overflow: hidden;
height: 100%;
}
#overlay {
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
color: white;
font-size: 24px;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
cursor: pointer;
}
</style>
</head>
<body>
<div id="overlay">Click to start</div>
<canvas id="renderCanvas"></canvas>
<!-- Babylon.js CDN -->
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script>
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
scene.gravity = new BABYLON.Vector3(0, -0.5, 0);
scene.collisionsEnabled = true;
// Camera
const camera = new BABYLON.UniversalCamera("camera", new BABYLON.Vector3(0, 2, 0), scene);
camera.checkCollisions = true;
camera.applyGravity = true;
camera.ellipsoid = new BABYLON.Vector3(0.5, 1, 0.5);
camera.speed = 0.2;
camera.fov = BABYLON.Tools.ToRadians(45);
camera.minZ = 0.1;
// Don't use built-in controls — we handle movement manually
camera.detachControl(canvas);
// Lighting
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.9;
// Ground
const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 20, height: 20 }, scene);
ground.checkCollisions = true;
// Room walls
const wallMaterial = new BABYLON.StandardMaterial("wallMat", scene);
wallMaterial.diffuseColor = new BABYLON.Color3(0.6, 0.7, 0.9);
function createWall(x, y, z, rotY = 0) {
const wall = BABYLON.MeshBuilder.CreateBox("wall", { width: 20, height: 4, depth: 0.5 }, scene);
wall.position.set(x, y, z);
wall.rotation.y = rotY;
wall.material = wallMaterial;
wall.checkCollisions = true;
}
createWall(0, 2, -10);
createWall(0, 2, 10);
createWall(-10, 2, 0, Math.PI / 2);
createWall(10, 2, 0, Math.PI / 2);
// Pointer lock
const overlay = document.getElementById("overlay");
overlay.onclick = () => {
overlay.style.display = "none";
canvas.requestPointerLock();
};
document.addEventListener("pointerlockchange", () => {
const locked = document.pointerLockElement === canvas;
if (locked) {
camera.attachControl(canvas);
} else {
camera.detachControl();
overlay.style.display = "flex";
}
});
// Movement logic
const keys = {};
let leftMouseDown = false;
window.addEventListener("keydown", e => keys[e.code] = true);
window.addEventListener("keyup", e => keys[e.code] = false);
window.addEventListener("mousedown", e => {
if (e.button === 0) leftMouseDown = true;
});
window.addEventListener("mouseup", e => {
if (e.button === 0) leftMouseDown = false;
});
scene.registerBeforeRender(() => {
const forward = keys["KeyW"] && leftMouseDown;
if (forward) {
const direction = camera.getDirection(BABYLON.Axis.Z).scale(camera.speed);
camera.cameraDirection.addInPlace(direction);
}
if (keys["KeyA"]) {
const left = camera.getDirection(BABYLON.Axis.X).scale(-camera.speed);
camera.cameraDirection.addInPlace(left);
}
if (keys["KeyD"]) {
const right = camera.getDirection(BABYLON.Axis.X).scale(camera.speed);
camera.cameraDirection.addInPlace(right);
}
if (keys["KeyS"]) {
const backward = camera.getDirection(BABYLON.Axis.Z).scale(-camera.speed);
camera.cameraDirection.addInPlace(backward);
}
});
engine.runRenderLoop(() => {
scene.render();
});
window.addEventListener("resize", () => engine.resize());
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment