9
\$\begingroup\$

I've been working on a tower-defense game for some time now, and so far I am really satisfied with the results. However, there's one thing I'd like to add.

I've seen a video of GeoDefense for Windows Phone 7 here: http://www.youtube.com/watch?v=YhPr4A4LRPQ

Notice how (when a unit gets killed or a projectile hits a unit), the background ripples in some kind of wave effect.

How can I make an equivalent? I'm thinking that I somehow need to do it in the vertex shader, with a quad made of many vertices.

What's your call?

Edit It is important to note that my XNA game is not made for Windows phone, but for Windows PCs.

\$\endgroup\$

1 Answer 1

8
\$\begingroup\$

The problem is that XNA on Windows Phone doesn't have custom shader support - so you can't write a vertex shader or pixel shader. However, you can use a trick described by Catalin Zima that deforms a vertex grid to achieve the same effect.

If you are not targetting Windows Phone 7, you can use a trick that I described on my blog. Copying the relevant bits in:

These distortions require 2 images. Firstly you need the entire scene as a render target (i.e. Texture2D) as well as the distortion render target. Typically you would use a particle system to fill the distortion render target; using special distortion sprites (example below).

Each color component in the distortion target (and distortion sprites) represents the following:

  • R: dx: X offset – f(x)=2x-1 mapping ([0.0f, 1.0f] to [-1.0f, 1.0f]).
  • G: dy: Y offset – f(x)=2x-1 mapping.
  • B: m: Z strength – f(x)=x mapping.

A good example of a sprite that would be used for a ripple would be:

Ripple Sprite

Determining the outcome of a ripple is as simple as adding the waves together (keeping in mind the mapping you need to perform first to [-1.0f, 1.0f]); because waves in reality are also additive this just works - you will get very good approximations of real waves.

Once you have the two render targets you can use the following shader:

Texture InputTexture; // The distortion map.
Texture LastTexture; // The actual rendered scene.

sampler inputTexture = sampler_state
{
    texture = <InputTexture>;
    magFilter = POINT;
    minFilter = POINT;
    mipFilter = POINT;
};

sampler lastTexture = sampler_state
{
    texture = <LastTexture>;
    magFilter = LINEAR;
    minFilter = LINEAR;
    mipFilter = LINEAR;
    addressU = CLAMP;
    addressV = CLAMP;
};

struct VS_OUTPUT
{
    float4 Position : POSITION;
    float2 TexCoords : TEXCOORD0;
};

float4 Distort (VS_OUTPUT Input)
{
    float4 color1;
    float4 color2;
    float2 coords;
    float mul;

    coords = Input.TexCoords;
    color1 = tex2D(inputTexture, coords);

    // 0.1 seems to work nicely.
    mul = (color1.b * 0.1);

    coords.x += (color1.r * mul) - mul / 2;
    coords.y += (color1.g * mul) - mul / 2;

    color2 = tex2D(lastTexture, coords);

    return color2;
}

float4 RunEffects (VS_OUTPUT Input) : COLOR0
{
    float4 color;

    color = Distort(Input);

    return color;
}

technique Main
{
    pass P0
    {
        PixelShader = compile ps_2_0 RunEffects();
    }
}

This is the final effect:

Ripple Effect

This technique should also work for 3D games; although you might have to dedicate more thought to the particle shader and the distortion shader.

\$\endgroup\$
10
  • \$\begingroup\$ I am not making the game for Windows Phone. I've updated my question. \$\endgroup\$ Commented Oct 6, 2011 at 8:36
  • \$\begingroup\$ @MathiasLykkegaardLorenzen I lifted some content off my blog and put it in the answer, hopefully it gives you a good starting point. \$\endgroup\$ Commented Oct 6, 2011 at 9:04
  • \$\begingroup\$ The phone example is nice and is exactly what I am trying to do. Unfortunately, I want the effect to move with the world, and not be based on screen coordinates. Is that possible? \$\endgroup\$ Commented Oct 6, 2011 at 14:42
  • \$\begingroup\$ @MathiasLykkegaardLorenzen It's definitely possible, but it will be incredibly expensive - in which case I recommend you go for my solution. I will mail you the code if I can find it; as long as you promise to not use any of my artwork :). \$\endgroup\$ Commented Oct 6, 2011 at 18:34
  • \$\begingroup\$ @Jonathan Dickinson Could you please provide us with updated XNA 4 code? \$\endgroup\$ Commented Jan 3, 2012 at 21:10

You must log in to answer this question.

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