News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

Object Management

Started by kevin, May 12, 2012, 05:27:25 PM

Previous topic - Next topic

kevin

  Object Management

     This is another variation of how we can store 'game objects/characters' in a typed array, which if you've looked through forum examples  crops up pretty frequently.   It's one of those things where the number of solutions is only limited by your creativity really.   Here we have a slight variation on the standard style of loop, where we have a FOR / NEXT running through all the cells in the array, and query to see if this object is alive or not.  

     A bit like this

PlayBASIC Code: [Select]
      For lp =1 to GetArrayElements(BadGuys())

; check if there's a allocated structure at this position in the array
if BadGuy(lp)
; This object exists, so here we update it
endif

next



     
     Generally if you use the above approach, you end up with an array that has holes in it over time.   So you could be looping through a bunch of objects that don't exit.   What impact that has on your programs performance is debatable, since the object counts are generally only in the double, or barely triple digits and we're not running on Vic-20's anymore.

     Anyway, the idea in the following example is to keep the array of objects in a solid bank of 'alive' objects at the start of the array.   To do this means we have to move items when something needs to be deleted.    There's a few ways we can do this, but first we'll look through a brute force solution.     In this version, when any objects needs to be deleted, we copy all the following objects back up and over themselves using the CopyArrayCells command.   Depending upon the size of the array and the frequency of deletion this as as good a solution as any really.  But if had to delete a large groups of objects each frame, then the copying will no doubt have impact at some point.  

       EXAMPLE #1

 
PlayBASIC Code: [Select]
   ; -------------------------------------------------------------
; Declare type to hold the properties of our game character
; -------------------------------------------------------------
Type tObject
x#
y#
angle#
Speed#
Size
Colour
EndType


; Create an array with 100 cells of type tObject
Dim Objects(100) as tObject



; ----------------------------------------------------------------
; >> MAIN LOOP
; ----------------------------------------------------------------
Do

; Clear The Screen
Cls


; Run Through and update/draw and kill the charcters in the object array
ProcessObjects()



; randomly add new batchs of objects to the list
if Rnd(1000)>500
for lp =0 to rnd(10)
SpawnObject()
next
endif

; show the screen to the user
Sync
loop EscKey()=true


End






; -------------------------------------------------------------
; This sub routine randomly spawns a single object.
; -------------------------------------------------------------

Psub SpawnObject()

index =GetFreeCell(Objects())

Objects(Index)=new tObject

Objects(Index).x =rnd(800)
Objects(Index).y =rnd(600)
Objects(Index).Angle =rnd(360)
Objects(Index).Speed =rndRange#(1,5)
Objects(Index).Size =rndRange#(10,20)
Objects(Index).Colour =rndrgB()


EndPsub


; -------------------------------------------------------------
; This sub routine randomly spawns a single object.
; -------------------------------------------------------------


Psub ProcessObjects()


; Work out a clipping area that all characters will be clipped against
pad=50
ViewPortX1=-Pad
ViewPortY1=-Pad
ViewPortX2=GetScreenWidth()+Pad
ViewPortY2=GetScreenHeight()+Pad


; lock the screen buffer, to help with drawing batches of circles
lockbuffer

; for through all array from Index #1 to it's highest
For lp=1 to GetArrayElements(objects())


; Check this type exists ? If so, we update the object
; if not we can stop looping, since we're at the end of the
; objects
if Objects(lp)


; get this objects angle and speed
Angle#=Objects(lp).Angle
Speed#=Objects(lp).Speed

; calc the objects new position
x#=Objects(lp).X+Cos(Angle#)*Speed#
y#=Objects(lp).y+Sin(Angle#)*Speed#


; check if the object still in legal space
if PointInBox(X#,y#,ViewPortX1,ViewPortY1,ViewPortX2,ViewPortY2)=false

; Kill this object can copy the following cells up
RemoveObject(lp)

; Subtract one from the LP counter,so we don't step over any objects
; that may have been copied back
lp--

; Jump to the end of this loop and continue for loop
Continue
endif


; it's alive so we draw it
Circlec x#,y#,Objects(lp).size,true,Objects(lp).Colour

; store it's new position
Objects(lp).X=x#
Objects(lp).Y=Y#


else

; if the objects doesn't, then we're at the end of the active objects
; so we can exit this for loop now
Exitfor

endif

next

; release our lock of screen
unlockbuffer

EndPsub

Login required to view complete source code




       EXAMPLE #2

       This version doesn't bother reclaiming delete indexes like the previous version, this allows the object to persist in the same location within the array , but we get some extra looping overhead of when the array contains null objects.    if the Object count in the game was going to fluctuates a lot, then it'd be handy to monitor the size of array every now and then and shrinking it where possible.  


PlayBASIC Code: [Select]
   ; -------------------------------------------------------------
; Declare type to hold the properties of our game character
; -------------------------------------------------------------
Type tObject
x#
y#
angle#
Speed#
Size
Colour
EndType


; Create an array with 100 cells of type tObject
Dim Objects(100) as tObject



; ----------------------------------------------------------------
; >> MAIN LOOP
; ----------------------------------------------------------------
Do

; Clear The Screen
Cls


; Run Through and update/draw and kill the charcters in the object array
ProcessObjects()



; randomly add new batchs of objects to the list
if Rnd(1000)>500
for lp =0 to rnd(10)
SpawnObject()
next
endif


; show the screen to the user
Sync
loop EscKey()=true


End






; -------------------------------------------------------------
; This sub routine randomly spawns a single object.
; -------------------------------------------------------------

Psub SpawnObject()

index =GetFreeCell(Objects())

Objects(Index)=new tObject

Objects(Index).x =rnd(800)
Objects(Index).y =rnd(600)
Objects(Index).Angle =rnd(360)
Objects(Index).Speed =rndRange#(1,5)
Objects(Index).Size =rndRange#(10,20)
Objects(Index).Colour =rndrgB()


EndPsub


; -------------------------------------------------------------
; This sub routine randomly spawns a single object.
; -------------------------------------------------------------


Psub ProcessObjects()


; Work out a clipping area that all charcters will be clipped against
pad=50
ViewPortX1=-Pad
ViewPortY1=-Pad
ViewPortX2=GetScreenWidth()+Pad
ViewPortY2=GetScreenHeight()+Pad


; lock the screen buffer, to help with drawing batches of circles
lockbuffer

; for through all array from Index #1 to it's highest
For lp=1 to GetArrayElements(objects())


; Check this type exists ? If so, we update the object
; if not we can stop looping, since we're at the end of the
; objects
if Objects(lp)


; get this objects angle and speed
Angle#=Objects(lp).Angle
Speed#=Objects(lp).Speed

; calc the objects new position
x#=Objects(lp).X+Cos(Angle#)*Speed#
y#=Objects(lp).y+Sin(Angle#)*Speed#


; check if the object still in legal space
if PointInBox(X#,y#,ViewPortX1,ViewPortY1,ViewPortX2,ViewPortY2)=false

; Kill this object
Objects(lp)=NUll


; Jump to the end of this loop and continue for loop
Continue
endif


; it's alive so we draw it
Circlec x#,y#,Objects(lp).size,true,Objects(lp).Colour

; store it's new position
Objects(lp).X=x#
Objects(lp).Y=Y#


endif

next

; release our lock of screen
unlockbuffer


EndPsub



 

 

     Related Examples:

      * Object Management (Character Life Cycles)
      * Manual Type Caching
      * Array Allocation Management Examples
      * Linked List / SpriteHit  Game Frame Work Example
      * Linked List of Typed Pointers
      * Type List Example
      * Manual Link Lists