You're welcome.
I'm currently playing around with a few small ideas while I'm watching the double-glazing fitters do their thing, and I thought I'd post something I've thrown together this morning.
One of the things that happens so often in games is that you want some code to run every frame, such as updating a timer, deleting objects, sprites, sounds etc
One of the ways to deal with this is to write a function that contains all of this code with the sync command, and to replace all calls to sync with calls to this function instead.
With the aid of one or two of the utility plug-ins, I though I'd have a go at providing a standard way to do this.
Paste the following code into it's own .dba file and include the code in your project when it's needed:
remstart
SyncFunctions.dba
Handle = RegisterSyncFunctions( PreSyncFP, PostSyncFP )
Register a pair of functions to be executed pre & post sync.
The functions that the functions pointers come from should not accept any arguments.
UnregisterSyncFunctions( Handle )
Unregister a previously registered pair of functions
DoSync()
Execute all pre-sync functions, issue a sync command, then execute all post-sync function.
remend
type __SF__SyncFunctions_t
ID as integer
PreSync as dword
PostSync as dword
endtype
global dim __SF__SyncFunctions() as __SF__SyncFunctions_t
global __SF__LastSyncID as integer
global __SF__InitialisedSyncFunctions as integer
function RegisterSyncFunctions(PreSync as dword, PostSync as dword)
local Pos as integer
if function ptr is valid( PreSync ) = 0 then PreSync = 0
if function ptr is valid( PostSync ) = 0 then PostSync = 0
if PreSync = 0 then if PostSync = 0 then exitfunction -1
if __SF__InitialisedSyncFunctions = 0
global dim __SF__SyncFunctions() as __SF__SyncFunctions_t
__SF__InitialisedSyncFunctions = 1
__SF__LastSyncID = 0x0000ffff
endif
array insert at bottom __SF__SyncFunctions()
inc __SF__LastSyncID
__SF__SyncFunctions().ID = __SF__LastSyncID
__SF__SyncFunctions().PreSync = PreSync
__SF__SyncFunctions().PostSync = PostSync
endfunction __SF__LastSyncID
function UnregisterSyncFunctions(ID as integer)
array index to top __SF__SyncFunctions()
while array index valid( __SF__SyncFunctions() )
if ID = __SF__SyncFunctions().ID
array delete element __SF__SyncFunctions()
exitfunction
endif
next array index __SF__SyncFunctions()
endwhile
endfunction
function DoSync()
local i as integer
if __SF__InitialisedSyncFunctions
for i = array count( __SF__SyncFunctions() ) to 0 step -1
if __SF__SyncFunctions(i).PreSync then call function ptr __SF__SyncFunctions(i).PreSync
next
sync
for i = array count( __SF__SyncFunctions() ) to 0 step -1
if __SF__SyncFunctions(i).PostSync then call function ptr __SF__SyncFunctions(i).PostSync
next
else
sync
endif
endfunction
Now, instead of using the DELETE OBJECT command, I can use the DeleteObject function:
function DeleteObject(Object as integer)
position object Object, 99999999.0, Object * 10000.0, 99999999.0
hide object Object
Place object in group Object, 10000
endfunction
function _fp_RecoverSingleObject()
exitfunction get ptr to next function()
endfunction 0
function RecoverSingleObject()
local Object as integer
if group count( 10000 ) > 0
Object = first object in group( 10000 )
delete object Object
endif
endfunction
I then register the recover function with the SyncFunctions library at the start of the program:
RegisterSyncFunctions( _fp_RecoverSingleObject(), 0 )
Then finally, I call DoSync() instead of the SYNC command. Now every time this command is issued, it will delete an object from object group 10000 automatically.
Here's all of that in a simple example:
sync on
sync rate 0
RegisterSyncFunctions( _fp_RecoverSingleObject(), 0 )
for i = 1 to 1000
make object cube i, 1.0
next
repeat
text 0, 0, "Total objects: " + str$( object count() )
text 0, 15, " Live objects: " + str$( group count(0) )
text 0, 30, " Dead objects: " + str$( group count(10000) )
text 0, 60, " FPS: " + str$( screen fps() )
if group count(0) > 0
for i = 1 to 10
DeleteObject( first object in group(0) )
next
endif
DoSync()
until object count() = 0
end
function DeleteObject(Object as integer)
position object Object, 99999999.0, Object * 10000.0, 99999999.0
hide object Object
Place object in group Object, 10000
endfunction
function _fp_RecoverSingleObject()
exitfunction get ptr to next function()
endfunction 0
function RecoverSingleObject()
local Object as integer
if group count( 10000 ) > 0
Object = first object in group( 10000 )
delete object Object
endif
endfunction
You'll need to add an include for the SyncFunctions.dba file too. This is ideal for quick reuse of instances or clones of objects - preload all of your objects, clone or instance them on demand using FIND FREE OBJECT to find an ID to use, delete them when done.
I've also done the equivalent with cloned sounds - cloning sounds on demand, and then freeing them back to be reused later.