Recursive functions

Blitz3D Forums/Blitz3D Programming/Recursive functions

AngelOnFira(Posted 2014) [#1]
So in the game I'm working on I have a function for the mainmenu() and for the maingame(). When the user tells the main menu that they want to play the game, I just send them to the maingame() function and everything starts working from there. That said, if they want to go back to the main menu, I just tell the game to go back to mainmenu(). The problem with this is that whenever I go to one or the other, it is still running the primary function, just the new function is inside of if. If I say return it will just go back to the previous function. I was wondering if there was a way of calling a function without it being inside of the other function, so if you go back and forth you don't get function inside of function inside of function and so on. Of course I could use Goto but I am under the impression that that isn't the best practice to use for organization. Is there a way that saying this function is independent of itself, or is there a better way to go about this?


RemiD(Posted 2014) [#2]
Personally i use states to manage which procedures/functions are executed and in which order.

For example :
;before the main loop :
global InteractionMode%
const CGUI% = 1
const CWorld% = 2
InitializeInteractionMode()

global ViewMode%
const CFirstPerson% = 1
const CThirdPerson% = 2
InitializeViewMode()

global CharactersCount%
Dim CharacterRenderer(10)
Dim CharacterActionState%(10)
Dim CharacterAnimationState%(10)

;in the mainloop :
While(keydown(1)<>1)
 If(InteractionMode = CGUI)
  GetInput()
  UpdateInteractionMode()
  UpdateGUI()
 elseif(InteractinMode = CWorld)
  GetInput()
  UpdateInteractionMode()
  UpdateViewMode()
  UpdatePlayer()
  UpdateBots()
  PlayStopAnimations()
  UpdateHUD()
 endif
 Render()
 Flip()
 PlayStopSounds()
Wend

End()


Each component of the game has several states and this helps me to modify what procedures/functions the program runs.


Yasha(Posted 2014) [#3]
Similar to RemiD's suggestion. You do need to jump back down the stack of invocations before climbing up it some more. You can implement a simple "service" architecture by simply having all of your different modes return a key indicating what they want to yield control over to:

Const MENUMODE = 0, SPMODE = 1, MPMODE = 2, KILLMODE = 3

Server MENUMODE    ;Start game

Function Server(mode)
    Repeat
        Select mode
            Case MENUMODE : mode = RunMenu()
            Case SPMODE   : mode = RunSinglePlayer()
            Case MPMODE   : mode = RunMultiPlayer()
            Case KILLMODE : End
        End Select
    Forever
End Function

Function RunMenu()
    While ...        ;A complete menu main loop
    Wend
    Return <next game mode>
End Function

Function RunSinglePlayer()
    While ...        ;A complete game loop with RenderWorld, Flip etc.
    Wend
    Return <next game mode>
End Function

...etc


There are some details to work out, e.g. whether you want services to be able to "pause" and have a persistent state or not. You might leave a world running and render the menu over the top of it, but doing so would demand that you also have a "cleanup" service that runs before you can switch e.g. between single and multiplayer, or before reloading a save.

Note that you can thread "next state" through services as well, by passing it into the service function as a parameter, so a cleanup or load knows what to hand off to. You could even get more advanced and use comma-separated strings or something instead of ints, to enqueue multiple future states, e.g. cleanup -> load -> SP.


AngelOnFira(Posted 2014) [#4]
Hmm very interesting, haven't thought of doing it this way. So basically you're making that your game loop and never leaving that... I always imagined having to jump from one function to another to complete tasks. Thanks!