Help with logic for reusing bullets

A place for people with an interest in developing new shmups.
Post Reply
User avatar
dpful
Posts: 1205
Joined: Tue Feb 01, 2005 5:19 pm
Location: SLC, UT, US
Contact:

Help with logic for reusing bullets

Post by dpful »

Hi I didn't search thoroughly through the forum, just thought I'd ask-- also, don't really know the best terms to google in this research, so please help me.

I'm working on a game (in Construct 3), finished it, learned about garbage collecting after completing the game, so after about a week, the garbage collection is ridiculous (it's an arcade game, always on at the local bar- choppy after about 7 days).
Anyways, I'm trying to backtrack on all the shooting logic.

Just experimenting with trashing all the "on button press spawn bullet, run 'bullet' behavior (move up screen), collide with enemy, destroy bullet",
and replacing it with a more appropriate "on button press position bullet at player, run 'bullet' behavior, collide with enemy, stop bullet behavior/relocate off screen- ready for next button press--- reusing same bullet, so no creation or deletion. And wow I wish I understood this concept and it's relation to garbage collection before I made the game. Or what garbage collection was, duh.

Anyways, this works great for one bullet. I'm just sitting here wondering the best way to do this for multiple bullets and I need some ideas. Does anyone have any?
What's the best way to reuse three or four bullets on the screen at once? Do I have to manage 3 or 4 independently? All in relation to each other?
---and I want to do the same for enemy bullets, which would be 50 or so. Sounds hard. What is the easiest logic for reusing 50 or so bullets?
Thanks!!!!

I'm sure there's a proper approach, but I'm having a hard time intuiting it. I'm low on brain cells after digging back in to get a single bullet fixed up.

And, just to be clear, my understanding is that any game that runs in a browser environment is subject to the browsers re-allocation of memory (garbage collection), and it's always choppy in-game. And there's no instruction to do the garbage collection when you choose to. So please correct me if I'm wrong about that.
-And I'm enjoying using Construct 3, I'm hoping I can program around this limitation.
(p.s. I know almost nothing about programming, I just made this game, so other fundamental computer concepts might have gone right over my head too, please set me straight!)
User avatar
dpful
Posts: 1205
Joined: Tue Feb 01, 2005 5:19 pm
Location: SLC, UT, US
Contact:

Re: Help with logic for reusing bullets

Post by dpful »

---update---
please chime in if you have some opinions or info on this.

---But just by googling some of the stuff I was trying to describe here, I've learned a lot about GC in browsers, so not as helpless as I thought.
But still at a standstill trying to finish up a smooth arcade game on Construct 3.
User avatar
Sumez
Posts: 8010
Joined: Fri Feb 18, 2011 10:11 am
Location: Denmarku
Contact:

Re: Help with logic for reusing bullets

Post by Sumez »

I have no experience with Construct 3, so I can't tell what's doable and what isn't in it, but I can share some general knowledge. I apologize if some of it is less relevant within that framework.

As you've learned, when you have a GC around it can cause some overhead if you keep creating and dereferencing objects, so when you're dealing with a massive amount of objects that are constantly replaced, it's definitely not a bad idea to "reuse" them. This is all abstractions though, so what terminology you want to use is less important. The easy solution to give you is that you can go about it however you want, as long as you come up with a solution where you never "new" a bullet object during frame logic. I don't believe there is really one right or wrong way to do this.
Just create the max amount of bullets on the first frame, and let each one know if it's currently active or not.

I last made a shoot'em up engine in 65816 assembly code, so for that I didn't even have to deal with memory allocation at all - everything is in a fixed place in memory, but you can replicate the same idea in high level languages too.

One approach would be to define a struct of a fixed size with every property you'd have for an enemy bullet. For simplicity sake let's settle for just these:
* int: Is active (could double as a "type" or "state" value if you want)
* double: X coordinate
* double: Y coordinate
* double: X velocity
* double: Y velocity

Other values could be things like hitbox size, sprite index, or counters for advanced patterns. I'm sure you already have something defined in your code, but the important thing here is that every bullet takes up the same size in memory, so you don't have to deal with reference pointers all the time, but can directly reference any one property of any specific bullet just by knowing its index.

Then at the start of a level you create a fixed-size array of however many bullets is your maximum. 50, or 5000, or whatever fits your style of game. The downside to this approach is that you need to loop through every single bullet in the array on every frame and update the ones that are active, but the overhead of checking for inactive bullets is probably still much more effecient than referencing new objects and reallocating memory constantly. Whenever a bullet goes off screen or hits something, just set its active status to 0, and whenever something fires a new bullet, find an inactive one and set it to active with the properties of the new bullet.
Finding an inactive bullet to activate is also something that can be optimized around, but I wouldn't bother unless you detect it actually causes a performance issue - it didn't for my SNES shooter.

If Construct 3 doesn't allow you to create fixed size arrays of structs, a simpler solution could be a multidimensional array (so instead of 5000 bullets, you just have an array of 5000 arrays of 5 integers each). If Construct 3 forces an "array" to be a variable size list (like JavaScript and such) the super lo-fi approach would be simply creating a an array for each potential property of a bullet! That's how my assembly code does it, due to the advantages provided with that specific CPU.
Ie. let's say you've looped to bullet #104 you'd check for isActive[104] and then update xCoord[104] and yCoord[104].
Post Reply