Dauntless-
The exapmles of virtual function/inheritance given so far have been great. I thought I would give a simple overview, as another perspective may help you if you were still a bit confused.
There are three types of functions you can place in your BASE classes, they are as follows:
Pure virtual/Abstract:
class myBase{
virtual void myFunc() = 0;
};
This function has NO implementation with in the base class. Your derived classes must implement the code for myFunc themselves.
Virtual:
class myBase{
virtual void myFunc();
};
This function has it's implementation within the base class. When you derive from it you CAN implement your own version of myFunc, but you don't have to.
Normal:
class myBase{
void myFunc();
};
This function also has it's implementation within the base class. But you CAN'T implement your own version in your derived class.
I hope this helps. How far along in your strategy game are you?? I would be interested to talk more just on how it is giong (perhaps out of this forum) as I am also putting together a couple of strategy games at the moment. In any case, good luck with it and I hope this helped.
Doolwind
[edited by - Doolwind on September 24, 2002 1:54:28 AM]
Unit design question
quote: Original post by Fuzztrek
i think the article said not to go more than 2 levels deep with inheritence. or osmething like that.
I don''t think it makes a difference. If you have an inheritance hierarchy, at any point you will be dealing with a concrete set of attributes and functionality (ie, if you have classes A->B->C->D->E where -> denotes base-to-derived inheritance, you will always be interacting with objects through one of these class interfaces). A vtable lookup is a vtable lookup.
quote: Original post by coderx75
I''ve had to use a lot of similar techniques discussed here. I have a CUnitDescriptor class that holds the static data for a unit. I also have a CEntity class that holds the dynamic data of the seperate entity. This class points to it''s descriptor.
I wouldn''t create two separate classes to define an entity unless the idea was that the two classes in conjunction could define several entities. Being data-driven, the classes could essentially be extensible by scripting languages, allowing non-programmer designers (perhaps through some nifty GUI tool) to create new class definitions and play with them immediately.
quote:
What if the units are in a private static array in the manager class and the manager class contained only methods and no non-static properties?
Could you clarify your use of static here? Do you mean static in a C++ connotation, or some other interpretation? If it''s the former, you might want to make this manager class a singleton object to ensure that that multiple non-synchronized managers aren''t updating and altering the static data concurrently.
quote:
The actual units could be derived from the manager class. The unit would only need a pointer to its own data in the static array which would be assigned in the constructor. The unit cannot see the data of other units (because it''s private) but the manager class can see that data so that it can set up interactions, such as collision.
You''re putting a lot of responsibility into the manager class. That''s okay if it''s to be handled through other, smaller manager classes sharing a pool of data. the concept of using managers with larger purview is a well-established one, but that purview is usually limited to one (or a few well-defined) sphere(s) of influence.
quote:
Am I making sense? And if so, does this sound like a solid plan?
So long as the design fulfills your needs, it''s viable.
quote: Original post by Oluseyi
I wouldn''t create two separate classes to define an entity unless the idea was that the two classes in conjunction could define several entities. Being data-driven, the classes could essentially be extensible by scripting languages, allowing non-programmer designers (perhaps through some nifty GUI tool) to create new class definitions and play with them immediately.
The descriptor class defines multiple units. A descriptor may define the maximum hit points for a unit type while the entity itself holds the current damage. My data is usually parsed from text files using a simple scripting language. Descriptor data will be taking from text files, while the entity/unit data is based on the descriptor.
quote: Could you clarify your use of static here? Do you mean static in a C++ connotation, or some other interpretation? If it''s the former, you might want to make this manager class a singleton object to ensure that that multiple non-synchronized managers aren''t updating and altering the static data concurrently.
I am declaring the array as static so that all instances of the manager class have access to the array. However, the array is also private so that units derived from the manager class do not have direct access to data for all units. The manager class only holds one non-static property, which is the pointer to it''s own data. This pointer is protected so that derived units have access to it but the outside world cannot directly read it.
quote: You''re putting a lot of responsibility into the manager class. That''s okay if it''s to be handled through other, smaller manager classes sharing a pool of data. the concept of using managers with larger purview is a well-established one, but that purview is usually limited to one (or a few well-defined) sphere(s) of influence.
The manager class (I''d rather think of this class as the "unit parent") only has a few simple responsibilities. First, its constructor must take the next available unit in the static array and assign its pointer. Methods are provided for setting and reading values in the unit. Simple methods allow for finding other units (and other game objects). Finally, the manager class provides a move () function that will attempt to move the unit. If a collision takes place, it returns a pointer to the unit it collided into. This is the only complex part of the class. Units are organized into a two dimensional array of linked lists to streamline collisions.
Here is a trimmed down example:
class CEntity:public CEntity {public: //methods for access to dataprivate: CUnitDescriptor *descriptor; //unit data};class CUnit:public CObject{public: CUnit (); //assigns a pointer to self CEntity * GetEntity (); //returns self short IsActive (); CUnit * Move (long dist);protected: CEntity * self; //reference to unit data within arrayprivate: static CEntity *entity; //array of units};class COrc:public CUnit //just a generic example =){ //All code specific to Orc units goes here. //Whatever data is required for this unit SHOULD be in the descriptor.}
- Jay
There''s an old saying in Tennessee... well, it''s in Texas but probably in Tennessee too. It say''s, "Fool me once, shame on... shame on you... uh... ya fooled meh uh can''t get fooled again."
- George W. Bush
Get Tranced!
Quit screwin' around! - Brock Samson
after reading coderx and oluseyi''s comments, I was wondering how exactly I''d go about creating a base unit template that the players can create units with. My problem is twofold.
First off, the actual units themselves will be modifiable. So you start out with generic units from which you can then build its attributes and capabilities. For example, for vehicles, you will have generic hull sizes, and from these hulls, you insert your equipment, such as engines, main armaments, sensor equipment, defenses, etc. Obviously, making players build all of their units from scratch would be very tiresome, so there will be pre-loaded and defined units (or in C++ terms, pre-defined objects built off of classes).
The second problem is that once the base units are defined and created, these are further put into container classes that I call Organized Units (OU''s). Think of a modern military''s company structure. It is comprimised (normally) of 4 platoons of infantry along with some support elements. However, since you can create different types of platoons, you can then tweak how your company is organized. This is a very important aspect of my game, because how you organize your forces is critical to it''s effectiveness. For example, perhaps you want to create a Marine Expeditionary Company and a Light Armored Cavalry company. With the MEC, you would create platoons mostly composed of rifle platoons, with little or no organic artillery support. You might include a specialist Force Recon team (special ops unit) in the company. With the LAC unit, you will want to "attach" some Infantry Fighting Vehicles and or scout vehicles with mechnazed infantry support that can carry heavier firepower. You may want to include a Forward Observation team with this kind of company.
All of this being said, when coderx mentioned that the data is just read from text files, and Oluseyi''s comments that you could create some scripting utilities, I wass trying to think of a way to make a class definition capable of being open ended enough to allow it to be modifiable.
I''m also going to have to do something about my commander class and how they will plug into the container class. The officer will be the one that intercepts communication tokens from the player and carry out his orders. The trick will be making sure that the officer has access to all the functions of all the base units that make up the container class he has been plugged into (I guess I''m going to need to make lots of pointers).
I see a couple problem domains I need to solve:
1) How do I make classes that are created at run time, but which the player can tweak once the game has begun (i.e. do like coderx and create a scripting engine that creates data in an external file, and the unit "reads" it''s capabilities from the text file?)
2)Solving problem 1, how do I make a scripting interface that allows non-programmers a way to generate the base unit and Organized Unit''s attributes (I think this part will be easy actually)
3) Insert commander objects into the container class (the class that defines the Organized Unit) and make sure that the officer object has access to ALL of the base units functions within that container class.
hoo boy....well, at least all of this thinking makes learning programming fun instead of tedious
First off, the actual units themselves will be modifiable. So you start out with generic units from which you can then build its attributes and capabilities. For example, for vehicles, you will have generic hull sizes, and from these hulls, you insert your equipment, such as engines, main armaments, sensor equipment, defenses, etc. Obviously, making players build all of their units from scratch would be very tiresome, so there will be pre-loaded and defined units (or in C++ terms, pre-defined objects built off of classes).
The second problem is that once the base units are defined and created, these are further put into container classes that I call Organized Units (OU''s). Think of a modern military''s company structure. It is comprimised (normally) of 4 platoons of infantry along with some support elements. However, since you can create different types of platoons, you can then tweak how your company is organized. This is a very important aspect of my game, because how you organize your forces is critical to it''s effectiveness. For example, perhaps you want to create a Marine Expeditionary Company and a Light Armored Cavalry company. With the MEC, you would create platoons mostly composed of rifle platoons, with little or no organic artillery support. You might include a specialist Force Recon team (special ops unit) in the company. With the LAC unit, you will want to "attach" some Infantry Fighting Vehicles and or scout vehicles with mechnazed infantry support that can carry heavier firepower. You may want to include a Forward Observation team with this kind of company.
All of this being said, when coderx mentioned that the data is just read from text files, and Oluseyi''s comments that you could create some scripting utilities, I wass trying to think of a way to make a class definition capable of being open ended enough to allow it to be modifiable.
I''m also going to have to do something about my commander class and how they will plug into the container class. The officer will be the one that intercepts communication tokens from the player and carry out his orders. The trick will be making sure that the officer has access to all the functions of all the base units that make up the container class he has been plugged into (I guess I''m going to need to make lots of pointers).
I see a couple problem domains I need to solve:
1) How do I make classes that are created at run time, but which the player can tweak once the game has begun (i.e. do like coderx and create a scripting engine that creates data in an external file, and the unit "reads" it''s capabilities from the text file?)
2)Solving problem 1, how do I make a scripting interface that allows non-programmers a way to generate the base unit and Organized Unit''s attributes (I think this part will be easy actually)
3) Insert commander objects into the container class (the class that defines the Organized Unit) and make sure that the officer object has access to ALL of the base units functions within that container class.
hoo boy....well, at least all of this thinking makes learning programming fun instead of tedious
The world has achieved brilliance without wisdom, power without conscience. Ours is a world of nuclear giants and ethical infants. We know more about war than we know about peace, more about killing than we know about living. We have grasped the mystery of the atom and rejected the Sermon on the Mount." - General Omar Bradley
Doolwind-
ahh, I didn''t know there was a difference between pure virtual and virtual methods. Although I''m not sure why you''d want to use a pure virtual method? What happens if your pointer points to the base class, and not the derived class? How would the function work?
As for my game, since I''m still learning programming, mostly it''s all theoretical, with lots of chicken scratch on notepad. I tend to think better with pen and pencil, and usually my ideas come to me while I''m at work. I have quite a bit of information on the background of the game world, but it''s mostly just the creative side. I''ve even been doodling again and drawing out some rough sketches of equipment, the units, things like that. But for technical stuff on my project, virtually nil. Right now, I''m really at the brainstorming levl, trying to think of a "rough draft" per se. If I knew anything about UML, I''d probably be trying to do that. Since my game will be a hybrid time system like Shogun, I haven''t even really put much thought into my event loop and game flow logic, although once I figure out how units, organized units, and officers all fit in, I''ll work on that next.
ahh, I didn''t know there was a difference between pure virtual and virtual methods. Although I''m not sure why you''d want to use a pure virtual method? What happens if your pointer points to the base class, and not the derived class? How would the function work?
As for my game, since I''m still learning programming, mostly it''s all theoretical, with lots of chicken scratch on notepad. I tend to think better with pen and pencil, and usually my ideas come to me while I''m at work. I have quite a bit of information on the background of the game world, but it''s mostly just the creative side. I''ve even been doodling again and drawing out some rough sketches of equipment, the units, things like that. But for technical stuff on my project, virtually nil. Right now, I''m really at the brainstorming levl, trying to think of a "rough draft" per se. If I knew anything about UML, I''d probably be trying to do that. Since my game will be a hybrid time system like Shogun, I haven''t even really put much thought into my event loop and game flow logic, although once I figure out how units, organized units, and officers all fit in, I''ll work on that next.
The world has achieved brilliance without wisdom, power without conscience. Ours is a world of nuclear giants and ethical infants. We know more about war than we know about peace, more about killing than we know about living. We have grasped the mystery of the atom and rejected the Sermon on the Mount." - General Omar Bradley
quote: Original post by Dauntless
Doolwind-
ahh, I didn''t know there was a difference between pure virtual and virtual methods. Although I''m not sure why you''d want to use a pure virtual method? What happens if your pointer points to the base class, and not the derived class? How would the function work?
It never happens. It is impossible to create an instance of a class with a pure virtual member (your compiler would complain) so it is impossible to have a pointer pointing to one.
quote: So you start out with generic units from which you can then build its attributes and capabilities. For example, for vehicles, you will have generic hull sizes, and from these hulls, you insert your equipment, such as engines, main armaments, sensor equipment, defenses, etc. Obviously, making players build all of their units from scratch would be very tiresome, so there will be pre-loaded and defined units
Bravor, sir! The only reason I can possibly think of to keep you from reaching this goal, is that I am certain it would occupy my time enough to interfere with my own progress! Luckily, I know that each and every game I play, especially the good ones (the ones with an original approach and groundbreaking new thoughts) is absorbed by my feeble mind. And ultimately, that''s what game design is all about: creating the game that you yourself would like to play eternally.
Just wanted to chime in my own thoughts on this simpler (read: non-programming) part in this thread. Love it. Lots of interesting possibilities.
You either believe that within your society more individuals are good than evil, and that by protecting the freedom of individuals within that society you will end up with a society that is as fair as possible, or you believe that within your society more individuals are evil than good, and that by limiting the freedom of individuals within that society you will end up with a society that is as fair as possible.
quote: Original post by Dauntless
I see a couple problem domains I need to solve:
1) How do I make classes that are created at run time, but which the player can tweak once the game has begun (i.e. do like coderx and create a scripting engine that creates data in an external file, and the unit "reads" it's capabilities from the text file?)
You don't want to get in over your head. The simplest approach is usually the best. What you are trying to do here is VERY similar to what I'm working on in my project.
To start off with, you are not changing your class during runtime, after all, that's impossible. If you have a tank unit, that should have a class of its own. The engine would be in its own class and your tank could contain a pointer to it.
To give you an idea of how this works, I'll use a units weight attribute as an example. The parent class could have a virtual GetWeight method that reads the weight value in the descriptor. The derived "tank" class contains a pointer to its components (engine, weapon, etc.) The tank class also has its own implementation of GetWeight that gets the total weight by first calling the parent class' GetWeight method and calling the GetWeight method for each of its components.
This is getting pretty complicated. Keep in mind that this isn't the last game you will ever create. Whenever you write something, you will ALWAYS find that you could have done it better. Write it however you see as being logical and learn from your mistakes.
quote: 2)Solving problem 1, how do I make a scripting interface that allows non-programmers a way to generate the base unit and Organized Unit's attributes (I think this part will be easy actually)
I'd stay away from any kind of scripting engine at this point. If you don't see the purpose of a scripting engine, you probably don't need one.
quote: 3) Insert commander objects into the container class (the class that defines the Organized Unit) and make sure that the officer object has access to ALL of the base units functions within that container class.
A simpler approach would be to put ALL units into one container class. They could be arranged into company/platoon by perhaps giving each unit a company ID number. If the unit has the same company ID as the commander, they will recieve his orders.
Another approach (and the one I'd prefer) would be to use a linked list. The commander would be at the top of the list and he would have a pointer to his first unit and that unit would have a pointer to the second and so on. It would save you the trouble of having to search through every unit for the correct ID.
Honestly, this seems like a pretty complex project for beginning OOP. I'd really suggest trying something simpler.
By the sounds of it, you're going to have quite a few units running around. How many units do you expect the game to simultaneously control? Is it a mission-based game?
- Jay
There's an old saying in Tennessee... well, it's in Texas but probably in Tennessee too. It say's, "Fool me once, shame on... shame on you... uh... ya fooled meh uh can't get fooled again."
- George W. Bush
Get Tranced!
[edited by - coderx75 on September 24, 2002 9:38:40 PM]
Quit screwin' around! - Brock Samson
Dauntless-
I have read quite a few of your posts over the past few weeks and I must say keep up the great work, your ideas have a fresh outlook on the tried and tested strategy game! But anyways, to the reason for the post...
I am going to try and guess at a simple solution to some of your problems. They may be completely off what you want. But here goes...
(Pure) Virutal Functions:
The best place to use these is for a "unit" class. Or perhaps a "humanUnit" and "vehiculeUnit" class. But we will call it "unit" class for now.
This class would look something like this:
class CUnit{
virtual void attack(CUnit attacking);
virtual void setHealth(int newHealth);
virtual void move(int x, int y);
...
private:
int fireRate;
int movementSpeed;
};
This class would never be instantiated (you would never call CUnit myUnit = new CUnit() as it is a base class. It''s functions are virtual so they can be implemented in the base class, but a derived class can also implement the fucntion in a different way if it wants. So then you may create "CTank" or "CAeroplane" which derives from CUnit.
What does this mean??
1. You can now simply have a vetor/array of "CUnit" and in it you can stick any class that derives from CUnit. So you can now have all of your tanks, aeroplanes and any other units all in one vector. You can see how powerful this becomes very quickly.
2. Lets say the "move" function is quite complex. For most units you can just use the base class implementation. But if for some reason you wanted to change it slightly you can, by implementing your own version of move in the derived class. (eg The CAeroplane class would probably need a completely differnet way of moving around).
This means now you can run through each element of the CUnit vector and call move on that element. This gives you lots of power as you can now have a tank and an aeroplane in the same vector (lets say you just selected both of them on the screen an the CUnit vector in this case is the "SelectedUnits" vector). Now you can tell all of the elements of this "SelectedUnits" vector to move to x, y and they will both do it. They will do it in completely differnet ways, but all you care about is you asked them to move. This has a bit of overhead when first creating the classes and fitting them together, but saves a lot of hassle later on as you don''t need to know what type of unit you are talking to, you just tell it to move and you know it will.
User defined units/platoons
I will make this one brief. Basically using the above style of having a base class (Unit) and derived classes (tank/infantry/aeroplane) you should be able to set up user defined units of platoons.
They would actually be looking at a graphical representation of your CUnit class. They could set the fire rate, movement speed etc and when they have finished "save" their unit. This would mean simply saving the properties of the class.
Anyways, this post has become quite large quickly. Tell me if this is on the right track, and I can ramble on some more.
Doolwind
I have read quite a few of your posts over the past few weeks and I must say keep up the great work, your ideas have a fresh outlook on the tried and tested strategy game! But anyways, to the reason for the post...
I am going to try and guess at a simple solution to some of your problems. They may be completely off what you want. But here goes...
(Pure) Virutal Functions:
The best place to use these is for a "unit" class. Or perhaps a "humanUnit" and "vehiculeUnit" class. But we will call it "unit" class for now.
This class would look something like this:
class CUnit{
virtual void attack(CUnit attacking);
virtual void setHealth(int newHealth);
virtual void move(int x, int y);
...
private:
int fireRate;
int movementSpeed;
};
This class would never be instantiated (you would never call CUnit myUnit = new CUnit() as it is a base class. It''s functions are virtual so they can be implemented in the base class, but a derived class can also implement the fucntion in a different way if it wants. So then you may create "CTank" or "CAeroplane" which derives from CUnit.
What does this mean??
1. You can now simply have a vetor/array of "CUnit" and in it you can stick any class that derives from CUnit. So you can now have all of your tanks, aeroplanes and any other units all in one vector. You can see how powerful this becomes very quickly.
2. Lets say the "move" function is quite complex. For most units you can just use the base class implementation. But if for some reason you wanted to change it slightly you can, by implementing your own version of move in the derived class. (eg The CAeroplane class would probably need a completely differnet way of moving around).
This means now you can run through each element of the CUnit vector and call move on that element. This gives you lots of power as you can now have a tank and an aeroplane in the same vector (lets say you just selected both of them on the screen an the CUnit vector in this case is the "SelectedUnits" vector). Now you can tell all of the elements of this "SelectedUnits" vector to move to x, y and they will both do it. They will do it in completely differnet ways, but all you care about is you asked them to move. This has a bit of overhead when first creating the classes and fitting them together, but saves a lot of hassle later on as you don''t need to know what type of unit you are talking to, you just tell it to move and you know it will.
User defined units/platoons
I will make this one brief. Basically using the above style of having a base class (Unit) and derived classes (tank/infantry/aeroplane) you should be able to set up user defined units of platoons.
They would actually be looking at a graphical representation of your CUnit class. They could set the fire rate, movement speed etc and when they have finished "save" their unit. This would mean simply saving the properties of the class.
Anyways, this post has become quite large quickly. Tell me if this is on the right track, and I can ramble on some more.
Doolwind
Personally, I''d use a tree. In other words, you''re the commander-in-chief, so you have pointers to all the top groups(battalions?) underneath you(not necessary for them to know who their peers are because they can just link to you. Perhaps they have a pointer to the commander-in-chief, perhaps not). Those groups underneath the player have pointers to their members, and so on, until they have as members individual units. How to do this is up to you. You''d probably have three classes--unit, unit holder, and unit-holder-holder. The limitation of this is that you''d be unable to have, say, two squads of four men each and two artillery units in a platoon, usable as needed. You''d have to have four men and an artillery in a squad, and two squads per platoon. To avoid that, I''d probably derive both unit and unit-holder from some token(as in, trivial) class, and hold pointers to that (token) class. The token class would probably just contain an integer to say whether or not it is a unit or unit-holder class(technically this can be done with RTTI, but I have had it explained to me very well, and I''ve heard bad things about its implementation in compilers).
As for holding variable units, make the class hierarchy reflect the various choices. Hold a pointer to Engine, PrimaryWeapon, SecondaryWeapon, etc. Derive from each of these the various types of these. For each of your UnitTemplate''s, hold pointers of type Engine, PrimaryWeapon, and SecondaryWeapon. Store in those whichever types the user selects. Have the unit class model itself after the UnitTemplate by copying each of the UnitTemplate''s pointers.(I''m assuming these components can be damaged, or used up(PrimaryWeapon objects hold their ammo stores, the heat of their barrels, the amount of gunpowder residue they contain, etc. Engine objects store their fuel, etc.). If this is not the case, you don''t need to use pointers at all, just store some id number or enum) If, when a unit dies, it hands off(calls some function and another class stores the address of a pointer which the object previously controlled) its equipment to its platoon, the container class will need to be able to store equipment as well. If, when a unit dies, it simply drops its equipment, some sort of world class will need to acquire a pointer to the equipment.
See the wonders of polymorphism?
As for holding variable units, make the class hierarchy reflect the various choices. Hold a pointer to Engine, PrimaryWeapon, SecondaryWeapon, etc. Derive from each of these the various types of these. For each of your UnitTemplate''s, hold pointers of type Engine, PrimaryWeapon, and SecondaryWeapon. Store in those whichever types the user selects. Have the unit class model itself after the UnitTemplate by copying each of the UnitTemplate''s pointers.(I''m assuming these components can be damaged, or used up(PrimaryWeapon objects hold their ammo stores, the heat of their barrels, the amount of gunpowder residue they contain, etc. Engine objects store their fuel, etc.). If this is not the case, you don''t need to use pointers at all, just store some id number or enum) If, when a unit dies, it hands off(calls some function and another class stores the address of a pointer which the object previously controlled) its equipment to its platoon, the container class will need to be able to store equipment as well. If, when a unit dies, it simply drops its equipment, some sort of world class will need to acquire a pointer to the equipment.
See the wonders of polymorphism?
---New infokeeps brain running;must gas up!
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement