UnderwareDESIGN

PlayBASIC => Resources => Source Codes => Topic started by: kevin on February 15, 2011, 06:58:47 AM

Title: Global / Local Animation
Post by: kevin on February 15, 2011, 06:58:47 AM
  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

 [pbcode]
   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

 [/pbcode]


 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.


 [pbcode]


   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


 [/pbcode]


  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 (http://www.underwaredesign.com/forums/index.php?topic=2548.0)