gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > mini-game structure (fsm?!?)

#18574 - darknet - Mon Mar 29, 2004 2:57 am

Here Goes:

I (for those who haven't helped me before) am making a game full of TIMED mini-games, in the vein of warioware microgames (but not that frantic!)

I have 2 games complete (of 4 or 5), but the main driver (main.cpp) is not functioning properly.

Basically, when a player beats a mini-game or time runs out on a mini-game, I want to the user to be transported back to the main menu. With my structure however, I cannot find a clean or good or working way to do this.

Each mini-game is completely self-contained and the all of the game code goes in a startGame() function (i.e. Breakout has void startBreakout() ). I have the user play the games until time either runs out or they complete the game. The main.cpp driver has a loadMiniGame function that does the following:

Code:

void loadMiniGame() {

      drawMode3Background(videoBuffer, menu_Bitmap);
      current_state = IN_MENU;

      int previousButton, button, down, up;

      while(current_state!=QUIT) {

         button = *BUTTONS ^ 0x03ff;
         down = button & ~previousButton;   //pressed since last loop
         up = previousButton & ~button;    //released since last loop

         if( (down & A_BUTTON) !=0) {

            switch(current_state) {
               case IN_MENU:
                  startTxtAdventure();
                  break;
            }
         }
         
         if( (down & B_BUTTON) !=0) {

           switch(current_state) {
               case IN_MENU:
                  startBreakout();
                  break;
            }
         }

         previousButton = button;
         waitForVSync();

      }
}


As of right now, once the mini-game ends the entire program halts and goes nowhere. I tried throwing in other cases within each to no avail. I even have a getState function within each game that gets the final state. No dice when I tried getting the state within the above code and checking if it was a certain value.

I hope this question makes sense. I suppose in an abstract manner the question is how the main driver can regain control of the program once the mini-game halts. Seems easy enough, but been having the worst time getting something going.

Any help is appreaciated + thanks alot for reading.

#18575 - Darmstadium - Mon Mar 29, 2004 3:40 am

If I understand your meaning, I would do something like this: have a variable that keeps track of what phase your game is in. Then in your main loop have if statements that make the game act how you want based on what phase it's in. I'll show you what I mean:
Code:

u8 phase = 0;

while (1)
{
     if (phase == 0)
          doMainMenu();
     if (phase == 1)
          doMinigameOne();
}

Then all's you have to do is change the phase variable to make your game go around between your different things. I hope I was able to help.

#18576 - darknet - Mon Mar 29, 2004 4:01 am

That seems to make sense....except where would I change the phase variable? Right after the function call? i.e.

Code:

 if (phase == 0)
          doMainMenu();
          phase = 1;


? You did understand my question correctly. I think I forgot to mention part of the dilemma was where that overall state variable is being changed (or phase variable). I have been doing something somewhat similar and changing the state in each game and then testing for equality...but that does not seem to work.

Thanks,
-Mike

#18579 - tepples - Mon Mar 29, 2004 4:18 am

darknet wrote:
That seems to make sense....except where would I change the phase variable? Right after the function call? i.e.
Code:

 if (phase == 0)
          doMainMenu();
          phase = 1;

Been coding too much Python lately? If you have more than one statement, you need to bracket your code like this:
Code:

if (phase == 0)
{
  doMainMenu();
  phase = 1;
}

If I were coding it, I'd use a switch statement:
Code:
switch(phase)
{
  case MAIN_MENU:
    phase = doMainMenu();
    break;
}

And then each function would return a constant representing what state to go to next.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#18584 - MumblyJoe - Mon Mar 29, 2004 6:11 am

Actually you have shown another great reason to use c++, classes with constructors and destructors that inherit from a base class with the functions needed would suit your need perfectly as i see it.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#18615 - dagamer34 - Mon Mar 29, 2004 11:05 pm

You would change the phase variable inside one of the functions (or in this case, mini-games) to change the game state.

Like have 1 represent the menu, 2 the first mini-game, 3 the second mini-game, etc.. and have a number for loosing and stuff like that.
_________________
Little kids and Playstation 2's don't mix. :(

#18629 - SmileyDude - Tue Mar 30, 2004 5:52 am

MumblyJoe wrote:
Actually you have shown another great reason to use c++, classes with constructors and destructors that inherit from a base class with the functions needed would suit your need perfectly as i see it.


That, and virtual functions -- instead of using a switch statement for a FSM, it's easier to do something like this in your while loop:

Code:
currentState.update();


Of course, I'm sure that there are plenty of people here that will scream bloody murder about using virtual functions, but for something like this, it's a perfect application.... and probably faster too.
_________________
dennis

#18653 - torne - Tue Mar 30, 2004 11:28 pm

A switch that gets compiled to a jump table is going to be in the same ballpark as a virtual function dispatch. A switch that's compiled to sequential if-else's will probably be slower than virtual dispatch.

The only way you'll get it faster than a virtual function is to use a function pointer, and that's not going to gain much. If you're comfortable with OO programming, use it.

#18980 - SmileyDude - Fri Apr 09, 2004 3:28 am

At a talk during the GDC (C++ performance), the performance guy from Microsoft said that they haven't seen any cases where virtual functions are a bottleneck in the games they have tested. The overhead just isn't that much.
_________________
dennis

#18986 - NoMis - Fri Apr 09, 2004 7:08 am

yeah if you have a 3 ghz machine. But what about the gba, wich is significantly slower than this. I use C++ too and i use some virtual functions but you need to know where to use them. e.g. if you call a virtual function within an inner loop wich may run, say 500 times every frame it will slow everything down because you have to lookup 500 times. but if it happens once a frame its not that big problem. But you can still use compile time polimorphismus in such cases (see http://www.gamedev.net/reference/articles/article2015.asp ).

NoMis

#19008 - torne - Fri Apr 09, 2004 10:18 pm

NoMis: the 500-times-per-frame case is the only time when you really need to avoid virtual dispatch. The rest of the time, the extra memory access is not likely to be significant. Optimising prematurely introduces more bugs and design problems; dont't worry about these things until the code works and has proven to be too slow (profiling is your friend).

#19146 - SmileyDude - Mon Apr 12, 2004 12:05 am

NoMis wrote:
yeah if you have a 3 ghz machine. But what about the gba, wich is significantly slower than this.


heh -- last I checked, the XBox is 700mhz, but that's not the point anyway.

If you are already using function pointers in a struct, you are most of the way to using polymorphism anyway. Doesn't make too much sense to trade away readability/maintability too early in the process because you might need that extra couple of cyles.

The best thing to do in any case, though, is to benchmark your code. Find out if virtual functions really are slowing your code down. Maybe you might find that there is another area of your code that you could optimise that will get you much better results.
_________________
dennis