Nape and Barrage Integration for Bullet Collision and Ricochet
Posted by Tony Dec 01, 2014
After the last article, Nape and Barrage are integrated and running together, but we still have a few issues -- Mainly that both Nape and Barrage want full control over a bullet's properties, and of course only one can win.
Nape Physics and Barrage Bullet Governor Control Issues
Integrating Nape and Barrage together resulted in control issues depending on which was allowed to dominate. To summarize where we are at, both methods and their drawbacks are listed below.
Who's in control?
- Nape - Resulted in loss of Barrage functionality, the inchworm pattern no longer crawled along.
- Barrage - Nape collisions were honored but bullets hugged objects.
Putting Nape in control makes more sense because it defines how the bullets should interact with the world. If you don't care about the bullets interacting with the world, then the initial Barrage implementation is a great solution. In this case though, Nape is here to stay and we need to teach Barrage to bend a bit without breaking. The starting point for the following solutions is Nape has full control over a bullet's velocity but will also allow Barrage to give input for how the bullet should move. A few key rules define what needs to happen here.
Solution 1 - Rules to make Barrage and Nape play nice
The first implementation will restore the Barrage functionality that we lost. Mainly we stopped supporting instant velocity changes once Nape took over. This solution brings back that Barrage functionality.
- Nape may change a bullet's path if a collision occurs
- Barrage may change a bullet's velocity, speed or direction at any time
Quick and Dirty Flowchart showing Nape and Barrage collaboration for solution 1 - ricochet
Code Changes Required
This implementation is nice because it's very simple. Here Nape has full control of a bullet's properties while also allowing Barrage to instantaneously change a bullet's speed or direction at any time. It's worth noting that a situation where a collision and a Barrage modification could occur at the same time. This means that not all bullet behavior is explicitly defined. Although the behavior is technically undefined, the resulting simulation still works out really well, and is a much cleaner than the original implementation in the previous blog post. If you like the bullets bouncing off objects and are not concerned with collision interactions, then this solution will fit your needs.
The changes here are minor. We modify the instant speed and direction changes to directly change the Nape physics' body velocity. By doing so, we re-enable the lost Barrage functionality easily recognizable by the inchworm example.
Here the #define to give Nape control of the bullet is removed and chosen as the default solution. This change doesn't need to be made -- it's just a bit of clean up since we chose to give Nape full control. As you can see the emitter's update() function is made as simple as possible. Another modification is that the IBullet and IBulletEmitter interface were simplified
Solution 2 - Some Different Rules to make Barrage and Nape play nice
The second implementation merely modifies the first rule. Instead of allowing a ricochet to occur we will instead allow Nape to remove the bullet from the simulation as well as from the Barrage particle pattern.
- Nape may remove a bullet from the pattern if a collision occurs
- Barrage may change a bullets instant velocity, speed or direction at any time
Quick and Dirty Flowchart showing Nape and Barrage collaboration for solution 2 - collision
Code Changes Required
This implementation requires the code changes from the first solution plus some extra work.
- Listen for bullet-to-object collisions.
- Remove the bullet from the simulation, emitter, and Barrage controller.
Two major changes take place for our particle class.
- Add a type to the bullet, essentially letting Nape know "Yeah this is a bullet" so that we can set up a collision listener.
- Add a state to the bullet so it knows a collision has occurred
Adding a state to the bullet is not an ideal solution. This is a temporary fix until we can dig deeper into the Barrage core and integrate the bullet removal methods to satisfy Nape and Barrage. The reason for this is that the Barrage data structures are not properly updated if some outside source (in this case Nape) removes a bullet from the particle pattern and can result in null references (run time errors) if not properly handled. That will be saved for a future article.
The state is added with
private var _collision:Bool; and the bullet type is added with
The last addition to the particle class is user data that we dynamically add to the Nape body in order to create a link between the physics body and Particle class (MiniParticle.hx). This allows us to perform a reverse lookup after a Nape collision occurs and properly remove the bullet involved
body.userData.bullet = this;.
None! No additional emitter changes are required. Phew!
In our main file we need to add the Nape listener to handle what happens after a collision occurs. The order of parameters is very important as it will define which physics body will be used in the callback for the Interaction Listener. One thing to be careful with when removing bodies from a Nape Space is when to remove the body. There are listener types where removing a Nape body can cause errors in the physics simulation, but we are safe to remove bodies in the Interaction Listener.
InteractionListeners handle events associated with a pair of Interactor objects (Shapes, Compounds, Bodies). These callbacks occur at the end of a space.step() call, and so you are free to do whatever you wish.
After a collision occurs the Emitter
kill() function is used to remove the bullet from the physics simulation and bullet pattern visuals. The bullet state changes once the
kill() function is called and this protects the particle from being re-used with bad data.
As always the source code with a running FlashDevelop project is included in the github repo linked below.
At this point many of the Nape and Barrage integration details have been handled. We now have a chunk of code that generates bullet patterns and supports physics-based bullet interactions. Next up is optimizing the Barrage internals to further the Nape and Barrage integration. Haxe macros will be used to parse the Barrage scripts at compile-time (vs. run-time) and new Bullet patterns will be created. That's the plan so far, but suggestions are always welcome. If there is anything in particular you would like to see, shoot me a line and I'll post something related. We are still in the guts of the code and just getting things to work, but don't worry this will pay off and soon we can start reaping the benefits by creating more of those coveted "ooh" and "ahh" type effects.
Xenizo Games Lead Developer