Monday, July 23, 2012

Three.js First Person Controls

‹prev | My Chain | next›

Today, I hope to make my Three.js avatar move based on human input. I had previously experimented with the FirstPersonControls for the camera movement, but had concluded that it might be better suited for the avatar movement—at least in my "game".

So I start by removing the FlyControls on the camera (it uses many of the was WASD controls) and add FirstPersonControls for the avatar:
  controls = new THREE.FirstPersonControls(avatar);
  controls.movementSpeed = 10000;
The movementSpeed setting was found via trial and error for the camera controls. And indeed, it still seems about right for the avatar, because I am able to maneuver the avatar to the edge of land:

I find it a bit strange that FirstPersonControls rotate the avatar from its normal face-foward direction so that it seems as though it would like to walk from left-to-right:

I can live with that, but I cannot live with what happens if I leave the avatar stationary for a time:

Indeed, it I try walking forward with the "W" key at this point, I walk into the ground:

This may simply be a limitation of applying the FirstPersonControls to an avatar instead of a camera. I set that aside for now, because there are other aspects of avatar motion that bear investigation.

I think I would prefer that the camera follow the avatar as it explores the country, so I no longer add the camera to the Three.js scene. Rather, I add it to the avatar, effectively making the avatar the parent of the camera:
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.z = 1500;
  camera.position.y = 750;
And that seems to work:

Again the rotation of the avatar seems to be coming into play here, having a very negative effect on the overall experience.

Eventually, I track this rotation down to the activeLook setting. Specifically, disabling it seems to do the trick:
  controls = new THREE.FirstPersonControls(avatar);
  controls.movementSpeed = 10000;
  controls.activeLook = false;
The activeLook setting appears to tie mouse position with where the object is looking / oriented. Since I want no orientation changes, setting it to false achieves the behavior that I desire.

Last up for tonight is to get the legs of the avatar moving only when it walks. There are no movement events to which I can bind in FirstPersonControls, nor is there a single i-am-moving boolean. So I have to resort to checking the status of a bunch of different movement booleans to get this working:
var w = 500;
function render() {
  var t_float = clock.getElapsedTime()
    , t = t_float * 1000
    , amplitude = (w/2 - Math.abs((t % (2*w)) - w))/w;

  if (controls.moveForward || controls.moveBackward ||
      controls.moveRight || controls.moveLeft) {
    avatar_left_leg.rotation.x  =    amplitude*(Math.PI/6);
    avatar_right_leg.rotation.x = -1*amplitude*(Math.PI/6);

    avatar_left_arm.rotation.x  =    amplitude*(Math.PI/6);
    avatar_right_arm.rotation.x = -1*amplitude*(Math.PI/6);
  renderer.render(scene, camera);

With that, I can take a nice seaside stroll:

That seems like a good stopping point for tonight. I think tomorrow I will conclude my Three.js exploration with some collision checking.

Day #456

No comments:

Post a Comment