# Creating similar effects of Geometry Wars in 2D only

I want to create a game with similar effects to that of "Geometry Wars"... for those who have never played the game, basically, massive amounts of 'bending' and 'warping' effects are done on the background during explosions and pulses.

Here is a picture:

The grid is normally a bunch of squares (perfect squares) in a perfect grid. When certain effects happen, the grid stretches and creates amazing effects.

Now, I'm trying to create a game using my own, from scratch, 2D engine. Is it possible to fake 3D effects such as this to my sprites? Is there some kind of effect I could do to do this?

-
When you say "2D engine" do you mean something sitting on top of e.g. OpenGL but rendering an orthogonal projection? Or something pushing bytes around in a framebuffer like an SDL Surface? – user744 Sep 5 '11 at 3:41

I implemented this using a very simple physics system in Flash about 5 years ago.

From memory:

## Basic Structure

The grid is an intangible background layer. It can be affected by other physical items, but cannot affect them.

Every physical entity has a "gravity warp" factor. Blackholes are strongly negative (they pull the grid towards them), bullets are slightly positive (they push the grid away from them), the ship is Strong positive, etc.

The background grid can be considered a series of lines connected by a square grid of nodes at the joints. These nodes have a known orignalPostion, a resistance value (for spring physics), and of course their current position and velocity.

## The Nodes

Once per pass (typically once per frame for smooth results), for each physical entity that has a non-zero gravity warp (I used a registration/deregistration on spawn/death system to prevent extraneous iterations), for each of the nodes that are within a given radius of effect, calculate their pull by a simple formula such as `PullVector = NormalisedDirection * gravityWarpFactor / (Distance*Distance)`
Where:
`NormalisedDirection` is a normalised vector (magnitude = 1) indicating the position of the object relative to the node.
`gravityWarpFactor` is the previously mentioned Gravity Warp unique to each type of entity `Distance` is the scalar distance between the node and the entity.

By sum of all pull vectors on a given node by all nearby entities will give you the overall force being exerted upon it.

Then, for each node, you can use basic spring physics to move them from their current position in the direction they are being pulled, while providing resistance. They WANT to return to their original position, but constant force can pull them away. (Like tugging on a rubber band)

## The Grid

Once you've calculated the position of each node, you can render the lines connected them to their neighbours. In flash, I made a simple linear connection to each adjacent node, but you can go fancy if you want and connect them via bezier curves to their 2nd neighbour, using the immediate neighbour as a control point.

## Going Fancy

As I mentioned before, you don't have to be linear with the grid lines. Splines and beziers can be very cool.

Also, if you look at the lines in Geometry Wars, you see that they alternative between thick and thin lines. This can be implemented by adding a 'thickness' property to each node, and for the lines drawn between them, choose either the higher or the lower of the two nodes' thickness values to determine the weight of the line.

Alternatively, if you wanted to go really fancy and get a comic-book style inking look, you could create an uneven line that graduates its thickness as it approaches the node.

One final thing which I did, which really lends extra impact to the gravity warp's visual effect is to alter the left/right speaker balance based on where the nodes are clustering. A simple way of doing this is to work out the average X value of the node's current position, compared with the average X value of the node's original position (which in most cases will be the centre of the screen). Whether the average is higher or lower than the original will tell you if the nodes are clustering to the left or right sides of the screen.

-