Main Menu

Global / Local Animation

Started by kevin, February 15, 2011, 06:58:47 AM

Previous topic - Next topic

kevin

  Global / Local Animation

   This example takes a look a two ways of solving a simple animation problem.   The program draws a screen full of characters running one of two animation sequences (the anims are just a sequence of numbers).  

  In the first example, each character has a position and animation settings.   Those settings being, the current frame (from the set) and the max number of frames this set contains.   So each character in the list has it's own local animation settings, which need to the bumped each update.  So if we have a 1000 characters, then this small process is being executed 1000 times.    


 Local Animation Version

 
PlayBASIC Code: [Select]
   loadfont "arial",1,18
loadfont "arial",2,32

// Make a series of images as our animation
Dim AnimFrames(32)

For lp=0 to GetArrayElements(AnimFrames())
Img=NewImage(32,32,2)
rendertoimage img
text 0,0,str$(lp)
AnimFrames(lp)=img
Next

rendertoscreen


Type tObject
x#,y# ; final screen position
CurrentFrame
Maxframes
EndType

Dim o as tObject list


MaxObjects=1000

For lp=0 to MaxObjects
o=new tObject
o.x =rnd(getscreenwidth())
o.y =rnd(getscreenheight())

if lp<(MaxObjects/2)
o.maxframes =32
else
o.maxframes =16
endif
next

setfont 2
ink $ffff0000
Do
Cls

frames++

// update the animation logic for each object
t=timer()
For each o()
o.CurrentFrame=mod(o.CurrentFrame+1,o.maxframes)
next
tt1#+=timer()-t

// Draw them loop, so we split processing time
// from the drawing time

t=timer()
lockbuffer
For each o()
drawimage animframes(o.currentframe),o.x,o.y,true
next
unlockbuffer
tt2#+=timer()-t

print "Anim Time:"+Str$(tt1#/frames)
print "Anim Time:"+Str$(tt2#/frames)

print fps()

Sync
loop





 Global Animation Version

   In this version, we're breaking the animation data out of the character structure and making them into a unique animations array.  Now rather than each character manually updating it's local animation settings, it's just pulling the current frame from the pre-calculated global animation array.    So rather than calculating a result multiple times, we're calculating the answer once and then reusing it multiple times.   A simple logical shift, that can be very useful when tweaking your programs performance.


 
PlayBASIC Code: [Select]
   loadfont "arial",1,18
loadfont "arial",2,32

// Make a series of images as our animation
Dim AnimFrames(32)

For lp=0 to GetArrayElements(AnimFrames())
Img=NewImage(32,32,2)
rendertoimage img
text 0,0,str$(lp)
AnimFrames(lp)=img
Next

rendertoscreen


Type tAnim
CurrentFrame
Maxframes
Endtype

Dim GlobalAnims(2) as tAnim

GlobalAnims(1) = nEw tAnim
GlobalAnims(1).CurrentFrame=0
GlobalAnims(1).MaxFrames=32

GlobalAnims(2) = nEw tAnim
GlobalAnims(2).CurrentFrame=0
GlobalAnims(2).MaxFrames=16


Type tObject
x#,y# ; final screen position
anim
EndType


Dim o as tObject list

MaxObjects=1000

For lp=0 to MaxObjects
o=new tObject
o.x =rnd(getscreenwidth())
o.y =rnd(getscreenheight())

if lp<(MaxObjects/2)
o.anim=1 ;32 frame anim
else
o.anim=2 ;16 frame anim
endif


next

setfont 2
ink $ffff0000
Do
Cls

frames++


// update the unique animations
t=timer()
for lp=1 to getarrayelements(GlobalAnims())
CurrentFrame=GlobalAnims(lp).CurrentFrame+1
GlobalAnims(lp).CurrentFrame=mod(CurrentFrame+1,GlobalAnims(lp).maxframes)
next
tt1#+=timer()-t


// Draw them loop, so we split processing time
// from the drawing time

t=timer()
lockbuffer
For each o()
ThisAnim=o.Anim
drawimage animframes(GlobalAnims(ThisAnim).CurrentFrame),o.x,o.y,true
next
unlockbuffer
tt2#+=timer()-t

print "Anim Time:"+Str$(tt1#/frames)
print "Anim Time:"+Str$(tt2#/frames)

print fps()

Sync
loop






  You can apply this seemingly simple concept to not only animation frames, but calculations also,   we often just need to  turn the problem upside down ..


  Want to learn more about program optimization -> A Crash Course In Optimization