Programming principles

Everything else that doesn't fall into one of the other PB categories.
jak64
Enthusiast
Enthusiast
Posts: 625
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Programming principles

Post by jak64 »

Hello everyone,
My question may seem "basic" to you but I ask it anyway.

I read, somewhere on the forum, that in a program, we should only have one loop, like while...Wend and manage all the events in this loop.
I would like to point out that my question concerns a game.

In a game, I can have a presentation screen, then a start of game screen, then a game screen, then a game, then the end of the game...

On each of these screens, I will have different events, with buttons or other...

How do I handle this in a single loop, for example I can have a Next button in multiple screens, how do I know, if I only have one loop, which screen the next button refers to?

My idea, for me, is to make a screen, with a loop, for each case, a screen for presentation, with a while...Wend loop and a Flipbuffer(), a screen for the start of the game, with a While...Wend loop and a Flipbbuffer(), etc., each screen management being in a specific procedure.

Please give me your opinions.

A+

// Moved from "Coding Questions" to "General Discussion" (Kiffi)
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 193
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Programming principles

Post by moulder61 »

@jak64,

As no kind of PB expert, or even any kind of programmer if I'm honest, I've had the same question.
Sometimes the logic of how it all fits together doesn't quite work in my head :?:
Anyway, having followed the snake game tutorial by PureProgramming on YouTube, I started to understand the concept of state machines and key handling/mouse handling routines working together.
Basically, in the main loop, check for the state i.e. TitleScreen, GameScreen, GameOver whatever, then in the key/mouse handling routines do the same and therefore you isolate it somewhat.
For example, there's no point checking for sprite collisions on the TitleScreen(probably). Etc.
There are way more proficient programmers on here, but as a beginner myself, that's how I've fumbled along in trying to get a game or two working.
I hope that makes some sense?

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Programming principles

Post by miso »

we should only have one loop
I'm not sure about this. You can have as many main loops, as many you want, but use only one at a time. I usually create a module that initializes screen and mouse etc, and separate modules for splash screen/intro, mainmenu loop, gameloop, shopping screen. I then switch back and forth of them. I usually create a 0 layer module that holds only the common global data, that can be accessed by the other modules.

Modules has not been invented for this, but works like a charm, if you want to put different game behaviors to different loops.
jak64
Enthusiast
Enthusiast
Posts: 625
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Programming principles

Post by jak64 »

Thank you molder61 and miso for your answers.

It's true that there are certainly several ways to proceed but, for my part, I prefer to write procedures independent of the main loop, with a logical test in the main loop which allows me to know where I am, for example, a boolean "Make_presentation" which will execute the procedure Make Presentation() if it is #true. Another boolean "Start_Game" which will execute the procedure "StartGame() when it is #true, etc...

This allows me to develop each procedure independently of the others and not regress on my main code or other procedures that already work.

But I am interested in any other good practice...

See you soon on this Forum which has taught me so many things... And I love PureBasic :D :D :D :D :D
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Programming principles

Post by miso »

We talk about the same thing. I just hid my procedure inside separate modules (in separate files.) :)
jak64
Enthusiast
Enthusiast
Posts: 625
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Programming principles

Post by jak64 »

Hello miso,
Do you mean that every procedure is in a .pbi?

If so, what is the point?
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 193
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Programming principles

Post by moulder61 »

@jak64

What you describe is basically what I said about state machines. Select the state in the main loop then jump to the relevant procedure.
Obviously you would initialise the state to #TitleScreen to start with, then when in the TitleScreen() procedure you would check for a button click or keypress then change the state accordingly, maybe to #Quit or #Playing or #Credits etc?

Code: Select all

Select state
  Case #TitleScreen
    MouseHandler()  ; Check mouse position, button clicks etc.
    TitleScreen()        ; Do TitleScreen related stuff.
  Case GameOver
    MouseHandler()
    GameOver()
EndSelect
Something like that maybe?
I don't pretend to understand it fully, but it works. :P

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
benubi
Enthusiast
Enthusiast
Posts: 220
Joined: Tue Mar 29, 2005 4:01 pm

Re: Programming principles

Post by benubi »

There are a few "game loop" theories that are not specific to PureBasic.

Inside your loop you will have to branch/call a few subroutines in any state (like check Windows Events).

One classic way is to use a "game state"

Code: Select all

; incomplete 
Enumeration
  #Game_Init
  #Game_Loading
  #Game_MainMenu
  #Game_Config
  #Game_Running
  #Game_Finished
  #Game_Hiscores
  #Game_ServerLoading ; or client or connecting to server etc
  ; ...
  EndEnumeration
  
  Global GameState
  Global EXIT
  
  Procedure RenderGameState()
    Select GameState
      ; ...
      Case #Game_Loading
         DisplayLoadScreen()
      Case #Game_Config
         EditConfiguration()
      Case #Game_Running
      	 DrawManyThings()
      	 ; ...
    EndSelect
    FlipBuffers()
  EndProcedure
  
  Procedure MainLoop()
    Repeat
  	DoWindowEvents()
  	DoUserInputs()
  	RenderGameState()  
    Until EXIT
  EndProcedure
  
  
benubi
Enthusiast
Enthusiast
Posts: 220
Joined: Tue Mar 29, 2005 4:01 pm

Re: Programming principles

Post by benubi »

Additionally your DoUserInputs() will have to check in what game state it is, probably. This way you can also separate the event handling and presentation.
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Programming principles

Post by miso »

Do you mean that every procedure is in a .pbi?
If so, what is the point?
I put parts of the game into separate modules, and those modules goes into different files. I can use the same procedure names to create a similar layout
but can get different behavior. For a small game like snake for example, its not necessary, for complex things I found this to be the most convenient.

I often use a short named module like GM (as game manager) at layer 0, that holds only public global variables that can be accessed by the other modules.

Heres a pseudo code, because I'm not sure I can explain it better than this:

Code: Select all

;PSEUDO CODE

DeclareModule mainmenu
  Declare run()
EndDeclareModule

Module mainmenu
  Declare init()
  Declare Destroy()
  Declare update()
  Declare draw()
  
  Procedure init()
    ;get resources, load some graphics, allocates some memory for the main menu
  EndProcedure
  
  Procedure destroy()
    ;releases the resources not needed when switching to another screen/game part
  EndProcedure
  
  Procedure update()
    ;checks for window events in windowed mode, check user input, mouse, etc
    ;if gm::state.s = "button_new_game" : destroy() : newgame::run() : endif
  EndProcedure
  
  Procedure draw()
    ;draw the main menu elements
  EndProcedure

 
  Procedure run()
    init()
    Repeat
      update()
      draw()
    ForEver
  EndProcedure
  
  
EndModule

;--------------

DeclareModule wilderness
  Declare run()

EndDeclareModule

Module wilderness
  Declare init()
  Declare Destroy()
  Declare update()
  Declare draw()
  
  Procedure init()
    ;get resources, load some graphics, allocates some memory etc
  EndProcedure
  
  Procedure destroy()
    ;releases the resources not needed when switching to another screen/game part
  EndProcedure
  
  Procedure update()
    ;if gm::state.s = "button_enter_city" : destroy() : city::run() : endif
  EndProcedure
  
  Procedure draw()
  EndProcedure
  
  Procedure run()
    init()
    Repeat
      update()
      draw()
    ForEver
  EndProcedure
  
EndModule 

;--------------

DeclareModule city
  Declare run()
EndDeclareModule

Module city
  Declare init()
  Declare Destroy()
  Declare update()
  Declare draw()
  
  
  Procedure init()
    ;get resources, load some graphics, allocates some memory etc
  EndProcedure
  
  Procedure destroy()
    ;releases the resources not needed when switching to another screen/game part
  EndProcedure
  
  
  
  Procedure update()
    ;if gm::state.s = "button_enter_shop" : destroy() : shop::run() : endif
  EndProcedure
  
  Procedure draw()
    ;code to draw the city screen
  EndProcedure

  Procedure run()
    init()
    Repeat
      update()
      draw()
    ForEver
  EndProcedure
  
EndModule 
jak64
Enthusiast
Enthusiast
Posts: 625
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Programming principles

Post by jak64 »

Hello and thank you all for your responses.
Post Reply