C Board  

Go Back   C Board > Community Boards > Article Discussions

Reply
 
LinkBack Thread Tools Display Modes
Old 02-08-2005, 11:43 AM   #1
Lead Moderator
 
kermi3's Avatar
 
Join Date: Aug 1998
Posts: 2,568
Module Development for Game Design - By Jeff Verkoeyen

Article Number Two:

http://www.cprogramming.com/tutorial/gamedesign.html
__________________
Kermi3

If you're new to the boards, welcome and reading this will help you get started.
Information on code tags may be found here

- Sandlot is the highest form of sport.
kermi3 is offline   Reply With Quote
Old 02-08-2005, 11:59 AM   #2
and the hat of marbles
 
Sang-drax's Avatar
 
Join Date: May 2002
Location: Göteborg, Sweden
Posts: 2,038
Objects in a game are also very good to represent with abstract base classes.

Code:
class Object
{
public:

  Object();

  virtual void process() = 0;

  bool isAlive();

  int getPriority();
private:
  int priority;
  bool alive();
};

//Other abstract subclasses
class GraphicObject;
class ConcreteObject;
Then the game loop can process every object in the game using a container:

Code:
std::list<Object*> objectList= ...

while (true)
{
  sort(objectList);  //Sort by priority
  for each (object <- objectList)
  {
     obj->process();
     if (!obj->isAlive)
       objectList.remove(obj);
  }
}
New types of enemies, weapons etc. can be added to the game without recompiling the game loop or almost anything else.
__________________
Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling
Sang-drax is offline   Reply With Quote
Old 02-09-2005, 12:03 AM   #3
vae victus!
 
skorman00's Avatar
 
Join Date: Nov 2003
Posts: 594
The modular Game class is a great method to use in any project, especially a party game consisting of several mini games.

As with game entities as Sang-drax indicated, it is sometimes useful to create an abstraction layer on aspects of game logic, rendering, or any other component using similar methods. This is most beneficial when their is a high risk of problems with the chosen technology being used.

These are common practices in other software industries, but, unfortunately, still foriegn to several game developers.
skorman00 is offline   Reply With Quote
Old 02-09-2005, 11:36 AM   #4
Carnivore ('-'v)
 
Hunter2's Avatar
 
Join Date: May 2002
Posts: 2,865
That's a neat and efficient system to use. However, how could this be applied to making menus (an important module to include in any game)? What if you wish for your game to remain running in the background while you access a menu, i.e. you don't want it to shut down every time you go to the menu screen? The system works fine if you simply want the game to change states, but it seems to me that having overlapping states might require a more complex mechanism - perhaps a module loop discretely nested in the main game module's Execute() function. Even then though, it would probably pause/stall the game while accessing the menu. Does anyone have better suggestions? (Or is multithreading always the answer to every question in life?)
__________________
Just Google It. √

(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Last edited by Hunter2; 02-09-2005 at 11:39 AM.
Hunter2 is offline   Reply With Quote
Old 02-09-2005, 05:56 PM   #5
vae victus!
 
skorman00's Avatar
 
Join Date: Nov 2003
Posts: 594
Code:
Module* oldMod=gamemod;
if((gamemod=gamemod->ExecuteModule())!=oldMod)
{
    lastMod=oldMod;
    lastMod->Shutdown();
    gamemod->Initialize();
}
He pointed out that this bit of code can be modified to fit needs. Directly before, or after this check, you can add a loop to control the menus, and exchange information to the game module through several methods. Personally, I think a singleton model would work well in such a situation.
skorman00 is offline   Reply With Quote
Old 02-10-2005, 12:20 AM   #6
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
Ahhhhhhhhhhhhhhh!!!

Virtuals. I avoid them like the plague in game programming. Don't use virtual functions.
Bubba is offline   Reply With Quote
Old 02-10-2005, 02:27 AM   #7
Cat without Hat
 
CornedBee's Avatar
 
Join Date: Apr 2003
Posts: 8,439
You can overdo anything, and avoiding virtuals in one of these things. What alternative approach do you suggest? Virtual calls are faster than switches, unless they're implemented as jump maps - which is far less extensible.
__________________
All the buzzt!
CornedBee

"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
CornedBee is offline   Reply With Quote
Old 02-10-2005, 10:10 AM   #8
Carnivore ('-'v)
 
Hunter2's Avatar
 
Join Date: May 2002
Posts: 2,865
>>Virtuals. I avoid them like the plague in game programming. Don't use virtual functions.
May I ask why? It's not like loading/unloading modules is a time-critical operation running in a tight loop anyway. The time spent in actual initialization and destruction will almost certainly overshadow virtual call overhead by such a degree that it becomes neglible.
__________________
Just Google It. √

(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
Hunter2 is offline   Reply With Quote
Old 02-11-2005, 05:31 AM   #9
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
Virtuals can result in a lot of function call overhead and often times they are misused to the point that this side effect begins to affect the performance of the game. It's probably not critical in applications but it is inside of a main game loop.

I was going to implement a renderer using virtual functions because it seemed the place to do so. However after reading several books and articles on the topic I decided against it. Instead the rendering is done inside of one main render function. The render function used to call the virtual render function of the class. The problem is that this resulted in a lot of function call overhead inside of a very time critical loop which was quite noticeable. Not only did I have to remove the virtuals but I also had to be careful about how/if I copied structures when rendering objects. What I eventually came up with was this:
  • Since Direct3D is essentially a state machine there are only so many 'useful' render states. These can be preserved using mechanisms provided in Direct3D called state blocks or you can implement them on your own.
  • The renderer should draw all objects from one vertex buffer
  • The renderer should call SetTexture() only as many times as is needed and no more.
  • The renderer should call SetTransform() only as many times as is needed and no more.
  • The renderer should NOT call out to any other code to render objects.
  • The renderer should render similar objects in batches.
  • The renderer should NOT check the current state block.
  • The renderer should NOT have to check any conditionals in order to properly render batches
  • Switching batches and states should be a simple matter of incrementing an integer which acts as an index

What this amounts to (so far) is this:

Prior to rendering
  • Cull objects based on frustrum and add vertices to master list if object passes test - add vertices depending on z order and/or priority of object (alpha blended objects must be rendered in correct order or they wont look right)
  • Add object state information to master object state vector
  • Add object transform to world transformation stack
  • Set the vertex buffer up so that vertices that use the same texture are sequentially arranged inside of the buffer
    ...
    ...

Rendering
  • Retrieve and setup block state from vector of states to be rendered
  • Retrieve index range information for this batch of primitives from object state vector
  • Retrieve primitive type for this batch from object state vector
  • Retrieve texture for this batch from object state vector and call SetTexture()
  • Retrieve world/view transform from matrix stack
  • (Optional)Retrieve vertex shader ptr from effect file for this batch from object state vector
  • (Optional)Retrieve reflection flags (if any) from object state vector
  • Set all shaders/states based on object state and shader info
  • Render the batch
  • Increment batch number counter
  • Repeat process until all batches have been rendered

What I'm trying to do is sequentially render everything. This amounts to simply incrementing a vector or an integer that indexes into mutliple vectors. As long as everything is lined up correctly in the vectors it should work. Same principle as when rendering bitmaps. You want to linearily traverse the array instead of doing a multiply to find every pixel in the bitmap.

Fact is this. If you call a virtual render function each time and that render function sets up all the states for an object, then if you have 600 objects on screen you will be rendering each object one at a time and setting the state 600 times, setting the texture 600 times (even if some share the same texture), setting the world/view 600 times, etc, etc.

So perhaps this isn't just a matter of not using virtuals..it's a matter of once you enter the main render loop...don't leave it until you are done with the scene. It's not easy to set it up this way but Direct3D works a lot better with one huge batch of primitives than with several hundred small batches of primitives. Virtuals already lend themselves to some call overhead and as you see I'm trying to eliminate almost all of the calling overhead. Calls to SetTransform() and SetTexture() cannot be avoided but a good engine will only call them when absolutely necessary. I left some of the list blank because there are certain things I'm still trying to hammer out with this structure.

That's the method behind my madness and my reason for not using virtuals. And no, I haven't figured out how to get all of this to click yet but I will. I'm having a lot of problems with the world/view transformation - no object will occupy the same space at the same time. So you must always change the translation. But if you use a matrix stack you can effectively do the multiply for the object, pop the stack, and get back to the original matrix. This prevents you from having to compute the inverse to get back to the original matrix.

Stack on entry to Render:

..Base World/View Matrix ( World is identity)


Stack on first batch:

..Transformation/scaling matrix for batch of objects
..Base World/View matrix

So you see that even if you have a complex model with elbows and joints you only have to track how many times you pushed a new matrix onto the stack. Pop off that many and you are automatically back at the original matrix which would transform an object to 0,0,0 in world space. There are other ways to do this as well.

Last edited by Bubba; 02-11-2005 at 05:42 AM.
Bubba is offline   Reply With Quote
Old 02-11-2005, 09:20 AM   #10
and the hat of marbles
 
Sang-drax's Avatar
 
Join Date: May 2002
Location: Göteborg, Sweden
Posts: 2,038
Well, it's not exatly the virtual function call itself which kills the performance then. It's more drawing 600 objects at once versus drawing them one at a time.

And if you use virtual functions like Jeff Verkoeyen suggested in the article, you won't be able to notice any performance difference.
__________________
Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling
Sang-drax is offline   Reply With Quote
Old 02-12-2005, 12:54 AM   #11
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
It's a matter of executing function calls inside of a render loop.
Bubba is offline   Reply With Quote
Old 02-12-2005, 10:58 AM   #12
Carnivore ('-'v)
 
Hunter2's Avatar
 
Join Date: May 2002
Posts: 2,865
If I'm not mistaken, it isn't inside a render loop - it's a mechanism by which you can switch between game modes (i.e. main menu, playing game, high scores, whatever). The render loop would be placed inside the overloaded virtual Execute() function of one module, not vice versa.
__________________
Just Google It. √

(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
Hunter2 is offline   Reply With Quote
Old 02-12-2005, 11:23 AM   #13
Cat without Hat
 
CornedBee's Avatar
 
Join Date: Apr 2003
Posts: 8,439
BTW, bubba, each call into DirectX is a virtual function call...
__________________
All the buzzt!
CornedBee

"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
CornedBee is offline   Reply With Quote
Old 02-12-2005, 11:25 AM   #14
Software Developer
 
jverkoey's Avatar
 
Join Date: Feb 2003
Location: University of Waterloo
Posts: 1,916
It's completely up to the coder where/how to implement that code. I use it inside of a render function that only gets called once per frame. I personally have not noticed any large performance hit on any of my games by using this system and have found that the amount of code readability/reusability is increased tremendously.

However, if you are truly worried about speed, you could just have it so each module has its own render loop and returns from that loop when it's finished. I personally would find this to be more of a hassle than anything....but whatever floats your boat.
jverkoey is offline   Reply With Quote
Old 02-12-2005, 03:02 PM   #15
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
Quote:
BTW, bubba, each call into DirectX is a virtual function call...
I was not under the impression that COM was using virtual function calls since COM is a binary standard and not true C++.
Even though everything is derived from IUnknown it is not the same as a C++ class.
Please expand on this.
Bubba is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Find Injected DLLs In A Process? pobri19 Windows Programming 33 02-07-2009 04:37 AM
Function basics sjleonard C++ Programming 15 11-21-2001 12:02 PM


All times are GMT -6. The time now is 04:46 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22