## Thursday, August 23, 2012

### Rotation Motion Controls in Three.js

‹prev | My Chain | next›

I enjoyed a huge breakthrough last night. It's one of those breakthroughs that makes a developer's pain and struggles all seem worthwhile. Where you finally have a brilliant stroke of genius to solve a problem in a new or unexpected way. Or, you actually read the documentation. Anyhow...

With my Three.js Physijs rafting simulation in better shape, I am ready to add motion controls to the raft.

First I add a "rudder" to the raft to indicate the direction in which the raft is pointing. I do not have to mess with Physijs for this, since it is just an indicator. I do have to mess around with manual veritices in Three.js in order to create a line:
``````  var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(0, 0, 0));
geometry.vertices.push(new THREE.Vector3(10, 0, 0));
var rudder = new THREE.Line(
geometry,
new THREE.LineBasicMaterial({color: 0xff0000})
);
rudder.position.z = 0;
rudder.position.x = 35;

raft.position.y = 20;
raft.rotation.x = Math.PI/2;``````
I suspect that it might be easier to create a cylinder, but I am glad for a way to create lines. With that, I have my direction indicated:

To add motion controls, first I use the space bar to add a force in the current direction. A simple document listener ought to suffice:
```document.addEventListener("keydown", function(event) {
var code = event.which || event.keyCode;
if (code == 0x20) { // space
pushRaft();
}
else {
console.log(code);
}
});

function pushRaft() {
var angle = raft.rotation.z
, cos = Math.cos(angle)
, sin = Math.sin(angle);

raft.applyCentralForce(new THREE.Vector3(1e8 * cos, 0, 1e8 * sin));
}```
And indeed that does work. I am able to move forward in whatever direction I happen to be pointing.

I need a little more than that in my game, however. I need to be able to steer clear of trouble. For that, I add two more keys to listen for: J/K. When one of those is pressed, I rotate the raft accordingly:
```document.addEventListener("keydown", function(event) {
var code = event.which || event.keyCode;
if (code == 0x20) { // space
pushRaft();
}
else if (code == 0x4a) { // J
rotateRaft(-1);
}
else if (code == 0x4b) { // K
rotateRaft(1);
}
else {
console.log(code);
}
});

function rotateRaft(direction) {
raft.__dirtyRotation = true;
raft.rotation.z = raft.rotation.z + direction * Math.PI / 100;
}```
And that actually works I am now able to rotate and move my raft. Two problems still remain.

First, when I collide with a river bank, the raft sometimes gets some angular velocity. I can likely solve that with some Physijs damping.

Second, when I apply enough force, I can move back upriver. The force that I applied last night from the river needs to be constant and greater than the force that my raft can exert. That seems a trickier proposition. Hopefully I will come up with something tomorrow.

Day #487