Yesterday, I discovered the benefits of
__dirtyRotation
in Physijs, this physics engine for Three.js. I used it yesterday to prevent my player from spinning out of control after contact with other objects. Tonight, I plan to use it to restore the spin-to-walk ability.I am not going to rewrite the Three.js first person controls, but I need some of that ability. I start with global variables that hold state (moving and state):
var moving = false; var controlState = {};Next, I need a keydown handler to set the state:
document.addEventListener("keydown", function(event) { // Last wins (for now) because we set the velocity, not apply force function setState(state) { moving = true; controlState = {}; controlState[state] = true; } var speed = 500; var code = event.which || event.keyCode; if (code == 0x57) { // w setState("moveForward"); a_frame.setLinearVelocity({z: -speed, y: 0, x: 0 }); } // ... });I feel a little bad about overwriting
controlState
and the velocity like that, but it works for now—movement is only in one direction.I also use a corresponding keyup handler to reset
controlState
and mark the avatar as no longer moving:document.addEventListener("keyup", function(event) { function stopState(state) { if (controlState[state]) { moving = false; controlState = {}; } } var code = event.which || event.keyCode; if (code == 0x57) { // w stopState("moveForward"); // a_frame.setLinearVelocity({z: 0, y: 0, x: 0 }); } // ... });This allows me to restore the motion of the legs when
moving
is true
. I can also spin the avatar in the proper direction depending on the controls' state: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 (moving) { avatar_left_leg.rotation.x = amplitude*(Math.PI/6); // ... if (controlState.moveLeft) spinAvatar(-Math.PI/2); // ... } else { spinAvatar(0); } scene.simulate(); // run physics renderer.render(scene, camera); }Even the
spinAvatar()
function still works. It works because it spins the avatar inside the Physijs frame so no changes are required:function spinAvatar(angle) { new TWEEN.Tween( { y: avatar.rotation.y } ) .to( { y: angle }, 100 ) .onUpdate( function () { avatar.rotation.y = this.y; }) .start(); }So it turns out that I did not need any additional use of
__dirtyRotation
. As long as it keeps the frame of reference steady, everything just works. Nice.This is all going so smoothly. Something is going to go horribly wrong soon. I just know it.
But failure does not arrive when I set up invisible fences around the island:
scene = new Physijs.Scene;
var fence = new Physijs.BoxMesh(
new THREE.CubeGeometry(ISLAND_WIDTH, 1000, 10),
new THREE.Material(),
0
);
fence.position.z = -ISLAND_HALF;
fence.position.y = 500;
scene.add(fence);
The last argument of zero to the BoxMesh
constructor specifies a mass of zero, which is interpreted as a static object in Physijs. In other words, my fence will not yield, keeping the avatar on the island:I finally do run into a small problem with the avatar's interaction with the ball that I have left on the island for the avatar's amusement. My avatar can no longer budge it:
What fun is that?
Fortunately, it does not take too long to identify the problem. I specified a mass of 1000 for my avatar's frame of reference / Physijs box:
a_frame = new Physijs.BoxMesh(
new THREE.CubeGeometry(250, 250, 250),
new THREE.Material(),
1000
);
It seems that, in Physijs, 1000 is very light. I suppose it is measured in grams.Anyhow, with a slightly heavier mass:
a_frame = new Physijs.BoxMesh(
new THREE.CubeGeometry(250, 250, 250),
new THREE.Material(),
1000*1000*1000
);
I can now send my ball rolling and bouncing around:It is literally minutes of fun!
Actually, what this really means is that I seem to have gotten the hang of Physijs.
Day #481
No comments:
Post a Comment