Jump to content
  • Advertisement
Sign in to follow this  
Suen

Enemy shooting

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement

header:
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 biggrin.png

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 this post


Link to post
Share on other sites
I disagree with deleting an enemy at run-time.

Assume you are creating a game World Of Warcraft: ph34r.png 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!! ph34r.png 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 this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!