## Sunday, July 15, 2012

### Walking Avatar

‹prev | My Chain | next›

This whole walking Gladius avatar think has taken a bit longer than expected. Still, I think I made some good progress last night. I have the right leg of the avatar moving back-and-forth:

I wound up with a poor algorithm for implementing the back and forth—effectively hard coding when to swing the leg in the opposite direction. I had originally planned on leaving it as-is, preferring working to elegant. But the ugly started to wear on me.

And it also occurred to me that, if I need to oscillate between 1 and -1, that is what sines and cosines are for. So I switch my game task function to use this instead:
``````        var task = new engine.FunctionTask( function() {
var entity = space.findNamed("right-leg-frame")
, transform = entity.findComponent("Transform")
, amplitude = Math.sin(space.clock.time/500);

transform.setRotation([0,0, amplitude*(Math.PI/8)]);
});
The problem with this approach is that the leg swings back and forth like a pendulum (slowing at the extremes), not so much like a leg.

I eventually stumble on an algorithm for more of a triangle wave. which seems to do the trick:
``````        var task = new engine.FunctionTask( function() {
var entity = space.findNamed("right-leg-frame")
, transform = entity.findComponent("Transform")
, t = space.clock.time
, w = 500
, amplitude = (w/2 - Math.abs((t % (2*w)) - w))/w;

transform.setRotation([0,0, amplitude*(Math.PI/8)]);
});``````
The arms are a little more difficult because of the angles. To handle these, I add two frames of reference: one for the initial shift and rotation relative to the body and a second that I can use to implement simpler swinging:
``````        space.add(new engine.Entity("right-arm-frame1",
[
new engine.core.Transform([0.5, 0, 0], [0, -Math.PI/8, Math.PI/3])
],
["avatar"],
space.findNamed("body")
));

[
new engine.core.Transform()
],
["avatar"],
space.findNamed("right-arm-frame1")
));

[
new engine.core.Transform([0, -0.5, 0]),
new cubicvr.Model(resources.cylinder_mesh, resources.blue_material)
],
["avatar"],
space.findNamed("right-arm-frame")
));
``````
At this point, my game `task()` is doing more than tranforming one limb. It has to coordinate four extremities.

So I move the arm and leg transforms out of the game `task()`, leaving `task()` to just swing the arms:
``````        var w = 500
, arm1 = space.findNamed("left-arm-frame").findComponent("Transform")
, arm2 = space.findNamed("right-arm-frame").findComponent("Transform")
, leg1 = space.findNamed("left-leg-frame").findComponent("Transform")
, leg2 = space.findNamed("right-leg-frame").findComponent("Transform");

var task = new engine.FunctionTask( function() {
var t = space.clock.time
, amplitude = (w/2 - Math.abs((t % (2*w)) - w))/w;

leg1.setRotation([    amplitude*(Math.PI/8), 0, 0]);
leg2.setRotation([ -1*amplitude*(Math.PI/8), 0, 0]);

arm1.setRotation([ 0, 0, -1*amplitude*(Math.PI/8)]);
arm2.setRotation([ -1*amplitude*(Math.PI/8), 0, 0]);
});``````
After rotating the camera a bit for a better view, I see the arms and legs move:

And do so in unison:

That will do as a nice stopping point for tonight. The chain of reference frames is both handy (for calculations) and a pain (for added code). I will have to mull that over. That aside, I'm pretty happy with the implementation as well as the result.

Day #448