I'm going to cut in here. I still see some design flaws that I feel I should point out, and some advise I don't necessarily agree with.
I'm not saying you need to change anything -- if it's working it's working and that's fine. I just feel I should point this out for your future reference. OOP is a very difficult concept to grasp, but you seem to be making a very strong effort here, so I just want to help guide you on the right path.
If you find yourself writing getters and setters for all your member variables you're doing something wrong. The whole point of a class is that it manages its own state. When you start making getters and setters, you are opening the doors to let other classes manipulate its state which defeats the entire point of having a class in the first place.
Putting all the stats in a struct and making a big getter/setter for that struct isn't much better. Sure it reduces the number of getters and setters, but it still horribly violates the encapsulation you're trying to create.
Furthermore, you are treating the player as a special case. You shouldn't be. At least not in the GameObject class.
1 2 3 4 5
|
void LivingObject::calcDamage()
{
if(EnemyFightActive=0)
{
damage = rand()%Player.getAtk()-rand()%this->getDef();
|
There are a few things wrong with this.
1) It assumes the player is attacking this object, and that this object is not the player.
2) It assumes there is only 1 player.
3) A base class (LivingObject) has knowledge about its children (Player and Enemy). It shouldn't. The base class should be generic and work the same way for ALL its child types. It shouldn't treat any of them specially. If you need special treatment for a specific child class, you put that code inside that child class.
In this situation, you are having to write separate code for player->enemy attacks and enemy->player attacks, even though they both fundamentally are the same. The goal here, and the whole point of having this hierarchy structure is so you can work in more generic terms. If enemies and players are both game objects, you only need to write code for an object->object attack.
I would do something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
class GameObject
{
public:
int calcDamage(const GameObject& attacker)
{
return (rand() % attacker.attack) - (rand() % defense);
}
void takePhysicalDamage(const GameObject& attacker)
{
health -= calcDamage(attacker);
}
protected:
int health;
int attack;
int defense;
// ...
};
/*
Then, elsewhere in your program, in a broader scope (ie, your 'Game' or 'World' class,
or your 'main' function .... basically whatever part of your program owns all the enemies
and the player...)
*/
// if the player is attacking an enemy
enemy.takePhysicalDamage( player );
// or if an enemy is attacking the player
player.takePhysicalDamage( enemy );
|
Since inheritance forms that "is a" relationship, you can treat Player and Enemy objects as if they were GameObjects, because they
are GameObjects. This lets you write generic functions like the above which work with
any GameObject, regardless of whether it's a player or a specific kind of enemy.
Also note that GameObject doesn't need to know or care whether it's a player attacking an enemy, or vice versa. It could be a player attacking a player for all it cares.
Also note that since all the stats are being modified in GameObject, you don't need a crapload of getters and setters, because GameObject is just modifying itself like it should.