Previous: Models. Animated models

Advanced model animation. Bones.

If you have read the previous workshop, you have learned that the models can be animated using frames. So all you need to do is to create frames for standing, walking, running, shooting, jumping, ducking, dieing, and so on. But what do you do if you want to be able to run AND shoot at the same time? Well, you can create another animation that does both these things and name it "runshot" or something like this. Or, you could use bones and create any combination of the existing animations using only C-Script code, like walking + looking up at the same time, or maybe crouching + shooting at the same time or... well, I think I've made my point.

Start WED, open work22.wmp and run it using script22.wdl:

You can see the robot playing its "walk" animation in a while loop; don't forget that you can press the zero key if you want to move and rotate the camera using the arrow keys, "Home", "End", "Page up", "Page down", "<" and ">". Now press and hold the "Space" key for a while:

The robot has rotated its weapons toward the left side of the screen. Release "Space" and the weapons will return to their original position. Now click here to see the robot walking in Med and here to see it turning (you will need Windows Media Player 9 or a newer version of it). You will notice that the 2 animations (walk and turn) are completely different, and yet our script file has blended them together nicely: the robot walks and turns its weapons at the same time! Oh, and the animations look a bit choppy in my movies because I wanted to keep their size as small as possible.

The script file is small enough - see for yourself:

The only thing that needs our attention is action bones_test:

action bones_test
{
    while(1)
    {
       ent_animate(my, null, 0, 0);
       walk_speed += 2 * time_step;
       ent_animate(my, "walk", walk_speed, anm_cycle);

We have discussed "ent_animate" in our previous workshop; the first line of code inside the "while" loop resets all the bones for our model, restoring their original positions. There isn't anything magical with that line of code: setting the animation name to "null" does the job IF your model uses bones. Don't forget to read Med's tutorial if you want to learn more about bone creation and bone animations. We have defined a variable named "walk_speed" which controls the animation speed; change "2" if you want to alter the "walk" animation speed for our robot.

The following line of code animates the robot using its "walk" animation, as discussed in our previous workshop. Ok, let's see that" ent_animate" definition once again; we will need it as a reference anyway:

ent_animate(entity, animation_name, animation_percentage, animation_mode);

There's nothing unusual with our "ent_animate" line of code: it animates our model using its "walk" animation, with the speed given by "walk_speed" and loops the animation because of the "anm_cycle" parameter. Let's discuss the next few lines of code from our action:

       if ((key_space == on) && (turn_speed < 100))
       {
             turn_speed += 10 * time_step;
       }
       if ((key_space == off) && (turn_speed > 0))
       {
            turn_speed
-= 10 * time_step;
       }

The lines above check if we have pressed the "Space" key or not. If we press it and turn_speed has a value below 100, its value will increase with the speed given by "10 * time_step"; otherwise, if "Space" isn't pressed and turn_speed is bigger than zero, its value will be decreased with the speed given by "10 * time_step". So this snippet sets the variable named "turn_speed" to a value that can grow from 0 to 100 if we press and hold "Space", and decreases "turn_speed" slowly if we release "Space". Here's a typical example:

The player waits for 1 second, and then it presses the "Space" key; "turn_speed" starts growing by adding "+10 * time" to its initial value every frame, and stops when it reaches 100, even if the player continues to keep "Space" pressed. Five seconds have passed now, and the player decides to release "Space", so "turn_speed" starts decreasing its value by "-10 * time" each frame, until it reaches zero.

       if (turn_speed > 0)
       {
            ent_animate(my, "turn", turn_speed, anm_add);
       }
       wait(1);
    }
}

The last part of the action checks if "turn_speed" is bigger than zero. If this is true, we "ent_animate" the model with its "turn" animation, using the "anm_add" parameter. This animation mode can't be used for frame-based animations (also known as vertex animations) so I chose not to mention it in our previous workshop: it adds the new bone angles to the old ones, rather than completely replacing the older bone angles. This means that the model will keep walking even if we press the "Space" key in order to trigger its "turn" animation.

Let's review the full action again (briefly):

action bones_test
{
    while(1)
    {
        ent_animate(my, null, 0, 0);
        walk_speed += 2 * time;
        ent_animate(my, "walk", walk_speed, anm_cycle);
        if ((key_space == on) && (turn_speed < 100))
        {
            turn_speed += 10 * time_step;
        }
        if ((key_space == off) && (turn_speed > 0))
        {
            turn_speed -= 10 * time_step;
        }
        if (turn_speed > 0)
        {
            ent_animate(my, "turn", turn_speed, anm_add);
        }
        wait(1);
    }
}

There are 3 "ent_animate" instructions in this action:

- the first one resets the animations (the bone positions) every frame;

- the second instruction animates the robot using its "walk" animation;

- the third "ent_animate" line will run only if "Space" is pressed, playing the "turn" animation and adding the new bone angles to the old ones.

The rest of the code should be really easy to understand.

This paragraph ends the first workshop that deals with bone animations. The code might look a bit complicated at the moment, but don't forget that you can rely on frame-based animations for most (if not all) of your games and move on to bone animations only when you feel the need to do it.

 

Next: The bone collector