Data structures for a UFO2 style game
Hi everyone - I am making a game (in C++) which contains classes like Base, Building, Inventory, etc. I need my inventory (and building) classes to do different stuff depending on what sort of building/inventory it is.
i.e. when the init() function of a building is called (when building is complete and is to be added to base), an Anti-Aircraft building should add 100 to the baseDefense, but a storage facility should add 150 to the availableSpace.
I have come up with 3 different ways of implementing this, and I wanted some input on which way is faster/simpler/more robust:
1) pointer to a function - have a list of pre-defined functions that do the different things, have the init function point to whichever one is applicable.
2) have a whole lot of derived classes for each type of inventory/building. i.e. public Anti-Aircraft : public Building
3) have a DWORD of flags which correspond to which function should be called. THen at init() check the flags and call appropriate functions
4) something else i haven''t thought of
Thanks everyone, any ideas appreciated! i''m leaning towards (2) but i think this might make the binary too large.
Well, (2) is one of the biggest benefits there are to using C++. By making the function virtual, the compiler will actually do (1) for you, you don''t have to worry about it.
I strongly disagree with #2. Deriving every single building type is something that is instinctive for people learning C++, because that's how so many C++ books teach OOP (except they use shapes and vehicles and stuff), but it's not the way to go imho. You'll notice a lot of commerical games are very modable, meaning they aren't doing this deriving stuff. Also, doing it the deriving way is going to result in lots of code, difficulty in expanding later, and will require recompiling whenver you want to change an aspect of gameplay.
I personally go by the theory that games (as well as other applications, but that's another topic) should truly separate the engine and the game. You should hard code stuff like physics, level management, graphics/sound/input management, etc, but no aspect of the gameplay should be in your source code. This includes everything from gravitational "constants" to many AI routines. It seems daunting, and you are NOT going to be able to accomplish all this on your first try. Practice goes a long way though, and if you are looking into game coding as a career, it will be a skill that won't be wasted.
For buildings, what you could try doing is making a Building class, and have it load a different data file depending on what type of building it is supposed to be. The data file could define the basic building statistics (health, defense, graphics (or actually a position in seprate graphics file where graphic for this building is located), etc). You also need the data file to define how the building affects your city, and this is possible through many many ways, and which one you pick is entirely dependent on the complexity of your game, your coding skill, time your willing to invest into this, etc. Here's two ideas:
1) If the ways that buildings can affect your city are limited, then you can have integer values for everything that the building can do. For example, you could have values for how much food the buildings adds, how many defense points, how much avialbe space it adds, etc). Then for example, for a storage facility, you could set all those values to 0 except for AvailableSpace, which could be like 150 (using your example here). This would be a fairly flexible system, and allow you to create things like base defences that also produce food. Limitations are that if you need a large and diverse amount of things that buildings can do, then you might have problems. This is probably the way you might wanna try first, since it's pretty easy to understand and impliment.
2) If you want to do crazier stuff, and really open up the gameplay to the creative mind, then you could impliment a rough scripting language. It doesn't have to be anything super fancy, in fact it could just be a recipe of stuff for the building to do, without structures like IF, FOR, etc. This is more flexible, since you could have the building morph, create units automatically based on city needs, pop turrets out when enemies approach, and all sorts of things that you would have to hard code with solution #1 and then just indicate that the building is allowed to do this. Basically, with solution 1, what buildings can and cant do is already clearly defined. With solution #2, you can get a lot more flexible. It's also a bigger project, especially with all the ways that scripting can be implimented.
That's just two solutions, there's plenty more. Just try to create a design where the game engine doesnt know anything other than that it is running a "Real Time Strategy game" or "Flight Simulator". Your .exe doesn't have to know that specifics like aircraft carriers or barns exist.
[edited by - LordElectro on May 3, 2002 2:44:48 PM]
I personally go by the theory that games (as well as other applications, but that's another topic) should truly separate the engine and the game. You should hard code stuff like physics, level management, graphics/sound/input management, etc, but no aspect of the gameplay should be in your source code. This includes everything from gravitational "constants" to many AI routines. It seems daunting, and you are NOT going to be able to accomplish all this on your first try. Practice goes a long way though, and if you are looking into game coding as a career, it will be a skill that won't be wasted.
For buildings, what you could try doing is making a Building class, and have it load a different data file depending on what type of building it is supposed to be. The data file could define the basic building statistics (health, defense, graphics (or actually a position in seprate graphics file where graphic for this building is located), etc). You also need the data file to define how the building affects your city, and this is possible through many many ways, and which one you pick is entirely dependent on the complexity of your game, your coding skill, time your willing to invest into this, etc. Here's two ideas:
1) If the ways that buildings can affect your city are limited, then you can have integer values for everything that the building can do. For example, you could have values for how much food the buildings adds, how many defense points, how much avialbe space it adds, etc). Then for example, for a storage facility, you could set all those values to 0 except for AvailableSpace, which could be like 150 (using your example here). This would be a fairly flexible system, and allow you to create things like base defences that also produce food. Limitations are that if you need a large and diverse amount of things that buildings can do, then you might have problems. This is probably the way you might wanna try first, since it's pretty easy to understand and impliment.
2) If you want to do crazier stuff, and really open up the gameplay to the creative mind, then you could impliment a rough scripting language. It doesn't have to be anything super fancy, in fact it could just be a recipe of stuff for the building to do, without structures like IF, FOR, etc. This is more flexible, since you could have the building morph, create units automatically based on city needs, pop turrets out when enemies approach, and all sorts of things that you would have to hard code with solution #1 and then just indicate that the building is allowed to do this. Basically, with solution 1, what buildings can and cant do is already clearly defined. With solution #2, you can get a lot more flexible. It's also a bigger project, especially with all the ways that scripting can be implimented.
That's just two solutions, there's plenty more. Just try to create a design where the game engine doesnt know anything other than that it is running a "Real Time Strategy game" or "Flight Simulator". Your .exe doesn't have to know that specifics like aircraft carriers or barns exist.
[edited by - LordElectro on May 3, 2002 2:44:48 PM]
I really prefer the #2.
I put an little example pseudo-code using STL:
I think it''s very easy, just need to understand some C++ feature, but not something complicated. Inheritance and Polymorfism are very powerfull.
_______________
Jester, studient programmer
The Jester Home in French
I put an little example pseudo-code using STL:
class Building{public: virtual void Init( Base* base )=0;};class AntiAircraft: public Building{public: virtual void Init( Base* base ) { base.mBaseDefense += 100; }};class Inventory: public Building{public: virtual void Init( Base* base ) { base.mAvailableSpace+= 150; }};class Base{public: void AddBuilding( Building* building) { mBuildingList.push_back( building ); building.Init(this); } int mBaseDefense; int mAvailableSpace;private: vector mBuildingList;};
I think it''s very easy, just need to understand some C++ feature, but not something complicated. Inheritance and Polymorfism are very powerfull.
_______________
Jester, studient programmer
The Jester Home in French
LordElectro, your suggestions address one of my biggest concerns - keeping the game as "expandable" as possible ... (the game being a relatively long-term project).
i''ve been thinking about the first idea (data file/integer values), as it does seem very easy. I''m just worried about excessive memory usage. each building will be malloc''d - i anticipate around 20 buildings per base, and 30/40 bases per player at the endgame. If I have each building containing stuff relevant to every building... i.e. an AA building with storage-facilility info set to zero, then it seems a huge waste of space.
i''m not sure, but i think scripting will also suffer from this problem
mind you, system memory is pretty cheap - and design IS sometimes about playing off mutually exclusive ideals
i''ve been thinking about the first idea (data file/integer values), as it does seem very easy. I''m just worried about excessive memory usage. each building will be malloc''d - i anticipate around 20 buildings per base, and 30/40 bases per player at the endgame. If I have each building containing stuff relevant to every building... i.e. an AA building with storage-facilility info set to zero, then it seems a huge waste of space.
i''m not sure, but i think scripting will also suffer from this problem
mind you, system memory is pretty cheap - and design IS sometimes about playing off mutually exclusive ideals
Keeping a clear head about memory usuage is something that I personally have lots of problems with too, especially since I first began programming in DOS, where 640KB (512KB actually, before you start having to make boot disks and things to make sure enough memory is available) had to fit graphics, sounds, and game data. On a Windows system, you easily have 32MB* to play with before you need to start worrying about dynamically loading media and paying lots of attention to memory management.**
Let's say each building needs to store 25 integer values (4 bytes, and yes, you could make them 1 byte each or whatever, but for argument's sake, let's pretend you need values that can hit 4 billion). These values are stuff like health, defense added, vision, etc. In addition, the building can have certain true/false attribute, such as "Resource Depot" (allowing resources to be deposited, "Spyvision" (allowing it to sense cloaked units, and anything else that can be amply defined with a simple true/false. For these attributes, you only need a bit to store the information, so you can create a Flags integer. I'm assuming you know how to flip individual bits. So each building now takes up 25 * 4 + 1 * 4 bytes of memory, which works out to 104 bytes.
Let's create 100 bases, each with 100 buildings. Each base will take up 10 400 bytes of memory, or *approximately* 10KB. 100 such bases will take up 1 040 000 bytes of memory, which isn't even a megabyte. Furthermore, the scenario I presented here uses 5 times your expected buildings per base, and twice the expected bases, creating an absolute worst case scenario. As well, it is doubtful you will be able to find 25 attributes for a building, so you can expect this method to use closer to 50-100KB of memory.
Now, I have explained all of the above, using the assumption that you are going to load all those attributes into each instance of the building. This will work, however, what you should be doing is loading all this stuff into a separate array of building types, and then having each instance of an actual building point towards it's type, and data can be retrieved from there. The only attributes that you actually need to load for a building are those that would change between each individual building (such as health). Suddenly, each building only needs around 12 bytes to store it (pointer to its type, and a couple building specific attributes). That's almost 10 times less memory being used per building, and the amount of memory your building type array will take up is insigificant, unless you introduce like 100 000 different building types.
I hope all that made sense, I am in a rush and don't have time to proofread.
* 32MB is the magic rule of thumb number I happen to use, for a variety of reasons. Your mileage may vary.
** This is not meant to imply that you don't have to care how much memory you are using when writing small programs. You should never adopt a careless attitude towards memory, or you will also find yourself not paying attention to where it is being allocated/deallocated, and will end up with a leaky nasty game or worst, application (*cough* ICQ *cough*). You just don't have to go overboard and try to save memory where it doesn't need saving.
[edited by - LordElectro on May 5, 2002 1:43:38 PM]
[edited by - LordElectro on May 5, 2002 1:44:38 PM]
Let's say each building needs to store 25 integer values (4 bytes, and yes, you could make them 1 byte each or whatever, but for argument's sake, let's pretend you need values that can hit 4 billion). These values are stuff like health, defense added, vision, etc. In addition, the building can have certain true/false attribute, such as "Resource Depot" (allowing resources to be deposited, "Spyvision" (allowing it to sense cloaked units, and anything else that can be amply defined with a simple true/false. For these attributes, you only need a bit to store the information, so you can create a Flags integer. I'm assuming you know how to flip individual bits. So each building now takes up 25 * 4 + 1 * 4 bytes of memory, which works out to 104 bytes.
Let's create 100 bases, each with 100 buildings. Each base will take up 10 400 bytes of memory, or *approximately* 10KB. 100 such bases will take up 1 040 000 bytes of memory, which isn't even a megabyte. Furthermore, the scenario I presented here uses 5 times your expected buildings per base, and twice the expected bases, creating an absolute worst case scenario. As well, it is doubtful you will be able to find 25 attributes for a building, so you can expect this method to use closer to 50-100KB of memory.
Now, I have explained all of the above, using the assumption that you are going to load all those attributes into each instance of the building. This will work, however, what you should be doing is loading all this stuff into a separate array of building types, and then having each instance of an actual building point towards it's type, and data can be retrieved from there. The only attributes that you actually need to load for a building are those that would change between each individual building (such as health). Suddenly, each building only needs around 12 bytes to store it (pointer to its type, and a couple building specific attributes). That's almost 10 times less memory being used per building, and the amount of memory your building type array will take up is insigificant, unless you introduce like 100 000 different building types.
I hope all that made sense, I am in a rush and don't have time to proofread.
* 32MB is the magic rule of thumb number I happen to use, for a variety of reasons. Your mileage may vary.
** This is not meant to imply that you don't have to care how much memory you are using when writing small programs. You should never adopt a careless attitude towards memory, or you will also find yourself not paying attention to where it is being allocated/deallocated, and will end up with a leaky nasty game or worst, application (*cough* ICQ *cough*). You just don't have to go overboard and try to save memory where it doesn't need saving.
[edited by - LordElectro on May 5, 2002 1:43:38 PM]
[edited by - LordElectro on May 5, 2002 1:44:38 PM]
LordElectro, i guess you never looked at the hl sdk. highly oop oriented with a class heiarchy. the trick is to make a generalized version, then derive from that things that are more specilized. in this way you have very few functions to rewrite, and because standrad code is in one place, thigs are much easier to debug. plus because you can just inhieret from the proper class, modify the virtual function (including be able to call the parent functoin) you can easily expand the game. in fact, using dlls you can make class factories. the compiler only needs the defination of the classes so it can determine the order of virtual functions and space required for varibles. after that you can derive and override to your hearts content.
dxm, look at the hl sdk source. it will show you one way of doing it. look at the ut sdk (though you probably will need to purchase the game if you dont have it since most of the source is actually included with the game since its using a scripted langauge). you will see amazingly modable oop in action.
remeber, if you need to override too many functions, then its possible that you need to reevaluate your hierachy.
dxm, look at the hl sdk source. it will show you one way of doing it. look at the ut sdk (though you probably will need to purchase the game if you dont have it since most of the source is actually included with the game since its using a scripted langauge). you will see amazingly modable oop in action.
remeber, if you need to override too many functions, then its possible that you need to reevaluate your hierachy.
A Person: I use this approach all the time when creating GUIs and things, but for games, I find it really annoying having to recompile code to add gameplay things. It''s even more annoying to the user, because most people don''t have access to programming tools or for that matter, the knowledge required. You are correct though that I have never seen the HL SDK, so I can''t comment on specifics.
Mind you, both ways WILL work, and both have advantages and disadvantages.
Mind you, both ways WILL work, and both have advantages and disadvantages.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement