Advertisement

Multiple bullets?

Started by April 16, 2016 12:30 PM
9 comments, last by irbaboon 8 years, 8 months ago

So, I've been asking a lot of questions on the forum recently, but those really payed off. So far, I've implemented a fair amount of features into my game (i.e grenades, health bars, attack system, etc.). Next, I intend to add guns basically attached to my player. I know HOW to do that, but I have a slight problem.

How would I have multiple bullets on the screen? What I usually do is, I wait for the bullet to exit the screen, then it becomes null, then the player can shoot again. The only problem is, I can't render more than 1 at a time (Note: I still haven't even implemented the gun, but that's just usually how it is in most of my other smaller games).

How would I go about doing this?

Thanks to whomever replies! :D

Create a vector or array of bullets.

Advertisement

How do you handle timing in your game? You can fire a bullet once every x unit of time.

or

You can fire another bullet once the current one is done firing. This can be accomplished with flags or a ticks based timer with potentially a FSM.

edit - rereading your post, glportal's advice seems prudent.

-potential energy is easily made kinetic-

then it becomes null

heh.

Anyway, look into "std::vector".

You could just make a variable like this:


std::vector<Bullet> myBullets;

then use it like this:


myBullets.push_back(Bullet(x, y)); // or however your constructor goes, if any. You can probably do myBullets.push_back({ x, y }); as well

If you have update and draw functions in your bullet class, then you can do this to call those:


for (auto& i : myBullets) { // Loop through all the elements in "myBullet" and let "i" be a reference to the current element. 
    i.update();  // or i.draw();
}

Hope that helps in any way.

One standard approach (as always, there isn't a single approach which is the approach in virtually all cases) is to use a factory function to instantiate bullet objects as needed. Usually this has two requirements: 1.) the player presses a "fire" button, and 2.) game rules determine that it is valid to fire again (something like a time delay between shots, the player has enough ammunition, whatever).

It sounds to me like your program has a variable instance of bullet, and you assign fresh values to it when a player fires, and then that variable is "taken" until the bullet goes off screen, so no new bullets can be fired until the values are nulled once the bullet goes off screen. Is that right? If so, glportal's suggestion is a good one. If you have a list of objects in the current scene, whether its a list for bullets alone, a list for all objects in the scene, or something in between, you can add and remove bullets from that list however you like. Each bullet is still an object and so will still have its own fields like position, velocity, etc.

-------R.I.P.-------

Selective Quote

~Too Late - Too Soon~

You treat the bullet as an entity. When you fire a bullet, you spawn a new entity, give it a constant velocity, and give it some special logic to do bullet things. When it collide's it's life is over and needs to destroy it's self.

Advertisement

Anyway, look into "std::vector".


Yes, you would be correct if the OP was using C++. But the tags on his topic states “Java,” so he should use java.util.ArrayList instead.

The same principles apply, though:

ArrayList<Bullet> bullets = new ArrayList<Bullet>();

bullets.add(new Bullet(x, y));

for ( Bullet b : bullets )
    b.update();
}    
At some point, you will need the ability to remove bullets. Use an iterator instead:

ListIterator<Bullet> itr = bullets.listIterator();
while ( itr.hasNext() )
    Bullet b = itr.next();

    if ( !b.update() )
        itr.remove();
}

Don't know if this is of any relevance for you...

What others said, but: at least if you are using Unity as your game engine, or your engine/framework has a similar weakness with instantiating/destroying gameobjects/whatever-it-is-called-in-your-framework, OR your own "engine" you write for your game there will end up having similar weaknesses, never EVER instantiate/destroy while running the game!

Always instatiate at scene load, manage as a pool during the game, and destroy at the end of the scene.

Why? Would you believe me that at least in case of Unity, the engine was able to handle hundreds and thousands of gameobjects with a renderer and physics (not all of them had their physics components active at the same time though) on a pretty up to date intel CPU and a high midrange GPU while keeping >30FPS as long as I was using a pool to "re use" the objects, but dropped to around 20 or less FPS while I was still using instantiate/destroy instead of managing the gameobjects with the pool?

Just so my usecase gets a little bit clearer, I was creating an automatic weapon at the time, that shot bullets with a renderer and physics rigidbody attached, and ejecting spent cartridges, again with a renderer and physics rigidbody attached. Madness? So I thought too, until I actually profiled the slow running scene and found the problem was neither rendering nor physics, but the obscene overhead of instantiate/destroy of a gameobject. Amplified by about 30-60 of both going on per second. Seems Unity and a midrange PC can pretty much handle the use case, as long as you optimize a little bit (for example use object pools).

Now, this might totally not affect you. But then, using a pool instead of instantiate/destroy doesn't cost much more time to implement, and will safeguard against such scenarios where instantiating and destroying an "object" (in case of unity, a gameobject comes with a multitude of components, its more like a whole mess of objects) costs more performance than anything else.

Just instantiate at startup (making a good assumption on how many bullets you are gonna need on the screen at any time), keep in a managed pool (reuse bullets that left the screen or impacted with something, move them back to the gun and reset their trajectory... if you need more bullets, instantiate more and add them to the pool, but never destroy them yet), and destroy them when the level is over (and you have a second or so anyway to dispose the rest of the level, and do not need to render anything on screen with a stable framerate).

As previously stated, the simplest way to handle multiple bullets is to store them all in an ArrayList, and remove them when they collide with something or leave the screen.

Although Gian-Retro's advice is the optimal practice, it requires a bit of experience to implement properly, and might not apply as well to your case as it did to his. I would just use ArrayList unless you notice a performance issue. :)

As previously stated, the simplest way to handle multiple bullets is to store them all in an ArrayList, and remove them when they collide with something or leave the screen.

Although Gian-Retro's advice is the optimal practice, it requires a bit of experience to implement properly, and might not apply as well to your case as it did to his. I would just use ArrayList unless you notice a performance issue. :)

True, as given the project is less taxing on hardware resources, and the "objects" being instantiated and destroyed are less resource intensive (2D Sprites, no Physics components for example), as well as the underlying engine/framework being better at handling instantiation and destroying of objects at runtime, the difference might not be measurable.

Just wanted to give a heads-up on a good practice I would have liked to know about sooner myself :)

This topic is closed to new replies.

Advertisement