UnderwareDESIGN

PlayBASIC => Resources => Source Codes => Topic started by: kevin on April 02, 2009, 10:33:21 PM

Title: Handling Multiple Animations using Timer()
Post by: kevin on April 02, 2009, 10:33:21 PM
 Handling Multiple Animations using Timer()

 
  This example demo's how to handle collections of game objects all animating independently of each other.



[pbcode]
;*=------------------------------------------------------------------------=*   
;
;                    >> Handling Multiple Animations Using Timer<<
;
;                         Code By: Kevin Picone
;
;           Copyright 2009 by Kevin Picone, All Rights Reserved.
;
;*=-------------------------------------------------------------------------=*   
;
; About:
; ======
;
;    This example demonstrates one approach for animating multiple game objects
; base upon the system timer().   The demo displays a grid of doors, each one
; is represented on screen as a line.  So visually it's not too interesting.

;    When the user clicks a door, the door will swing open then automatically
; close.  It could stay open if you like, but I didn't bother.  The interesting
; part is the each door has local animation based upon the time it's been open.  
;
;    What's local animation ?   There's two main types of animation approaches
; used in games programming,  Local and Global.  Local systems are where the
; game object includes animation counters/timers internally, so it's keeping
; track of it's animation state itself.    In global Animation, the game object
; gets it's current frame (animation state) from an external source, thus
; allowing many objects to be animated in unison.       Given the game objects
; in the demo,  each need to animate separately of each other, we'll need to
; take an local animation approach.
;
;   So how we do it ? Well, the mechanics are really pretty simple.   In this
; example, we're initializing the doors to give them a screen position and a
; state.  Each door starts in it's closed state.
;
;   During the programs main loop, we're running through the array of doors.  
; For each door,  we check it's state.  
;
;       If the Door is currently closed, then we check to see if the user
;                    is clicking the mouse upon this door.   If they are,
;                    we change this doors state to Opening and set this
;                    doors Starting animation time. If they didn't, we just
;                    continue on to draw the door.
;
;      If a door is opening or closing,  we apply it's animation logic code.
;                   In this example, we calc the elapsed time (the time from
;                   when the door started to open) in milliseconds .   Then
;                   we use  this time to calculate the doors swing angle and
;                   it's current state.      In the code, one full cycle of
;                   swing animation will take 1000 milliseconds (1 second),
;                    1/2 a second to open and the 1/2 a second to close.    
;
;   So,
;
;        * if the elapsed time is less than 500 milliseconds, the door
;            is opening.  
;
;        * if the elapsed time is greater than 500 milliseconds, the door
;          is closing.  
;
;    And finally if the elapsed time is greater than 1000 milliseconds, the
;  door has closed and it's state is reset to closed.
;
;    So since each door holds it's state and animation timers internally, the
;  same basic logic can be applied to any number of  game objects.
;
;
; Controls:
; ========
;
;     Mouse = Click the mouse on lines
;           ESC = EXIT
;
;
;*=-----------------------------------------------------------------------------=*   





   // Define the some constants that we'll use for the various door states
      Constant DoorState_Closed       =1
      Constant DoorState_Opening    =2
      Constant DoorState_Closing       =3


   // Define the Type to hold everything about the door
      Type tDoor
         state
         X,Y
         Colour
         Size
         AnimationStartTime   
      EndType

   // Create an array to hold a bunch of doors in it
      MaxDoors=50   
      Dim Doors(MaxDoors)  as tdoor
      

   // Run through and init all of the Doors positions on screen and
   // their size and colours
      Xpos=50
      Ypos=100

      For lp=1 to MaxDoors

         // Set the Doors state   
            Doors(lp).State      =DoorState_Closed

         // set this doors doors position on screen
            Doors(lp).x          =Xpos
            Doors(lp).y          =Ypos
   
         // set its' colour and size
            Doors(lp).Colour      =rndrgb()
            Doors(lp).Size         =50

         // move the position coords to where the next door
         // will be      
            Xpos=Xpos+100
            if Xpos=>700
               Xpos=50
               Ypos=Ypos+100
            endif
      next

      

;*=------------------------------------------------------------------------=*   
;                              >> Main LOOP <<
;*=------------------------------------------------------------------------=*   

// Start of programs main DO/LOOP   
   Do

      // Clear Screen to black
         Cls rgb(0,0,0)

   
      // Get Mouse state at start of frame.
         mx=mousex()
         my=mousey()
         mb=mousebutton()

      // Get the current Time (in milliseconds)
         CurrentTime=Timer()

      // Run through and arocess all doors in the Doors() array
         For lp=1 to MaxDoors

            // Check if this door exists or not
            If Doors(lp)

               // Get Thre doors Screen position
               x1#      =doors(lp).x
               y1#      =doors(lp).y

               // set the angle to
               Angle#   =0
               Radius   =doors(lp).size

               // calc the end position of this door
               x2#=cosnewvalue(x1#,angle#,radius)
               y2#=sinnewvalue(y1#,angle#,radius)
      
               // Check the current State of this door.  Is it closed, or opening ?
               Select Doors(lp).State

                     // ----------------------------                  
                     case DoorState_Closed
                     // ----------------------------                  

                        ; This door is closed, so we need to check for mouse clicks on it
                        if MB<>0

                           // Detect a mouse click upon an door
                           if LineIntersectCircle(x1#,y1#,x2#,y2#,mx,my,20,false)
                              Doors(lp).State=DoorState_Opening
                              Doors(lp).AnimationStartTime=CurrentTime
                           endif                     
                        endif


                     // ----------------------------                  
                     case DoorState_Opening,DoorState_Closing
                     // ----------------------------                  

                        ; This door is opening or closing, so we'll animation this one

                        ; Get the number of milliseconds that have past since the door started opening               
                        TimePast=CurrentTime-Doors(lp).AnimationStartTime
                        
                        // Set the state to closing, if it's over 500 milliseconds (1/2 a second)
                        if TimePast=>500
                                 Doors(lp).State=DoorState_Closing
                        endif

                        // Set the state to closed, if it's over 1000 milliseconds (1 whole a second)
                        if TimePast=>1000
                           Doors(lp).State=DoorState_Closed
                        endif

                        // Calc the angle of the door based upon the length of time it's been open
                        // 180 degrees reporesent a full swing cycle (open & close)
                        DegreesPerTick#=180.0/1000
                        Angle#=DegreesPerTick#*TimePast

                        // Reflect the angle so it swings backwards, once it's reached the 1/2 way point                                  
                        if (Angle#>90)
                           Angle#=180-Angle#                        
                        endif

                        // Clip the angle so it's stays within our 90 degree range
                        Angle#=ClipRange(Angle#,0,90)

                        // Calc the doors swining end point    
                        x2#=cosnewvalue(x1#,angle#,radius)
                        y2#=sinnewvalue(y1#,angle#,radius)

               EndSelect

               // Draw the door as a line
               linec x1#,y1#,x2#,y2#,Doors(lp).colour

            EndIF
         next


      // Draw the instructions
         Ink rgb(255,255,255)
         Print "Click to open doors"
   
      // Flip the back buffer to the screen
         Sync

   // loop back to the DO statement above to keep this program running
   loop



[/pbcode]


 Related Examples:

   * Sprite Tweening / Animation (http://www.underwaredesign.com/forums/index.php?topic=4287.0)
    * Movement Path Library Example (http://www.underwaredesign.com/forums/index.php?topic=2253.0)