This tutorial will show you how to navigate through a 3D environment using your keyboard's arrows, much like a first person shooter game such as Doom (or Halo these days). To achieve this, you'll need three things:
- A surface to navigate along - use planeGeometry or follow this guide to set up a fancier terrain
- The ThreeX.Keyboardstate script by Jerome Etienne
- Some music - this is just for you to enjoy following the tutorial more
Step 1: Include the ThreeX.Keyboardstate Script
An easy first step - just include the ThreeX.Keyboardstate script underneath the main three.js script:
<script src="libs/three.js"></script> <script src="libs/THREEx.KeyboardState.js"></script>
Step 2: Create a skeleton Camera Control Object
Using the combination/constructor prototype pattern (a way of writing object oriented JavaScript), create a Camera Controls object:
/** * CameraControls */ function CameraControls(){ //constructor } CameraControls.prototype={ constructor:CameraControls };
Above is the basic structure for our CameraControl object:
- In line 4, we define create the constructor for the CameraControls object.
- In line 8, we add the constructor to the CameraControls object
Now inside the prototype declaration, we can add a function called 'update' which will contain all the code related to moving the camera around the world:
CameraControls.prototype={ constructor:CameraControls, update:function(camera, keyboard, clock){ //functionality to go here } };
Line 4 shows the new update function, which has camera, keyboard and clock variables:
- It's obvious what the camera is
- Keyboard will be a ThreeX.Keyboardstate instance
Now your set up, and we can start adding in the main functionality to control the camera position.
Step 3: Move the camera using ThreeX.Keyboardstate
Inside the update
function created in the previous step, we'll add all the code to move the camera about - using the ThreeX.Keyboardstate script included in step 1.
To start, define 3 variables at the top of the update function:
var delta = clock.getDelta(); // seconds. var moveDistance = 150 * delta; // 200 pixels per second var rotateAngle = Math.PI / 2 * delta; // pi/2 radians (90 degrees) per second
What are these for?
delta
uses the clock instance passed into the update function - it is used to define the speed inmoveDistance
androtateAngle
moveDistance
defines how many pixels the camera will move per second when a direction key is pressedrotateAngle
does the same asmoveDistance
, but for rotating left and right
Now we can move onto hooking up the keyboard presses with the camera. Keep in mind that in the following codeblock, keyboard
is a ThreeX.Keyboardstate
object passed into the update function, so has some awesome functionality. The keyboard
(ThreeX.Keyboardstate instance) object has a pressed()
function, which accepts any key on the keyboard as a parameter. Therefore, to detect if the up arrow is being pressed, we can pass in "up":
if ( keyboard.pressed("up") ){ //if up is pressed, move the camera into the screen camera.translateZ( -moveDistance ); }
Above, we use the translateZ
function available to the camera object, and move the camera into the screen (away from you) by providing a negative moveDistance
value.
That's actually as complicated as it gets - implementations of the other arrow key presses can be seen below. Left and right rotate the camera rather than move it:
// move forwards/backwards/left/right //up if ( keyboard.pressed("up") ) camera.translateZ( -moveDistance ); //down if ( keyboard.pressed("down") ) camera.translateZ( moveDistance ); // rotate left/right THREE.Matrix4().identity(); //left if ( keyboard.pressed("left") ) camera.rotateOnAxis( new THREE.Vector3(0,1,0), rotateAngle); //right if ( keyboard.pressed("right") ) camera.rotateOnAxis( new THREE.Vector3(0,1,0), -rotateAngle);
Step 4: Use the CameraControls object in your main script
To actually use the object created in the previous steps, you first have to create an instance of it:
var cameraControls = new CameraControls();
Then, create the keyboard instance (along with clock and camera):
var keyboard = new THREEx.KeyboardState(); var clock = new THREE.Clock(); var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
And finally use the update function we created in the render function of your main three.js script:
cameraControls.update(camera,keyboard,clock);
Well Done
Congrats, you're done - if there's any questions/improvements please add them in the comments.