Reputation: 45
My question is How can I have combat for all enemies by having only 1 function?
At the moment I create my enemies by writing Enemy
(class) and giving it object + number
name, then I just give some inputs and it looks like:
Enemy object1(1, 20, '/', "AQUA", 1);
Enemy object2(5, 40, '/', "YELLOW", 2);
Enemy object3(10, 60, '/', "WHITE", 3);
Then I have a runtime for Combat and I run an awful while loop:
while (object1.getHp() > 0)
to run my combat code.
So now I need to have just one combat function to run all different enemies, I already tried a lot of thing but nothing seems to work. Any idea on what can I do?
Sounds and looks dumb but I really can't guess anything to do about it, already lost tons of hours looking for a solution.
Upvotes: 3
Views: 16230
Reputation: 2789
What you need first is a container able to hold your Enemy
instances or pointers to them. Most containers are templated classes, which have to be typed. One of them is the vector (a contiguous 'list'), which can be created in your case as
std::vector<Enemy>
: A 'list' holding your full objectsstd::vector<Enemy*>
: A 'list' holding pointers to your objectsAn example if you take references from your objects:
std::vector<Enemy*> enemies;
enemies.push_back(&object1);
enemies.push_back(&object2);
enemies.push_back(&object3);
If you are not familiar with pointers, you can look here, even though it may be a bit opaque at first!
A range for loop will let you iterate over your container pretty easily
for ( auto enemy : enemies ) {
enemy->doStuff();
}
The auto
will deduce the type from the container, and doStuff
will be executed sequentially for every enemy in your list. If your container contains instances instead of pointers *
, you will need to take a reference &
of the object instead, and use for ( auto& enemy : enemies )
. This will ensure your object is modified in place, and not copied, otherwise, your changes won't get reflected in the container.
As mentioned in other answers, when you are ready to move to the next level, you can have a look at smart pointers. Because C++ code is unmanaged and has no out-of-the-box memory management, you are responsible for delete
ing any new
ed object. Smart pointers will help you more safely manage the lifespan of your data. Raw pointers (without any smart pointer to protect them) are considered bad practice in most situations nowadays.
However, your Enemy
instances are created on the stack, so they will get automatically destroyed at the end of their scope (function, {}
, ...). This also means that if you have any pointer *
or references to them that you use outside this scope, your object has been destroyed already, and you will encounter a memory exception or undefined behavior, i.e. Don't do that!
Upvotes: 6
Reputation: 14607
You can use std::vector to group your objects like this:
std::vector<Enemy> vEnemies
{
{ 1, 20, '/', "AQUA", 1 },
{ 5, 40, '/', "YELLOW", 2 },
{ 10, 60, '/', "WHITE", 3 }
};
And, then you can use C++11's range-for loop for all the objects:
for ( auto& e : vEnemies )
{
e.doSomething();
}
You may also explore std::for_each for your other use-cases.
If you're looking for a solution with pointers e.g. std::vector<Enemy*>
then you ought to first look at smart pointers (std::unique_ptr / std::shared_ptr along with std::make_unique / std::make_shared) to enforce RAII for your objects allocated on the heap / free-store.
Upvotes: 2
Reputation: 1675
Define a container of enemies preferably a std::vector<Enemy>
and iterate over all the objects in the container.
std::vector<Enemy> enemies;
// Now construct your enemies in the vector.
enemies.emplace_back(1, 20, '/', "AQUA", 1);
enemies.emplace_back(1, 20, '/', "YELLOW", 2);
.
.
// Now loop through.
for (auto & enemy: enemies) {
enemy.Combat(); // Whatever you want
}
Upvotes: 1
Reputation: 4490
Please find the rough instructions below to solve your problem.
That's all.
Upvotes: 1