Particles + Physics = Particle Physics? Not Quite But It's Still Pretty Cool
Posted by Tony Nov 18, 2014
So now that we have implemented Barrage in the most basic manner possible, let's take a look at adding some new functionality. Particle effects are great for graphic-only effects that do not interact with game play, but with a few tweaks we can change that. Using a physics engine for in-game bullets will quickly add a boatload of functionality. A physics engine can bring collision detection, ricochet effects, allow us to push objects around, and more. This isn't a trivial decision though because no matter how Barrage and Nape (a 2d physics engine) are merged together there will be drawbacks. What I'm getting at here is that there is no single correct implementation, so instead the focus will be on exploring different solutions to see what can be accomplished.
This Article Covers The Following:
- Integrating Nape into the initial Barrage project
- Integration decisions involving Barrage and Nape
- Allowing Barrage to control the bullets
- Allowing Nape to control the bullets
The details of the Nape implementation are not explained within this article. If you are completely new to using a physics engine then reading up on the Nape manual will be very helpful. You don't need to fully understand what Nape is doing, but it's important to understand there are conflicting forces acting on the particles and that we must take precaution when dealing with them to get a desired result.
Integrating Nape into the Initial Barrage Project
Integrating a physics engine with Barrage is difficult because both Barrage and Nape want to govern a bullet's velocity and acceleration. This becomes an issue when Barrage and Nape want to move a bullet differently, so we will focus on how to handle those situations.
|Nape||The starting position must be set, but modifying position directly in nape is not a recommended practice.||Initial velocity is set, and velocity is allowed to be changed at anytime but we need to be aware of when the physics engine will try and change velocity (or else we may override they physics engine value).||Impulses, gravity and friction get applied to objects, all of which directly modify the current velocity.|
|Barrage||The starting position must be set, but modifying position directly in nape is not a recommended practice.||Initial velocity is set, but a Barrage script could change velocity at anytime (by directly setting speed) if we want to support instant velocity changes we need to be careful.||Acceleration is added each time step to the current velocity. This doesn't have any special use cases.|
|Who Controls It?||
Nape Position must be controlled by Nape because if a physics simulation is running it needs to control the particle's final position.
Nape or Barrage Depends on what you want to do.
Nape or Barrage Depends on what you want to do.
The main thing to keep in mind is that are a set of properties that both Barrage and Nape want to control at the same time so we need to specifically define what will happen for each shared interaction. In each case we have some sort of acceleration that will be applied to a particle's velocity and then the particle's velocity will determine where the particle moves next. The specifics of who controls what will be explained in detail further in the article.
Modifying the Particle
You may remember that the particle is simply a data structure with values that will be manipulated by the particle system. This relationship between the particle and physics engine is exactly the same. The particle holds some values and the physics engine modifies them.
The changes we made are to add a Body to the bullet which contains all of the necessary properties that an object needs to participate in a physics simulation. You can see that we initialize the starting position and velocity exactly the same way as before.
Modifying the Particle Engine
The particle engine needs to be aware of the physics simulation known as the Nape Space. The Space will be used to attach new bullets to the physics world.
The update() function is where things get a bit complicated. This is where we will have to make our decisions on who will control a bullet's velocity and acceleration; Barrage or Nape. The changes for the update() function involve keeping the Nape properties in sync with the Barrage properties. We are using the Haxe definition (similar to a #define in C) TEST_NAPE_CONTROLS_VELOCITY in order to choose who will control velocity.
Modifying the Periodic Updates
Now that we have made changes for both the particle and particle system we need to make some additional modifications to initialize the physics world and properly update it each frame.
A nice feature of Nape is the built-in debug graphics which will be used to test out bullet collisions. The new additions here are the creation of the Nape Space which is the back end for the physics simulation and the debug object which allows us to visualize things without specifically adding graphics. The details for the Nape objects are explained very well in the Nape manual and I encourage you to read up a bit on Nape if it's unfamiliar. The documentation is a fun read and the examples are awesome, can't say enough good things about Nape.
Nape Specific Changes
Nape uses interaction groups and masks in order to determine if two or more objects will interact. This works by assigning a base type and a collection of all the other interaction types to a physics body. Some constants were created to determine the desired Nape interactions.
By defining the Nape interactions this way we can easily change them in the future to modify functionality. Maybe we want to allow bullets to collide with another, if so, we would modify COLLISION_MASK_BULLET from COLLISION_GROUP_STATIC to COLLISION_GROUP_STATIC | COLLISION_GROUP_BULLET.
Testing Nape and Barrage Integration
So the code is now in place, after running the Flashdevelop project in github you should see the following. Bullets are only allowed to collide with the randomly scattered objects and on collision the bullets do not change course because Barrage is controlling the velocity and not Nape. Nape is trying to modify the bullet's velocity because it detected a collision but in our update() function of the particle system we are setting velocity directly from Barrage essentially overriding Nape.
Barrage in Control
When Barrage controls velocity notice that when a bullet collides with an object it appears to stick to the object. This is because Barrage has no knowledge that the bullet has hit an object. Nape is honoring the collision between the bullet and the object by not allowing it to pass but Barrage is not informed. Hence, the bullet's path does not change and the bullet appears to hug the objects.
(Building with TEST_NAPE_CONTROLS_VELOCITY off to allow Barrage to control particle velocity)
Nape in Control
When Nape controls velocity notice that when a bullet collides with an object it bounces off the object and takes a new trajectory. This is because Nape applies an impulse to the bullet which directly modifies the bullets velocity. This implementation allows Barrage to control the acceleration of the bullet while allowing the bullet to bounce around the physics world. Also, watch the inchworm pattern and notice that it no longer crawls along, this is because the pattern relies on instantaneous velocity changes controlled by Barrage. Nape is overriding this behavior so with this method we essentially lose some of Barrage's intended functionality.
(Building with TEST_NAPE_CONTROLS_VELOCITY on to allow Nape to control particle velocity)
Barrage and Nape are integrated and running together, but they are not cooperating all that well. In the next article we will explore use cases for using Barrage and Nape together for a number of desired outcomes. Stay tuned!
Xenizo Games Lead Developer