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