Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

My game is a 2D game(or tries to be) in pure C using SDL(no OpenGL at all). No specific goal in it, it's pretty much boilerplate code.

I decided I want to make my character/player shoot "something", whether you'd call it a bullet or not is up to you. But even before writing any code, I already saw my first hurdle. You see, in reality when you shoot a bullet it's pretty fast, you'd normally hit a target by the time you shoot again, in my game I want the bullets to be slow so that two or three or more can be displayed on the screen. This is where the problem starts. I have written some pseudo-code to illustrate my problem.

Basically, when I shoot a bullet, I increment a total bullet counter, then the sprite would appear and every few MS I would update the animation and check for collision. When I have multiple bullets which I store in a structure array, I would loop through all of them to check their collision, or if they went out of the screen's view. When one fits either condition, I will remove it from the screen and (free it) from the structure array and that index will point to invalid memory. Basically, my pseudo-code tries to illustrate the problem.

http://pastebin.com/9Y40GgT4

This is my interpretation of how it should be done. I am assuming there are other ways. Hopefully we can avoid the "Why C and not C++ discussion at this time".

share|improve this question
add comment

1 Answer

up vote 4 down vote accepted

There's no reason to go c++ here =)

The simplest solution in these kinds of situations that I've found is something like this:

#define MAX_BULLETS (something reasonable)

struct Bullet 
{
int alive; // default = 0
float x, y;
...
}
bullet[MAX_BULLETS];

..

void spawn_bullet(float x, float y, ...)
{
// find first free slot
int i = 0;
while (bullet[i] == 0 && i < MAX_BULLETS) i++; 
// fill in the data
bullet[i].alive = 1;
...
}

..and when handling physics, just loop through the whole array and handle the ones that are alive.

YES, you will be "wasting time" looping through unused array slots, but you should be able to handle the situation where all of the slots are in use, so this is not as big a problem as it seems - the simplicity is worth it.

Alternatively you could use linked lists, but then you get the overhead of traversing the linked list - the worst case performance will be much worse than looping through an empty array.

As a bonus feature, you can use the "alive" as a counter that you decrease on every physics loop to give the bullets a limited range; and the "age" of the bullets can also affect the amount of damage they cause.

If you have huge amounts of bullets, you can skip the "find first free slot" scan and just pick a random slot; if it's in use, just don't spawn a bullet. Nobody will notice.

EDIT

As Sam Hocevar pointed out, the search is not necessary if, when removing bullets, you move the latest bullet on top of the currently removed one, like:

void remove_bullet(int n)
{
    bullet[n] = bullet[--bullet_count];
}

In this case you won't need the alive member either.

share|improve this answer
    
Does this mean that I basically will not have to free the bullet object once I am done with it? –  farmdve Dec 22 '12 at 6:54
    
Just set the alive to zero. No run-time allocations needed. –  Jari Komppa Dec 22 '12 at 6:55
    
But this means it's all going to be on the stack, not on the heap. With today's systems running quite a few GBs of RAM, even mine has 5 it won't be a problem, but usually I avoid creating a lot variables on the stack. –  farmdve Dec 22 '12 at 6:58
1  
+1 for "The simplicity is worth it". That's probably the most important thing in the world (of game programming) –  Panda Pajama Dec 22 '12 at 9:51
1  
Oh wow. There is no reason for that loop, not even simplicity. You can avoid it with just one extra count variable, which is the current number of bullets. spawn_bullet writes in bullet[count] then increments count, end of story. –  Sam Hocevar Dec 22 '12 at 20:17
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.