Ok, good work :+)
But a note of caution though: there is still going to be massive changes, as I said earlier I would hold off on altering your existing code. Seriously consider starting a new project, gradually build it up from scratch.
About what should be a class and what shouldn't:
Say a Soldier has a rank of Sergeant. In a simple scenario, that might exist only as private member variable of type std::string or as you have it an enum. However, if it is going to have some responsibility or functionality, then it would need to be a class. A weapon (or any type of resource) is a good example of something that should be a class. The Soldier can "OWN" them: "HAS A" with member variables.
Now I am not saying you should go and create 20 classes representing weapons or armour say. A Gun class might still only have basic info like it's name and calibre, but at least you have taken that info out of the Soldier class. It's the same thinking as a Person doesn't have a
PushBrakePedal function. One can still have 20 Gun objects with different names etc, but we have just the one class for them.
About complexity:
One of the not so obvious things about OOP design is how all the classes interact with each other. If one has a bunch of complexity in a class, then one has to define how that is going to work with everything else. If the complexity exists in a class and is not implemented in terms of the other classes, then we may as well not have it: it doesn't do anything.
So that's another reason to start simple: adding something seemingly innocuous like 10 different Armour types might have quite a large effect on the complexity for the whole application. Those implications on the design need to be managed.
What are we going to have in our Soldier class?
With the Soldier class (indeed any class), we have to ask ourselves: What attributes does it have? ; What things does it own? ; What actions can it do? So we need to careful about anything external to Soldier, we have to allow for interaction with external things, but we don't want any external logic in our class. That means anything to do with fighting or battle or tactics, a Soldier should perhaps only have an
UpdateHealth function, all the logic for battle should be elsewhere.
So can you write down what you want to have in your Soldier class? Try not to put in too much. We can then see how that is going to fit in the scheme of things.
One thing you could do: create an Actor, Player and Enemy classes:
1 2 3 4
|
class Actor;
class Player : public Actor;
class Soldier : public Player
class Enemy : public Actor;
|
Think about what variables and functions are going to go in each of those classes, what variables / functions can be pushed upwards? We can call base class functions from the derived class.
In my mind, we haven't yet finalised what is in our class, but here is some observations on the existing code, again I would be reluctant to rush in and change it.
With those enum's, I would be inclined to pull them out of the class and have them available in the scope that calls the class constructor, you can put them in a header file. The enum value would then be an argument to the ctor call. IMO scoped enum's are better, they don't decay to an int:
http://en.cppreference.co/w/cp/language/enum
They also make things easier to read, as in :
Race::Human
With your ctor's consider using a member intitialization list:
1 2 3 4 5 6 7 8 9 10
|
Soldier::Soldier()
: // colon introduces member initializer list
baseAtt (1) , //direct initialize
baseDef(1) ,
armor (2) ,
tatics(1) , // high number represents more advanced tactics ie more effiecent
support (0) ,// support represents it's ability to handle many situations
numberOfAttacks(1)
{}
|
http://en.cppreference.com/w/cpp/language/initializer_list
Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. Member initializer list is the place where non-default initialization of these objects can be specified. |
With the names of things, don't abbreviate them and use something meaningful. You are right, items is not a good name, call it what it is: BattleKit or something else equally descriptive.
What do these mean?
1 2 3 4 5 6
|
int baseAtt;
int baseDef;
int armor;
int support;
int tatics;
int inia;
|
Class member variables should be
private
, and provide functions to use them. It may not be necessary to have get and set functions for every member variable. We only need functions for the member variables we want to expose as the interface for the class. We only need set functions if the value changes (in an external sense) after construction.
There we go more stuff to think about :+)