It won't have as much effect as you might think. For a one-off call (such as during initialisation), then you may as well use function names. However if you are planning to call a function pointer over and over again, then use the name to get the address, then use the address instead.
The overhead of function pointers is relatively low - for example, I wouldn't replace 1 or 2 if statements with a jump table of function pointers, but over that, then yes it would definitely be a consideration.
sync on
sync rate 60
autocam off
dim Behaviour(3) as dword
Behaviour(0) = get ptr to function("MoveClockwise")
Behaviour(1) = get ptr to function("MoveAnticlockwise")
Behaviour(2) = get ptr to function("MoveFigure8")
Behaviour(3) = get ptr to function("Occillate")
dim Colour(3) as dword
Colour(0) = rgb(255,0,0) ` Red
Colour(1) = rgb(255,255,0) ` Yellow
Colour(2) = rgb(255,0,255) ` Purple
Colour(3) = rgb(255,255,255) ` White
type Object_t
BehaviourID as integer
Speed as float
Flag as integer
endtype
dim Objects(0) as Object_t
B = 0
for Object = 1 to 20
array insert at bottom Objects()
Objects().BehaviourID = B
Objects().Speed = 0.5
Objects().Flag = 0
make object cube Object, 3.0
repeat
x = rnd(100)-50.0
z = rnd(100)-50.0
until abs(x) > 10.0 and abs(z) > 10.0
position object Object, x, 0.0, z
yrotate object Object, rnd(359)
color object Object, Colour( Objects().BehaviourID )
inc B
if B > array count( Behaviour() ) then B = 0
next i
position camera 0.0, 120.0, 0.0
point camera 0.0, 0.0, 0.0
do
UpdateObjects()
sync
loop
function UpdateObjects()
local Object as integer
local Action as dword
` NOTE:
` Here's the main movement loop
` No 'if's, no 'selects' - just do it.
for Object = 1 to array count( Objects() )
Action = Behaviour( Objects(Object).BehaviourID )
call function ptr Action, Object
next
endfunction
function MoveClockwise(Object as integer)
yrotate object Object, wrapvalue( object angle y(Object) + 2.0 )
move object Object, Objects( Object ).Speed
endfunction
function MoveAnticlockwise(Object as integer)
yrotate object Object, wrapvalue( object angle y(Object) - 2.0 )
move object Object, Objects( Object ).Speed
endfunction
function MoveFigure8(Object as integer)
if Objects(Object).Flag >= 0
yrotate object Object, wrapvalue( object angle y(Object) + 3.0 )
else
yrotate object Object, wrapvalue( object angle y(Object) - 3.0 )
endif
inc Objects(Object).Flag
if Objects(Object).Flag > 120 then Objects(Object).Flag = -120
move object Object, Objects( Object ).Speed
endfunction
function Occillate(Object as integer)
` If flag not set, point object towards origin and set the flag
if Objects(Object).Flag = 0
Objects(Object).Flag = 1
point object Object, 0.0, 0.0, 0.0
endif
` Flag will be set to either 1 (forward) or -1 (backward)
` Multiply the speed by the flag will move the object in the right direction
move object Object, Objects(Object).Speed * Objects(Object).Flag
if sqrt( object position x(Object) ^ 2.0 + object position z(Object) ^ 2.0 ) > 80.0
Objects(Object).Flag = Objects(Object).Flag * -1
endif
endfunction
Quote: "So on coroutines you could, basically run two functions at once?"
Yes. I have an incomplete example somewhere on my hard-drive where I load some terrain data, and create and populate a multi-limbed object from that data, and while doing so, keep a fixed frame rate.
The function that does this runs in its own coroutine. When initiated, it creates a blank object then yields control, then loads the data and yields control, then in a loop, updates each limb data, yielding control each time the current limb is completed, then finally, carries out a few final settings before yielding control again. This will then be repeated for any other object creation requests that have been made.
This would work just as well with any other long-running process, for example path-finding.
If I can track down the code for this then I'll post it.