Sort of long question about game loop

Started by
9 comments, last by Zahlman 17 years, 2 months ago
I'm trying to come up with the game loop for a 3d RPG game and this is what I have (in pseudocode):

win main()
{
   make window()
   make other stuff()

   current time = time
   frame time = 0.05 ms

   while quitting = false
   {
      if time => current time + frame time
      {
         current time = time

         switch game mode
         {
         case main menu:
            keyboard map = starting menu
            update menu()
         case load game menu:
            keyboard map = starting menu
            update load game menu()
         case game:
            switch game submode
            {
            case loading:
               render a single frame that will last until loading is done("Loading")
               if resources
                  delete resources()
               if scene
                  destroy scene()
                  delete scene()
               load resources()
               load scene()
               make scene()
               game mode = normal
            case normal:
               keyboard map = normal
               update scene and scene objects()
               update simple animations()
               update enemy animation()
               update enemy physics
               update npc animation()
               update npc physics()
               update player animation()
               update player physics
               update camera()
               update HUD()

               add scene and scene objects to render list()
               add enemies to render list()
               add npc to render list()
               add player to render list()
               add HUD to render list()
            case reading sign or talking:
               keyboard map = talking or reading
               update simple animations()
               update camera()

               add scene and scene objects to render list()
               add enemies to render list()
               add npc to render list()
               add player to render list()
               add text display to render list()
            case paused:
               keyboard map = pause menu
               update menu()

               add scene and scene objects to render list()
               add enemies to render list()
               add npc to render list()
               add player to render list()
               add menu to render list()
            case cutscene:
               keyboard map = none
               update cutscene()
               update scene objects()
               update simple animations()
               update enemy animation()
               update enemy physics
               update npc animation()
               update npc physics()
               update player animation()
               update player physics
               update camera()

               add scene and scene objects to render list()
               add enemies to render list()
               add npc to render list()
               add player to render list()
               add other cutscene stuff to render list()
            }
         }
      if game submode != loading
      render everything 3d()
      render everything 2d()
      }
   }
   delete stuff()
}
Anyways, I had one or two questions (only one of which I can think of right now): Say I have different amounts of enemies in each scene... how do I loop through them all without typing enemy1.update(); enemy2.update(); for each one? They are not going to necessarily be called something similar, some might be called "rock_monster" or "wolf"... Basically, how can I make it so that this loop goes through all classes derived from a base "enemy" class and executes the update() function for all of them? Thanks. EDIT: Just remembered second question... how would you go about adding a "list" of things to render? I don't want each object to render after it is updated because I wouldn't have much control over it. For example, I couldn't do depth sorting for transparency. [Edited by - Gumgo on January 30, 2007 9:53:00 PM]
Advertisement
Exactly what you described is what you should do.
I did not look at the pseudo code because I am in a hurry now , but you kind of answered your own question.

You will create a dat structure ( vector probably ) of your base enemy class , call it however you want , and store them all inside as dervied classes.By running an iterator of the vector and calling the update function each time , it calls the correct function each time.
This , I think ( I am still a student of Informatics and no expert ) , is what is called polymorphism.
I think that you should think about the switch you use for your gamemodes. It will be HUGE and even bigger when you need to add another mode.

My suggestion is that you create a class for each mode that inherits from a common base class.

GameMode  |  +- MainMenu  |  +- Game  |  etc


Then in your gameloop you run currentMode.update() and currentMode.draw() or what ever you think you need.

When it is time to switch mode you simply change the class in currentMode.

This is just a quick description and you you got any questions just fire away.
Quote:Original post by Gumgo
Say I have different amounts of enemies in each scene... how do I loop through them all without typing enemy1.update(); enemy2.update(); for each one? They are not going to necessarily be called something similar, some might be called "rock_monster" or "wolf"... Basically, how can I make it so that this loop goes through all classes derived from a base "enemy" class and executes the update() function for all of them? Thanks.

Rather than having "enemy1.update(); enemy2.update();" in the main loop, you make a function named UpdateEnemies() and call that from the main loop. UpdateEnemies() looks like this:
    for ( int i = 0; i < nEnemies; ++i )    {        enemies.update();    }    ... 
You might want more than just simple functions to manage enemies, so you might have a class called EnemyManager that creates, destroys, and maintains the enemies, and you would call enemyManager.Update() from the main loop.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
I'd create an abstract base-class, provide a virtual Update() function and fill it in in each derived class. You can store pointers to these objects in a vector, and call their Update() function regardless of the exact class type. Which function needs to be called will be resolved at run-time, so you don't need to worry about that yourself. Just be sure to make the base-class destructor virtual as well. ;)
Creating a manager class to wrap this update process and additional management is a good idea, especially when you game gets larger over time. I find that it allows you to manage code more easily.

Wc-duck has a good point bytheway. His proposed method is usually called 'state pattern'.
Create-ivity - a game development blog Mouseover for more information.
Thanks for all the replies! I have a few questions for each...

Captain P: Good idea. I had something of the sort in mind (having a base "enemy" class with data like X, Y, Z, rotation, etc) but you explained it in more detail. One thing I don't understand is this "storing pointers in vectors". I always thought a vector was a 3d representation of direction and distance... but obviously it means something else as well.

JohnBolton: I like the idea of using arrays but I'm confused about one thing... as far as I know, you can't change the size of an array. So during level loading, I'd have to create a new array with the amount of enemies in the level. The problem is, say I wanted to add more enemies when the player did something... or delete them when they were killed? Wouldn't that require me to increase/decrease the array size? Also, thanks for the tip about the EnemyManager class. I'll definately use something along those lines (as well as an NPCManager, etc.)

Wc-duck: I can understand why to make a class for each game mode, but I don't understand why I'd them inherited. All they'd really have is an update() function (and maybe another small function specific to the game mode), right? And each game mode requires a completely different update().

EDIT: I'm thinking something along the lines of this and this.

[Edited by - Gumgo on January 30, 2007 11:13:05 PM]
A vector is a dynamic array, or container.
Quote:Original post by Gumgo
I like the idea of using arrays but I'm confused about one thing... as far as I know, you can't change the size of an array.
That's where the vectors that were mentioned come into play. There are other similar containers available in the C++ Standard Library with different specific strengths and weaknesses (and you should at some stage invest some time into learning what's available) but to start with have a look at std::vector, which will probably meet your current needs.

- Jason Astle-Adams

Quote:Original post by Gumgo
Wc-duck: I can understand why to make a class for each game mode, but I don't understand why I'd them inherited. All they'd really have is an update() function (and maybe another small function specific to the game mode), right? And each game mode requires a completely different update().


The big thing with using the state pattern (thanks Captain P for giving me the name ;) ) is that your will be very small and neat and it will stay that way even if you add new states.

an example:

BaseMode* currentMode = new MainMenu();while(gameShouldRun){  currentMode->update();  currentMode->render();  if(changeMode)    currentMode = new UberGameMode();}


The code above is not at all good code but it gets the point across I hope. For example the changeMode-part maybe shouldn't be directly in the loop.
Well, a vector is simply a 1D list. It's so commonly used in 3D situations that we often read (x, y, z) when we see the word vector, but it can be of any size. What I actually meant here is the std::vector template class. Which is a dynamic array. Which is pretty usefull. :)
Create-ivity - a game development blog Mouseover for more information.

This topic is closed to new replies.

Advertisement