Given the complex animation behavior you're looking for, I would definately limit rampant callbacks and timeouts.
I would do something like this:
// first define the atomic animation effects
function first_figure_moves_towards_second_figure() {
// animation calls
}
function first_figure_attacks() {
// animation calls
}
function second_figure_blocks_attack() {
// animation calls
}
var animation_script = [
{
at_time: 30 * 1000, // 30 seconds
animation: first_figure_moves_towards_second_figure
},
{
at_time: 31 * 1000, // 31 seconds
animation: first_figure_attacks
},
{
at_time: 32 * 1000, // 32 seconds
animation: second_figure_blocks_attack
}
];
Then have a master function with control of the animation script, like this:
var current_time = 0;
function animate_next() {
var next = animation_script.shift(),
time_between = next.at_time - current_time;
setTimeout(function () {
current_time = next.at_time;
next.animation();
animate_next();
}, time_between);
}
With this you can define your animations free from a jumble of callbacks, timeouts and intervals - and instead focus on the animation script and the atomic animation building blocks.
Edit after comments:
Note that the names of the functions in the animation script (eg. first_figure_attacks
) are function references - stored for later execution. Adding parameters will make them function calls - executing them immediately.
You can use anonymous functions to add parameters like this:
var animation_script = [
{
at_time: 5 * 1000,
animation: function () { doAttack('left', '#char1', '#char2', 2000); }
}
];
or maybe more aesthetically pleasing, you can wrap doAttack to return a function reference, like this:
function doAttack(side, c1x, c2x, speed) {
// animation calls
}
function attackAnimation(side, c1x, c2x, speed) {
return function () {
doAttack(side, c1x, c2x, speed);
};
}
var animation_script = [
{
at_time: 5 * 1000,
animation: attackAnimation('left', '#char1', '#char2', 2000)
}
];