I don't know exactly how ZUN coded the bullets, but I managed to create an equivalent algorithm with XNA.
Here is what I used:
>A class hierarchy for different types of shots. Each type of shot defines the AMOUNT (not the types) of data needed to achieve a certain behavior. This trims down unnecessary memory usages and enforces consistent behaviors
>Flyweight Pattern.
>Instanced Mesh Rendering. Yes, I know that XNA has SpriteBatch, but I wanted to make the bullets be models rather than sprites so I can do some 3D camera tricks.
>A kind of Visitor Pattern that works around the need of using virtual methods on the bullet Flyweight classes. Virtual methods aren't as bad in C# as they are in C++, but the optimization is noticeable
>CPU Budget. If the application is running at 60 fps, the Update methods of the bullets only actually update half of the bullet instances per frame and the other half on the other frame.
>Loop unrolling and avoid using LINQ (since I'm using C#) or foreach loops. Unrolled for loops can go a long way!
>Sweep and Prune broadphase for the collision detection. Per-Pixel collision in the narrowphase for odd-shaped bullets.
>Pre-allocations galore. Pre-allocating all you can is specially mandatory in C# applications, but it can help a bit on C++
>Use C#, because using pre-allocated Reference Types is absolute master race over dealing with all this pointer bullshit
On my machine, this algorithm can deal with over 100 bullets on the screen at around 660 fps.
As for the bullet patterns, they are implemented in a hard-coded fashion. But I can just use IronPython to get a Python script, compile it and run it on C# levels of performance.
Also, I don't think need any overly complicated collision detection mechanism. Just attach simple shapes to your bullets and only do circle vs circle collisions, even for lasers. You can arrange your shapes in a hierarchy so your crescent moon bullet will have 20 circles to define the crescent shape and one circle to define the bounding ``box''.
there are n bullets and you have to do O(n) tests to see if any bullet hit the player. there's no speed up you can do.
it's only if the n bullets can interact with each other that that you can speed things up from O(n^2) using buckets
Name:
Anonymous2013-06-22 10:20
>>6 there are n bullets and you have to do O(n) tests to see if any bullet hit the player. there's no speed up you can do.
you can always do monte carlo integration with voronoi dias.
pre-emptive collision detection?
somewhere along the lines of the robo-code wave-riding system?
Name:
Anonymous2013-06-22 22:15
except you know where the bullets are heading in this case =)
ie, if a bullet is not heading towards a target.. no need to test for collisions... if the bullet is heading towards a target, but the target cannot move fast enough to get into the trajectory, no collision, and if cannot move fast enough to get out of the trajectory, collision... etc?
The other day I came across Shadow Warrior, that game from 1997. On my laptop it runs at well over 1000 fps, and that includes rendering everything at 1920x1080, and it sure as hell is drawing more than 100 things at once. Seeing that it can do all of that in under a millisecond is a bit eerie actually. I wonder where we went wrong.
Name:
Anonymous2013-06-23 2:45
>>11 jp stop shitting it
Japanese is shit by definition.