Enemy Bullets

Started by
29 comments, last by BeerNutts 9 years, 2 months ago

I'm just a little confused at the moment. I'm making a 2d space shooter with SDL and C++. Whats the general process for making the enemies on screen shoot? How should I go about creating bullets for them?

Advertisement

I would use a sprite or solid circle/rectangle and make that move in the directions the enemy would be shooting in.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

What I mean is how do I create and store bullets? I got the player to shoot perfectly. For the player I just used a vector to store the bullets. But now I'm dealing with numerous enemies so how would I go about it?

Are your enemies game objects like the player because you could deal with it in the same way. What I do is I have a bullet system that owns all of this stuff and the enemies and player just ask it to create one for it and they get a handle to this object. This allows me to reuse old bullets for new ones so I have less memory allocation.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

Is it siimilar to:

Loop through enemy

enemy.createBullet();

I have something like this but it doesnt really work.


What I do is I have a bullet system that owns all of this stuff and the enemies and player just ask it to create one for it and they get a handle to this object. This allows me to reuse old bullets for new ones so I have less memory allocation.

That: make sure you never ever create new instances if you can reuse old ones. Easy rookie mistake to avoid (and you won't end up asking yourself why its starting to lag after a while...)

Megallion, you should post some of your code so that we can see where the problem is. Right now, it sounds vague. There are a gazillion ways to make bullets, and chances are, what you might be doing isn't one of them...\\

Here are a question to ask yourself:

When do enemies shoot? Is it after a predetermined set of interval, e.g. every 2 seconds, 1 second, 10 seconds? or is it triggered by a specific event in the game, e.g. player happens to be in the line of sight? Or perhaps a specific frame in an animation? Just like the player shoots after the player presses the shoot button, enemies need their own triggers too. The only difference is that instead of having the human player initiates the trigger (pressing a button), the trigger for the enemies must come from within the game code itself.

Once you have determined the trigger, then it's a matter of calling that createBullet() function from that trigger.

If you have organized your game objects such that the player and enemies share a common interface to shoot bullets, then having the enemies shoot is just the same as having the player shoots.


if (shootButton.pressed()) {
    playerShip.createBullet();
}

if (enemyTrigger.shoot()) {
    enemyShip.createBullet();
}

Since it looks like we're doing this piecemeal, some additional tidbits.

While you are unlikely to stress the computer with the style of game you described, you can get into somewhat good habits of being cache friendly. Don't obsess overmuch about these, but as you reach a larger scale they become important.

For small temporary objects like this it is generally good to work with pools, activating and deactivating objects as needed. Allocations take a relatively large amount of time, and if you are creating and destroying thousands of bullet objects every second, that is wasted time. Instead maintain object pools that have a live/dead or active/inactive or similar state. Depending on the situation it might make sense to keep them partitioned so all the live items come first then you can stop processing, or it might make sense to traverse the entire collection of both live and dead items every step.

Pools as organization can be very effective for bulk processing, especially for processing particle-like objects such as bullets. Can each side's bullet have friendly fire? If every bullet can hit everything then a single pool of bullets might work well. If there are friendly fire rules the pools can accomodate that as they are processed. Perhaps have an "AI bad guys" pool and a general "all players" pool if there is no friendly fire between players. Or perhaps an array of pools for each player if they can friendly fire other players but not friendly fire themselves.

As you process the pools, be cache friendly. The cost of loading data is expensive. Crossing the boundaries is roughly an exponential performance penalty. There are all kinds of good books and descriptions and studies, but here's a quick and fun little toy that demonstrates it rather clearly. If you are working with larger data sets there are very clear performance steps as you exceed the various cache size boundaries.

Ensure that these little particles are small and well-aligned. Cache lines are typically 64 bytes these days, so if you're processing them linearly it can work great as the processor can detect when you are nearing the end of your cache and prefetch more data. For a 2D space shooter you likely can store 2 16-bit numbers for position and 1 or 2 8-bit numbers for direction, if each structure is 8 bytes you can have an array of tens of thousands of bullets, something like a bullet storm.

So if you have a non-swept collision you might have a loop over every bullet, test the active/inactive flag, read the direction and speed it travels, then adjust its velocity, test the new position bounding box against the player sprite bounding box, potentially queue up if the bullet needs extra processing for a collision, and advance to the next bullet.

Of course, considering that the modern L1 data cache is around 32K, and the L2 cache is around 256K, assuming you are letting your video card do all the rendering work and your audio card do the audio work, your memory caches will have plenty of free space for your 2D simulation even if you are very sloppy about it.

Much of this advice is good, but, really, he's an obvious beginner, he's asking about how to creates enemy bullets, he doesn't need to hear about being "cache friendly" yet or reusing entities. You've probably lost him and he might be getting discouraged.

megallion, your enemies creating a bullet can be almost exactly like your player creating a bullet. You said, for the player's bullets, you add it to a vector. Why can't you add enemy bullets to the same vector?

In your bullet class, you can have an OwnerId, so you know if the bullet belongs to the player or an enemy. Every time you add a bullet from the enemies or the player, put it in your BulletVector. As you iterate over the BulletVector, moving it based on each bullet's position and velocity, check for collisions. If an enemy has collided with a player's bullet, you remove the bullet from the vector, and subtract the bullet's damage from the enemy. Same if the player collides with an enemy's bullet.

Once you're comfortable doing that, you can look into more advanced topics like creating a pool of objects, and having them be stored ina cache-friendly location, but, I'd say just get it to work now.

Good luck and have fun.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

You should have a list, if theres 1 enemy, only 1 enemy will be checked.

( i have a list for every enemytype btw, not 1 big for all )

You just do this :

enemylist.checkhit( x,y )

A list is advanced memory management,

every object holds a pointer to the next object in the list,

search it up.

greetings

S T O P C R I M E !

Visual Pro 2005 C++ DX9 Cubase VST 3.70 Working on : LevelContainer class & LevelEditor

This topic is closed to new replies.

Advertisement