38
\$\begingroup\$

I'm currently making a game with my own game engine which I've written in C++ and I'm using the most recent directx SDK.

The game is a top down space shooter (with a pretty interesting twist) and I'm looking to have a sort of nebula effect that the player will fly through. I really want to try and nail that nice tactile feel of hundreds of particles moving out of the way of the player ship as it flies into them. Somewhat like how particles would move out the way of the player in Geomtry Wars on XBLA.

I'm an experienced programmer when it comes to C++. I don't know, however, how to start implementing this effect. Does anyone have any cool ideas or design choices I might want to look into? Feel free to answer to any degree of depth you fancy.

\$\endgroup\$

1 Answer 1

65
\$\begingroup\$

It's a cool idea. You'd need some sort of diffusion gradient around your ship. There are three physical models I can think of that you might want:

  1. You want it to seem almost like it's a liquid medium, where the pressure gradient rebalances, i.e. once you've passed some particles, they move back into your wake (like water behind a boat). In this instance, the particle's positions are absolute, and it's only their relation to the player which temporarily modifies their rendering position. This is a bit like when you pass a thick magnifying glass over things, and the diffraction seems to make them move — but only until you move the glass away. In this case, your ship is the glass.

  2. If you want them to move away from the ship, and continue moving once they've moved. This is like standard physics in generally empty space where there are no (or very small) pressure gradients.

  3. You want to move the particles away from the ship swiftly as it approaches, as in (1) and (2), but once the ship is gone, the particles will slowly re-balance themselves to be equidistant in your wake.

Common to all three solutions: you need to have a diffusion field that moves with your ship. In this example, we'll make it circular. You then detect vector — call it v1 — between the ship and each particle within that region. Push your particle away along that vector. How strongly you'll push it away will depend on its distance from the ship: use 1 - v1.magnitude. This formula will give you a linear strength, however you could modify it to use something else like a circular strength curve that diminishes in strength toward the edges. This would give it more of a look as though there's a spherical rather than circular pressure gradient around the ship.

For solution 1: All you now do is modify the render position of that particle (that is, the sprite position) on every render update, by this vector. Because you're doing it this way, this is purely a rendering effect and has no effect on the particle's actual world position. So you add the world position to the render offset (v1) and you now have nicely displaced particles as you move past, toward or beside them, and smoothly reverting particles as you pass by (behind you).

For solution 2: Instead of just applying v1 to the view position, apply it on each logic update, to the particle's position. So, p1.position += v1. So you're applying an accelerative force to the particle, which translates into velocity. You'll probably want each particle's velocity to be dampened, so that they they'll gradually slow down and come to a halt once you've passed. You can see how this solution will result in bunched-up particles in your nebula because they'll never re-diffuse. Not very realistic, I'm sure, since nebulae have pressure gradients within them, no matter how weak in reality.

For solution 3: Same as (2), but in this case you're going to have to re-diffuse your particles. To do this easily is a bit of a brute-force approach, but since these are only particles and thus eye-candy, you probably don't need to cover a huge area of interest (probably only a radius of playerPosition + maxPlayerSpeedPerTick, or whatever rectangular area circumscribes that, for logic purposes). Each particle will apply a force on each other particle within the area of interest. They'll apply forces based, once again, on their distances from one another. Calculate all inter-particle forces in a single sweep across the area of interest and then apply all the forces in a single sweep. Lastly, make sure that you only perform this inter-particle force processing on particles that have zero velocity. And once any given particle reaches some minimum speed, cut it's velocity vector to zero, so that it's no longer using up processor time.

There are all kinds of diffusion formulae, etc., out there, but I think in this case, a simple solution works best.

\$\endgroup\$
3
  • \$\begingroup\$ Mate, unfortunately I don't currently have the reputation to upvote your answer (and I'd only be able to do it once, which is less than it deserves). You absolutely nailed what I'm looking for in your first solution. Fantastic answer. Honestly. Thanks! \$\endgroup\$ Commented Sep 1, 2011 at 10:29
  • \$\begingroup\$ Total pleasure Matt, it's a good question & worth flexing the brain for! \$\endgroup\$
    – Engineer
    Commented Sep 1, 2011 at 10:30
  • \$\begingroup\$ I've also decided that with very little change in code I could have this apply to smaller asteroids within a belt. Thanks again. \$\endgroup\$ Commented Sep 1, 2011 at 10:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .