Reputation: 59
I am trying to make a first person controls prototype from scratch in THREE.js. I have successfully got the front and back movements working but I cant get my left and right (a, d) movements working. I tried adding and subtracting 90 degrees from the view angle, and then finding the sine and cosine values of it. but it doesnt work.
I was thinking of moving the player on tangent but dont think thats right and dont know how to do it.
<!DOCTYPE html>
<html>
<head>
<title>THREEJS</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script type="text/javascript">
let width = innerWidth
let height = innerHeight
let scene = new THREE.Scene()
let camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)
let renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(width, height)
document.body.appendChild(renderer.domElement)
let cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshLambertMaterial({ color: 0x00FF00, wireframe: false }))
let plane = new THREE.Mesh(new THREE.PlaneGeometry(20, 20, 20, 10),
new THREE.MeshLambertMaterial({ color: 0xFFFFFF, wireframe: false }))
let light = new THREE.PointLight(0xFFFFFF, 1.5, 20)
plane.rotation.set(-Math.PI / 2, 0, 0)
cube.position.set(0, 1, 0)
light.position.set(0, 10, 0)
scene.add(cube)
scene.add(plane)
scene.add(light)
addEventListener("resize", () => {
width = innerWidth
height = innerHeight
renderer.setSize(width, height)
camera.aspect = width / height
camera.updateProjectionMatrix()
})
camera.position.set(0, 1, 0)
renderer.domElement.onclick = () =>
renderer.domElement.requestPointerLock()
document.addEventListener('pointerlockchange', lockChangeAlert, false);
document.addEventListener('mozpointerlockchange', lockChangeAlert, false);
let player = new THREE.Object3D()
player.position.set(0, 0, 0)
player.add(camera)
scene.add(player)
function updatePosition(event) {
camera.rotation.order = 'YZX'
let { movementX, movementY } = event
let rotateSpeed = 0.002
player.rotation.y -= movementX * rotateSpeed
camera.rotation.x -= movementY * rotateSpeed
camera.rotation.x = Math.max(-Math.PI / 2, Math.min(camera.rotation.x, Math.PI / 2))
camera.rotation.order = 'XYZ'
}
function lockChangeAlert() {
if (document.pointerLockElement == renderer.domElement) {
document.addEventListener("mousemove", updatePosition, false)
} else {
document.removeEventListener("mousemove", updatePosition, false)
}
}
let keys = {}
function keyDown(event) {
keys[event.key] = true
}
function keyUp(event) {
delete keys[event.key]
}
document.onkeydown = keyDown
document.onkeyup = keyUp
function update() {
let moveSpeed = 0.05
cube.rotation.x += 0.01
cube.rotation.y += 0.01
if(keys["w"]) {
player.position.x -= Math.sin(player.rotation.y) * moveSpeed
player.position.z -= Math.cos(player.rotation.y) * moveSpeed
}
if(keys["s"]) {
player.position.x += Math.sin(player.rotation.y) * moveSpeed
player.position.z += Math.cos(player.rotation.y) * moveSpeed
}
if(keys["d"]) {
player.position.x += moveSpeed * Math.sin(player.rotation.y + Math.PI / 2)
player.position.z += moveSpeed * Math.cos(player.rotation.y - Math.PI / 2)
}
if(keys["a"]) {
player.position.x -= moveSpeed * Math.sin(player.rotation.y + Math.PI / 2)
player.position.z -= moveSpeed * Math.cos(player.rotation.y - Math.PI / 2)
}
}
function draw() {
renderer.render(scene, camera)
}
function loop() {
update()
draw()
requestAnimationFrame(loop)
}
loop()
</script>
</body>
</html>
Upvotes: 2
Views: 933
Reputation: 59
After meshing around a little bit, i did this and got it working fine
if(keys["d"]) {
player.position.x += moveSpeed * Math.sin(rotation + Math.PI / 2)
player.position.z += moveSpeed * Math.cos(rotation + Math.PI / 2)
}
if(keys["a"]) {
player.position.x += moveSpeed * Math.sin(rotation - Math.PI / 2)
player.position.z += moveSpeed * Math.cos(rotation - Math.PI / 2)
}
Upvotes: 1