Carousser Carousser - 1 month ago 9
C++ Question

Invoking a member function with object as arguments

I am currently taking an intermediate c++ class with my university, and we've just done classes/polymorphism and so I decided to work on a little project of my own. This is not homework, figured I'd get that out of the way.

So I'm using SFML to make a little "idle" game. This consists of an entity class, with a class for a weapon and a class for an armor. I have 2 entities, being the player and "other", or the enemy. Everything has been good so far, but I am running into trouble when I am trying to invoke a member function on the entity class with an argument as another entity.
Here are the two functions

/*
Simulates the entity attacking another entity
*/
void Entity::attackEntity(Entity other) {
other.decreaseHP(5);
if (other.getCurrentHP() <= 0) {
killEntity(other);
}
}

/*
Simulates main entity defeating another
*/
void Entity::killEntity(Entity other) {
if (other.getEntityType() == "Enemy") {
other.setXP(rand() % (other.getRequiredXP() / 9) + 1);
addXP(other.getXP());
//addXP(rand() % (rand() % (getRequiredXP() / 10) + 1) + getEntityLevel()); // testing
addGold(rand() % getEntityLevel() + getEntityLevel());

// Increment the level of the entity to give them better armor/weapon
other.incrementLevel();
// Regenerate a weapon and armor for the enemy
other.setWeapon(other.getWeapon().generateRandomWeapon(other.getEntityLevel()));
other.setArmor(other.getArmor().generateRandomArmor(other.getEntityLevel()));
}
else if (other.getEntityType() == "Player") {
other.setXP(other.getXP() / 10);
other.setCurrentHP(other.getMaxHP());
other.refreshEntityInfo();
}
}


Currently, in the main program, I am calling it as

if (clock.getElapsedTime().asSeconds() >= 1.0f) {
player.attackEntity(enemy);
clock.restart();
}


What I want the code to do is every 1 second, the player will "attack" the other entity, being enemy. This will decrease the health points of the other entity by 5, and when the other entity's health points drop below 1, it will "kill" the entity, granting the player experience and resetting the other entity's armor and weapon, which will give it new stats.
However, what is happening, is nothing. Health points do not decrease.
Obviously I am doing something wrong here as it is not working.

I tested just calling the decreaseHP() method alone in the time loop and that works:

if (clock.getElapsedTime().asSeconds() >= 1.0f) {
//player.attackEntity(enemy);
player.decreaseHP(5);
clock.restart();
}


but the way I supplied before using the attackEntity() method does not.

Here is the decreaseHP() method.

/*
Decreases the entity's current health by amount
*/
void Entity::decreaseHP(int amount) {
setCurrentHP(getCurrentHP() - amount);
}


Do I need to pass the other entity object as reference? Am I going about these functions in a poor way? How should I be approaching this?

Edit -- So I know I just posted this, but I changed the parameters for both the attackEntity() function and killEntity() function so it takes the entity object by reference, and that seemed to solve the solution.

/*
Simulates main entity defeating another
*/
void Entity::killEntity(Entity &other) {
if (other.getEntityType() == "Enemy") {
other.setXP(rand() % (other.getRequiredXP() / 9) + 1);
addXP(other.getXP());
//addXP(rand() % (rand() % (getRequiredXP() / 10) + 1) + getEntityLevel()); // testing
addGold(rand() % getEntityLevel() + getEntityLevel());

// Increment the level of the entity to give them better armor/weapon
other.incrementLevel();
// Regenerate a weapon and armor for the enemy
other.setWeapon(other.getWeapon().generateRandomWeapon(other.getEntityLevel()));
other.setArmor(other.getArmor().generateRandomArmor(other.getEntityLevel()));
}
else if (other.getEntityType() == "Player") {
other.setXP(other.getXP() / 10);
other.setCurrentHP(other.getMaxHP());
other.refreshEntityInfo();
}
}

/*
Simulates the entity attacking another entity
*/
void Entity::attackEntity(Entity &other) {
other.decreaseHP(5);
if (other.getCurrentHP() <= 0) {
killEntity(other);
}
}


However, my last questions still stand: am I going about this the right way?

Answer

The signature void Entity::attackEntity(Entity other) causes other to be a copy of the entity. Any changes made to other are local to the attackEntity function.

If you need the changes to persist from the source item, the most straight forward way is to pass other in by reference, changing the signature to: void Entity::attackEntity(Entity& other)