Given the complex animation behavior you are looking for, I would definitely limit runaway callbacks and timeouts.
I would do something like this:
function first_figure_moves_towards_second_figure() {
}
function first_figure_attacks() {
}
function second_figure_blocks_attack() {
}
var animation_script = [
{
at_time: 30 * 1000,
animation: first_figure_moves_towards_second_figure
},
{
at_time: 31 * 1000,
animation: first_figure_attacks
},
{
at_time: 32 * 1000,
animation: second_figure_blocks_attack
}
];
Then execute the master function with an animation control script, for example:
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 without messing up callbacks, timeouts, and intervals - and instead focus on script animation and atomic animation blocks.
Edit after comments:
Note that the names of the functions in the script animation (for example, first_figure_attacks) are references to functions - saved for later execution. Adding parameters will lead to their functional calls - their immediate execution.
You can use anonymous functions to add the following parameters:
var animation_script = [
{
at_time: 5 * 1000,
animation: function () { doAttack('left', '#char1', '#char2', 2000); }
}
];
, , , doAttack, , :
function doAttack(side, c1x, c2x, speed) {
}
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)
}
];