There has been a lot of talk about this lately, so I thought I'd post an example of exactly how to do it.
This is animation blending, using interpolation. It is NOT combining animations. That is, animating the top half of a model as firing and the bottom as walking by combining different animations.
What this does is blend one animation smoothly to another. This allows your model to go from walking to attacking or lying down to standing up smoothly. It looks really good when you do it properly.
There are two examples - the first one is the initial tech demo that I used to see if I could get it to work. It is not timer based, and sort of a hack. It's not directly usable in a game in this form, but it's easier to understand.
The second example is timer based. Both the animation and the blending are based on the elapsed time for each loop. This method can, and should, be used in games. It does not rely on the FPS. Also, it is not passive timer control. It will animate the model at the correct speed no matter how fast or slow the computer is running. It will skip frame if necessary, and there is never lag.
First code, non timer-based interpolations.
rem _ _ _ _ ___ _ _ _
rem /_ _ _ (_)_ __ __ _| |_(_)___ _ _ | _ ) |___ _ _ __| (_)_ _ __ _
rem / _ | ' | | ' / _` | _| / _ ' | _ / -_) ' / _` | | ' / _` |
rem /_/ __||_|_|_|_|___,_|__|____/_||_| |___/____|_||___,_|_|_||___, |
rem |___/
rem ___ _ ___ _ _ ___ ___
rem / __|__ _ __| |_ / __| _ _ _| |_(_)___ |_ _|_ _|
rem | (__/ _` (_-< ' | (_| || | '_| _| (_-< | | | |
rem _____,_/__/_||_| ____,_|_| __|_/__/ |___|___|
Rem Initialize program
sync on
center text screen width()/2,screen height()/2,"Loading"
sync
load object "export.x",1
set object filter 1,0
make light 1
position camera 0.0,1,-2.0
color backdrop rgb(0,0,0)
Rem Just setting a variable to display the directions
message as string="Hold down spacebar to see the interpolations between transition frames."
Rem Begin Main Loop
do
Rem Animation Set 1
for i=0 to 38
`Set the frame to the same as the loop number
set object frame 1,i
wait 20
center text screen width()/2,10,message
text 10,30,"Object Frame: "+str$(object frame(1))
sync
next i
Rem Animation Set 1 interpolations
Rem The frame number remains the same, we just advance it toward the next
if spacekey()
for i=1 to 100
Rem Advance interpolation from 1 to 100, progressively
set object interpolation 1,i
Rem Set the frame to next frame. Resulting frame will be a combination of previous frame and this frame
set object frame 1,39.0
Rem Slight delay to slow things down
wait 5
center text screen width()/2,10,message
text 10,30,"Object Frame: "+str$(object frame(1))
text 10,40,"Interpolating "+str$(i)+" %"
sync
next i
endif
Rem Animation Set 2 - commands are just a repeat of the above commands
for i=39 to 71
set object frame 1,i
wait 20
center text screen width()/2,10,message
text 10,30,"Object Frame: "+str$(object frame(1))
sync
next i
if spacekey()
for i=1 to 100
set object interpolation 1,i
set object frame 1,72.0
wait 5
center text screen width()/2,10,message
text 10,30,"Object Frame: "+str$(object frame(1))
text 10,40,"Interpolating "+str$(i)+" %"
sync
next i
endif
Rem Animation Set 3
for i=72 to 96
set object frame 1,i
wait 20
center text screen width()/2,10,message
text 10,30,"Object Frame: "+str$(object frame(1))
sync
next i
if spacekey()
for i=1 to 100
set object interpolation 1,i
set object frame 1,1.0
wait 5
center text screen width()/2,10,message
text 10,30,"Object Frame: "+str$(object frame(1))
text 10,40,"Interpolating "+str$(i)+" %"
sync
next i
endif
sync
loop
Second example, using timer based animation and blending.
rem _ _ _ _ ___ _ _ _
rem /_ _ _ (_)_ __ __ _| |_(_)___ _ _ | _ ) |___ _ _ __| (_)_ _ __ _
rem / _ | ' | | ' / _` | _| / _ ' | _ / -_) ' / _` | | ' / _` |
rem /_/ __||_|_|_|_|___,_|__|____/_||_| |___/____|_||___,_|_|_||___, |
rem |___/
rem _ _____ _ _ _ _
rem _| |_ |_ _(_)_ __ ___ _ _ __ _ _ _ (_)_ __ __ _| |_(_)___ _ _
rem |_ _| | | | | ' / -_) '_| / _` | ' | | ' / _` | _| / _ '
rem |_| |_| |_|_|_|____|_| __,_|_||_|_|_|_|___,_|__|____/_||_|
rem
rem ___ _ ___ _ _ ___ ___
rem / __|__ _ __| |_ / __| _ _ _| |_(_)___ |_ _|_ _|
rem | (__/ _` (_-< ' | (_| || | '_| _| (_-< | | | |
rem _____,_/__/_||_| ____,_|_| __|_/__/ |___|___|
Rem Initialize program
sync on
center text screen width()/2,screen height()/2,"Loading"
sync
load object "export.x",1
set object filter 1,0
color backdrop rgb(0,0,0)
make light 1
position camera 0.0,1,-2.0
set object interpolation 1,50
Rem Initialize Variables
`This is the animation frame rate of the object, defined as frames per second
animSpeed#=25.0
`Set the timer variable. Timers are stored as integers
animTimer=timer()
`This is the blend rate. Increase to speed up the blends. At 75.0, it's a bit slow.
blendRate#=75.0
Rem Instruction string
message as string="Hold down spacebar to add extra syncs per loops to see the effect on blending."
Rem Main Loop
do
Rem Get the time stamp by subtracing timer from last timer. It is the time each loop takes in milliseconds.
time=timer()-animTimer
Rem Here, we multiply the elapsed milliseconds by the object speed in milliseconds
Rem We get the speed in milliseconds by dividing the speed in seconds by 1000
timeFrame#=time*(animSpeed#/1000.0)
Rem If we're not blending, then just advance the frame
if blend=0 then animFrame#=animFrame#+timeFrame#
Rem If we reach the end of the first animation set, begin blending to the next
if animFrame#>=38 and animFrame#<39
blend=1
animFrame#=39.0
endif
Rem If we reach the end of the second animation set, begin blending to the next
if animFrame#>=71 and animFrame#<72
blend=1
animFrame#=72.0
endif
Rem If we reach the end of the third animation set, begin blending to the next
if animFrame#=>96
blend=1
animFrame#=0
endif
Rem If we are blending, advance the blend progressively
if blend=1
blendFrame#=blendFrame#+(time*(blendRate#/1000.0))
set object interpolation 1,blendFrame#
endif
Rem Set the next frame. It only advances if we're not blending
set object frame 1,animFrame#
Rem If the progressive blend reaches 100, stop blending and return control to normal animation
if blendFrame#>=100
blendFrame#=0
blend=0
set object interpolation 1,100
animFrame#=animFrame#+1
set object frame 1,animFrame#
endif
Rem Set the timer variable
animTimer=timer()
Rem On screen display
text 10,10,str$(screen fps())
text 10,30,"Object Frame: "+str$(object frame(1))
text 10,40,"Blend Frame: "+str$(blendFrame#)
text 10,50,"Blend Frame: "+str$(blend)
text 10,70,message
sync
loop
And finally, the project. The project includes the media necessary to run the project. It's small, a 567 kb .ZIP file. It includes projects of both examples. All you have to do is open them and compile.
Animation Blending, regular and Timer Based project download
All of the code is well commented, so I hope that it's understandable. My hope is that DBP projects will improve with this animation technique. Smoother animations + timer based controls are definitely a plus. It's the same technique that I use in my game, except that I use UDTs to define all of the animation ranges. I didn't include that for the sake of simplicity.
Enjoy!
[EDIT]
Ignore the note about adding syncs to the loop. That was for something I was working with Fallout on.
Come see the WIP!