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)