# Enemy shooting

This topic is 2298 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm creating a very simple 2D game in C++ (with a given external library) where I might have something like 20-30 enemy sprites on the screen from the beginning. I keep track on whether the enemy is alive or not through a member variable of the enemy object (simply a bool variable).

Now I want to have one random enemy of these 20-30 enemies to shoot a bullet and I want this to happen periodically. So for example every two seconds one enemy should be shooting a bullet. First time it might be the first enemy, second time might be the 10th enemy etc. I thought I could keep this simple by just generating a random number within a limit (which is the number of enemies) and use that number to determine which enemy that will shoot. The issue here is that an enemy can only shoot if it is alive, and if I have...say 20 enemies and 19 of them are dead I will keep generating random numbers until I get that very specific number of the remaining enemy that is alive and that feels like quite a waste of computations, basically a very inefficient way of doing it.

Surely there are better ways of doing this? The problem is that I'm not quite sure on what to search for on the net when it comes to this.

##### Share on other sites

int m_FrameTime; // Initialized on zero in the cpp
int m_ShootCounter; // Initialized on a certain number of frames.

cpp:
// In the constructor(or initialize)
m_FrameTime = 0;
m_ShootCounter = 2; // 2 frames for example

//in the gamecycle(or gametick):
if(m_FrameTime > m_ShootCounter) // When my frametime reached the amount of frames of the shootcounter, search for a random enemy
{
if(m_pEnemyList->Size() > 0 )
{
int random = rand()%(m_pEnemyList->Size()-1); // Creates a random number from zero to the maximum number of enemies
/*NOTE: array starts from zero until the 'size-1', so if the last enemy is random-ed and you don't add a -1 to it, you are out of the array! */
m_pEnemyList->At(random)->ShootBullet();
}
m_FrameTime = 0 // Reset frameTime
}

++m_FrameTime;
Edited by EngineProgrammer

##### Share on other sites
I guess that you are storing your enemies in an array since they can either be set as alive or dead.

Just read EngineProgrammer's answer, and his code has an m_pEnemyList. It's not defined in his code, but it seems to be a vector.

Going with that, you add your living enemies to the vector, while still using the array as a data pool to spawn new enemies and keep dead ones. The vector would have pointers to the enemies that are alive in the array, and you would query a random index for the vector.

##### Share on other sites

I guess that you are storing your enemies in an array since they can either be set as alive or dead.

Just read EngineProgrammer's answer, and his code has an m_pEnemyList. It's not defined in his code, but it seems to be a vector.

Going with that, you add your living enemies to the vector, while still using the array as a data pool to spawn new enemies and keep dead ones. The vector would have pointers to the enemies that are alive in the array, and you would query a random index for the vector.

You are correct that I have an array where I have stored my enemies in. Going by the two answers given by you, I would at the start of the game have a vector of pointers to all of my enemies and as soon as a certain enemy is dead I should remove the pointer to this enemy from this vector, correct?. Yes this does basically reduce the amount of enemies that can shoot each time so it does solve the problem. But doesn't this also mean that each time I remove an element from the vector all the data in it has to be moved due to the nature of the stl vector? Is there a way of avoiding all that shuffling of data inside the vector? Or perhaps this movement of data in the vector isn't expensive due to the fact that it only consist of pointers?

##### Share on other sites

[quote name='CC Ricers' timestamp='1346355995' post='4974892']
I guess that you are storing your enemies in an array since they can either be set as alive or dead.

Just read EngineProgrammer's answer, and his code has an m_pEnemyList. It's not defined in his code, but it seems to be a vector.

Going with that, you add your living enemies to the vector, while still using the array as a data pool to spawn new enemies and keep dead ones. The vector would have pointers to the enemies that are alive in the array, and you would query a random index for the vector.

You are correct that I have an array where I have stored my enemies in. Going by the two answers given by you, I would at the start of the game have a vector of pointers to all of my enemies and as soon as a certain enemy is dead I should remove the pointer to this enemy from this vector, correct?. Yes this does basically reduce the amount of enemies that can shoot each time so it does solve the problem. But doesn't this also mean that each time I remove an element from the vector all the data in it has to be moved due to the nature of the stl vector? Is there a way of avoiding all that shuffling of data inside the vector? Or perhaps this movement of data in the vector isn't expensive due to the fact that it only consist of pointers?
[/quote]

Yes, the vector would have to move all the data after the erased element down one position. The operation takes linear time whether it holds pointers or not, but for 30 enemies this is not a big deal and you won't notice a performance hit.

##### Share on other sites
But doesn't this also mean that each time I remove an element from the vector all the data in it has to be moved due to the nature of the stl vector? Is there a way of avoiding all that shuffling of data inside the vector? Or perhaps this movement of data in the vector isn't expensive due to the fact that it only consist of pointers?

If you do not care too much about the ordering of the pointers inside the element, you can swap the element to be deleted with the last element in the array then erase the last element in the array.

##### Share on other sites
EngineProgrammer provided a nice solution

Something far more simple would be to:
keep track of how many enemies are alive (variable initialized with number of enemies and decremented each time one dies);
using the same process he described to do this at certain intervals: generate a random number using the number of living enemies as your cap, and iterate through your enemies array, skipping dead ones, while decrementing the random number, and have the enemy shoot when your random number is 0
Hope that makes sense

Some pseudo code could help:
int totalEnemies = 30;
int livingEnemies = totalEnemies;
Enemy[30] enemies;

// in code region dealing with enemy death
livingEnemies--;
//

// on iterval for enemy to shoot
if(livingEnemies > 0)
{
int randNum = Math.Rand(0, livingEnemies); // generates a random integer between bounds, lower exclusive, upper inclusive
for(int i = 0; i < totalEnemies; i++)
{
if(enemies.isAlive)
{
randNum--;
if(randNum == 0)
{
// Enemy shoots
}
}
}
}
//
Edited by TheResolute

##### Share on other sites
I disagree with deleting an enemy at run-time.

Assume you are creating a game World Of Warcraft: There is a mob you are killing. The mod has like 40items carrying, position, rotation, etc. All stored in data members. And then... You kill it in run-time. The mob is gone.. And the world continues happily ever after. But then... unexpected The mob has a re-spawn!! BAM! Enemy has been allocated again! 40items, position, rotation, and many more data members created in Run-time.

I think we all know what will happen? If not: the game have a possibility of lag. always try to avoid lag so never ever allocate an object at run-time. ( unless it's a temporary local data variable or something.

Solution: The enemy has a "bool m_IsKilled" or somethng. You only calls Ticks, Paints, Checks on the Enemy when he is still alive.

##### Share on other sites

Some pseudo code could help:
int totalEnemies = 30;
int livingEnemies = totalEnemies;
Enemy[30] enemies;

// in code region dealing with enemy death
livingEnemies--;
//

// on iterval for enemy to shoot
if(livingEnemies > 0)
{
int randNum = Math.Rand(0, livingEnemies); // generates a random integer between bounds, lower exclusive, upper inclusive
for(int i = 0; i < totalEnemies; i++)
{
if(enemies.isAlive)
{
randNum--;
if(randNum == 0)
{
// Enemy shoots
}
}
}
}
//

Won't work.

So you have 30 enemies. Let us say I have killed the 2nd, 4th, 6th one. So 27 enemies left.

the rand() seeder will only give me a number from 0-27.
Meaning, if I get the number 0, 4, 6 those enemies will try to shoot but they are dead..
Also means the last 3 enemies will never be able to shoot a bullet.

##### Share on other sites

Won't work.

So you have 30 enemies. Let us say I have killed the 2nd, 4th, 6th one. So 27 enemies left.

the rand() seeder will only give me a number from 0-27.
Meaning, if I get the number 0, 4, 6 those enemies will try to shoot but they are dead..
Also means the last 3 enemies will never be able to shoot a bullet.

You must have misread the code or I made a mistake, but it is not accessing the array using the random number as an index, it is iterating through the array and every time an enemy is alive, it decrements its counter and if the counter is zero, meaning that this enemy is the nth living one, it will then have it shoot

1. 1
2. 2
Rutin
19
3. 3
khawk
18
4. 4
5. 5
A4L
11

• 9
• 12
• 16
• 26
• 10
• ### Forum Statistics

• Total Topics
633769
• Total Posts
3013754
×