Tuesday, July 20, 2010

Animating Grouped Raphaël.js Objects

‹prev | My Chain | next›

Last night, I was a bit disappointed to find that I could not use raphaël.js to animate my game players as they moved about the room. The second of the two animations, the player moving or the player animation as it moves, cancels out the first.

I would like to be able to do this in my (fab) game, so I drop down to old-fashioned frame animations. I take my two SVG frames (standing and walking) and pass them to the build_animation() function:
var frames = build_animation(standing, walking);
The build_animation() function works through each SVG description of a frame (using yesterday's draw_object()):
function build_animation() {
var frames = [];
for (var i=0; i<arguments.length; i++) {
frames.push(draw_object(arguments[i]));
};
for (var body_part in frames[0]) {
frames[0][body_part].show();
};
return frames;
}
It shows the first frame—all frames are hidden by draw_object()—then returns the frames.

To move, I need to move both frames so that I can toggle visibility along the way:
var frames = build_animation(standing, walking);
translate_frames(frames, 100, 100, 5*1000);
That function simply iterates over each frame and calls yesterday's translate_object on each:
function translate_frames(frames, x, y, seconds) {
for (var i=0; i<frames.length; i++) {
translate_object(frames[i], x, y, seconds);
}
}
Before animating the player as it moves, I make sure that it does move:

video

Nice!

To animate the player as it walks, I add a call to a new toggle_frames() function at the bottom of translate_frames():
function translate_frames(frames, x, y, seconds) {
for (var i=0; i<frames.length; i++) {
translate_object(frames[i], x, y, seconds);
}
toggle_frames(frames); }
The toggle_frames() function hides the first frame / shows the second frame every other call:
function toggle_frames(frames, count) {
if (!count) count=0;
if (count % 2 == 0) {
for (var body_part in frames[0]) {
frames[0][body_part].show();
};
for (var body_part in frames[1]) {
frames[1][body_part].hide();
};
}
else {
for (var body_part in frames[0]) {
frames[0][body_part].hide();
};
for (var body_part in frames[1]) {
frames[1][body_part].show();
};
}
if (count < 10) {
setTimeout(function(){toggle_frames(frames, count+1)}, 500);
}
}
There is some definite room for DRYing up that code. For now, I just want to make sure it works. At the very end of that function, I call the function again after a half second delay. That will keep calling itself until the tenth time it has been called as specified by the count argument.

With that, I get my animated walk:

video

Happy! Tomorrow, I will clean this up a tad.

Day #170

No comments:

Post a Comment