<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> body { margin: 0; overflow: hidden; } </style> <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script> </head> <body> <script> let camera, scene, renderer; let moveForward = false; let moveBackward = false; let moveLeft = false; let moveRight = false; let moveSpeed = 0.1; let yawObject, pitchObject; let mouseX = 0; let mouseY = 0; let sensitivity = 0.002; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(0, 1.6, 0); const axesHelper = new THREE.AxesHelper(100); scene.add(axesHelper); const gridHelper = new THREE.GridHelper(50, 50); scene.add(gridHelper); yawObject = new THREE.Object3D(); yawObject.position.y = 1.6; yawObject.add(camera); pitchObject = new THREE.Object3D(); pitchObject.add(yawObject); scene.add(pitchObject); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); document.addEventListener("mousedown", onMouseDown, false); document.addEventListener("mouseup", onMouseUp, false); document.addEventListener("mousemove", onMouseMove, false); document.addEventListener("keydown", onKeyDown, false); document.addEventListener("keyup", onKeyUp, false); window.addEventListener("resize", onWindowResize, false); } function animate() { requestAnimationFrame(animate); updateCameraPosition(); renderer.render(scene, camera); } function onMouseDown(event) { if (event.button === 0) { // 左クリック document.body.requestPointerLock(); // マウスをキャプチャして移動を検知する } } function onMouseUp(event) { if (event.button === 0) { // 左クリック document.exitPointerLock(); // マウスキャプチャを解除 } } function onMouseMove(event) { if (document.pointerLockElement === document.body) { mouseX -= event.movementX * sensitivity; mouseY -= event.movementY * sensitivity; } } function onKeyDown(event) { switch (event.keyCode) { case 87: // W key moveBackward = true; break; case 83: // S key moveForward = true; break; case 65: // A key moveRight = true; break; case 68: // D key moveLeft = true; break; } } function onKeyUp(event) { switch (event.keyCode) { case 87: // W key moveBackward = false; break; case 83: // S key moveForward = false; break; case 65: // A key moveRight = false; break; case 68: // D key moveLeft = false; break; } } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function updateCameraPosition() { const direction = new THREE.Vector3(); camera.getWorldDirection(direction); if (moveForward) { pitchObject.position.addScaledVector(direction, -moveSpeed); } if (moveBackward) { pitchObject.position.addScaledVector(direction, moveSpeed); } if (moveLeft) { const left = new THREE.Vector3(); left.crossVectors(camera.up, direction); left.normalize(); pitchObject.position.addScaledVector(left, -moveSpeed); } if (moveRight) { const right = new THREE.Vector3(); right.crossVectors(camera.up, direction); right.normalize(); pitchObject.position.addScaledVector(right, moveSpeed); } pitchObject.rotation.y += mouseX; yawObject.rotation.x += mouseY; // 垂直方向の回転を制限する yawObject.rotation.x = Math.max( -Math.PI / 2, Math.min(Math.PI / 2, yawObject.rotation.x) ); mouseX = 0; mouseY = 0; } </script> </body> </html>