Here's my advice, I think you may have a little too much polymorphism going on.
First, let's start with the Player's health. Where is it? I see you have a function PlayerHealth(), but all that does is set a temporary local variable which is then immediately lost. If you're trying to implement a game with attacking, you'll almost certainly want a member
health
. It's up to you what type you want
health
to be, but I'd keep it simple and use an
int
.
Now where would you put a member
health
?
Well, since every player is going to have a health, I would implement the health member within your base class
Player
. That way every class, like
Warrior
, that inherits from
Player
, will have a member
health
. Furthermore, you'd probably want the player's health to be public since other enemies can attack and lower a player's health.
1 2 3 4 5 6 7 8 9 10
|
class Player{
protected:
int AttackPower;
public
int health; //I think health should be public because other enemies can attack and diminish a players health.
void setAttackPower(int b){ AttackPower = b; }
virtual void Attack() = 0; // Pure virtual
};
|
Next, I would implement constructors for the child classes. If you want all Warriors to have the same attack power, then you can define it within the constructor.
1 2 3 4 5 6 7 8 9 10 11 12 13
|
class Warrior:public Player{
public:
Warrior(){ AttackPower = 80; health = 120; } //initialize the inherited members from Player
void Attack(Enemy &enemy){ //Attack takes a reference to an Enemy because a player will attack different types of enemies
cout << "Warrior charge! - " << AttackPower << endl;
enemy.health -= AttackPower; // equivalent to takeDamage();
if(enemy.health <= 0){
//player killed the enemy, you could delete or destory the enemy depending how you implement it
}
}
};
|
I also made changes to your Attack function. It's defined as pure virtual because every child class Warrior, Musketeer, etc. will presumably have different attack modes and strengths. Therefore, each of their Attack methods may be slightly different from one another. For example, maybe the Musketeer can deal varying damage depending if he shoots the enemy in the chest or head, whereas the Warrior might have the same attack type dealing the same damage every time.
By implementing
health
as public, players and enemies can attack each other and remove each other's health. I got rid of the takeDamage() function all together because an Enemy attacking a Player is the same thing as the Player taking damage and visa versa.
Here's the full implementation:
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
#include <iostream>
#include <string>
using namespace std;
class Enemy;
class Player{
protected:
int AttackPower;
public:
int health;
void setAttackPower(int b){ AttackPower = b; }
virtual void Attack(Enemy &enemy) = 0;
};
class Enemy{
protected:
int AttackPower;
public:
int health;
void setAttackPower(int a){ AttackPower = a; }
virtual void Attack(Player &player) = 0;
};
class Warrior:public Player{
public:
Warrior(){ AttackPower = 80; health = 120; }
void Attack(Enemy &enemy){
cout << "Warrior charge! - " << AttackPower << endl;
enemy.health -= AttackPower; // equivalent to takeDamage();
if(enemy.health <= 0){
//player killed the enemy, you could delete or destory the enemy
}
}
};
class Musketeer:public Player{
public:
Musketeer(){ AttackPower = 150; health = 200; }
void Attack(Enemy &enemy){
cout << "Musketeer shoot! - " << AttackPower << endl;
}
};
class Ninja:public Enemy{
public:
Ninja(){ AttackPower = 60; health = 90; }
void Attack(Player &player){
cout << "Ninja! - " << AttackPower << endl;
player.health -= AttackPower;
}
};
int main(){
Warrior warrior1;
Ninja ninja1;
cout << "The enemy has health: " << ninja1.health << endl;
warrior1.Attack(ninja1);
cout << "The enemy now has health: " << ninja1.health << endl;
return 0;
}
|