Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I was developing tower of defence game for a long time. It was about to complete but I have to create ripple effect for one of the weapon that I have used.

First question I want to ask is that is it feasible to use ripple effect for such purpose? Because suddenly fps goes down.

I have created ripple effect for live wallpaper. But I don't know how to create it for normal game activity.

I was not able to understand many things from it. If any one has some knowledge on this then please provide.

Edit : I include the image for ripple effect that I think I have to use for weapon fire.enter image description here

Also I include code that I use to create ripple effect. Similar code with some changes I used to create live wallpaper and it work perfectly. But in normal game activity I don't able to find my mistake. So please guide on this

public Engine onCreateEngine(EngineOptions pEngineOptions) {

    return new org.andengine.engine.Engine(pEngineOptions) {
        private boolean mRenderTextureInitialized;

        private RenderTexture mRenderTexture;
        private UncoloredSprite mRenderTextureSprite;

        public void onDrawFrame(final GLState pGLState)
                throws InterruptedException {
            final boolean firstFrame = !this.mRenderTextureInitialized;

            if (firstFrame) {
                this.mRenderTextureInitialized = true;

            final int surfaceWidth = this.mCamera.getSurfaceWidth();
            final int surfaceHeight = this.mCamera.getSurfaceHeight();

                /* Draw current frame. */

            /* Draw rendered texture with custom shader. */
                pGLState.orthoProjectionGLMatrixf(0, surfaceWidth, 0,
                        surfaceHeight, -1, 1);
                            .onDraw(pGLState, this.mCamera);

        private void initRenderTextures(final GLState pGLState) {
            final int surfaceWidth = this.mCamera.getSurfaceWidth();
            final int surfaceHeight = this.mCamera.getSurfaceHeight();

            this.mRenderTexture = new RenderTexture(RippleEffectDemo.this
                    .getEngine().getTextureManager(), surfaceWidth,

            final ITextureRegion renderTextureTextureRegion = TextureRegionFactory
            this.mRenderTextureSprite = new UncoloredSprite(0, 0,
                    renderTextureTextureRegion, RippleEffectDemo.this
                            .getEngine().getVertexBufferObjectManager()) {

                protected void preDraw(final GLState pGLState,
                        final Camera pCamera) {


                    super.preDraw(pGLState, pCamera);

                    if (mCurrentWaveLength > 25)
                        mCurrentWaveLength -= 25;
                        mCurrentWaveLength = 0;

                    float currentTime = -0.001f * mCurrentWaveLength;
                    float aliveTimer = (float) mCurrentWaveLength
                            / (float) mWaveLength;

                            (float) SCREEN_WIDTH, (float) SCREEN_HEIGHT,
                            currentTime, aliveTimer);

public void onCreateResources() {
    this.mBitmapTextureAtlas = new BitmapTextureAtlas(
            this.getTextureManager(), 512, 512);
    this.mBackgroundTextureRegion = BitmapTextureAtlasTextureRegionFactory
            .createFromAsset(this.mBitmapTextureAtlas, this,
                    "badge_large.png", 0, 0);


public Scene onCreateScene() {
    final Scene scene = new Scene();

    final int centerX = (int) ((CAMERA_WIDTH - this.mBackgroundTextureRegion
            .getWidth()) / 2);
    final int centerY = (int) ((CAMERA_HEIGHT - this.mBackgroundTextureRegion
            .getHeight()) / 2);

    backgroundSprite = new Sprite(centerX, centerY,
            this.mBackgroundTextureRegion, this.getEngine()


    return scene;

protected void onTap(final int pX, final int pY) {
    // we do not support multiple wave
    if (0 == mCurrentWaveLength) {
        // so skip wave, if it is active
        mCurrentWaveLength = mWaveLength;

        this.mDropCenterX = (float) pX;
        this.mDropCenterY = (float) pY;

public void onClick(final ClickDetector pClickDetector,
        final int pPointerID, final float pSceneX, final float pSceneY) {

public boolean onSceneTouchEvent(final Scene pScene,
        final TouchEvent pSceneTouchEvent) {

    if (pSceneTouchEvent.isActionDown()) {
        onTap((int) pSceneTouchEvent.getX(), (int) pSceneTouchEvent.getY());
        return true;

    this.mDropCenterX = pSceneTouchEvent.getMotionEvent().getX()
            / this.mCamera.getSurfaceWidth();
    this.mDropCenterY = pSceneTouchEvent.getMotionEvent().getY()
            / this.mCamera.getSurfaceHeight();

    return true;

public static class RippleShaderProgram extends ShaderProgram {
    private static RippleShaderProgram INSTANCE;

    public static final String VERTEXSHADER = "uniform mat4 "
            + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX
            + ";\n" + "attribute vec4 "
            + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n"
            + "attribute vec2 "
            + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n"
            + "varying vec2 "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n"
            + "void main() {\n" + " "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + " = "
            + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n"
            + " gl_Position = "
            + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX
            + " * " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n"
            + "}";

    // private static final String UNIFORM_TOUCH_COORDS = "touchCoords";
    private static final String UNIFORM_RESOLUTION = "resolution";
    private static final String UNIFORM_TIME = "time";

    public static final String FRAGMENTSHADER = "precision mediump float;\n"

            "uniform sampler2D "
            + ShaderProgramConstants.UNIFORM_TEXTURE_0
            + ";\n"
            + "varying mediump vec2 "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES
            + ";\n"
            + "uniform vec4 "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ";\n"
            + "uniform vec2 "
            + RippleShaderProgram.UNIFORM_TIME
            + ";\n"

            "void main() {\n"
            + " vec2 tap = "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".zw;\n"
            + " tap.x = "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".x - tap.x;\n"
            + " vec2 tPos = -1.0 + 2.0 * tap.xy / "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy;\n"
            + " vec2 cPos = -1.0 + 2.0 * gl_FragCoord.xy / "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy;\n"
            + " cPos = cPos + tPos;\n"
            + " float cLength = length(cPos);\n"
            + " float radius = 18.0 * "
            + RippleShaderProgram.UNIFORM_TIME
            + ".y;\n"
            + " float amplitude = 0.05 * "
            + RippleShaderProgram.UNIFORM_TIME
            + ".y;\n"
            + " vec2 uv = gl_FragCoord.xy/"
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy"
            + "+(cPos/cLength)*cos(cLength*radius-"
            + RippleShaderProgram.UNIFORM_TIME
            + ".x *4.0)*amplitude;\n"
            + " vec3 col = texture2D("
            + ShaderProgramConstants.UNIFORM_TEXTURE_0
            + ",uv).xyz;\n"
            + " gl_FragColor = vec4(col,1.0); \n" + // color


    // ===========================================================
    // Fields
    // ===========================================================

    public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformResolution = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformTime = ShaderProgramConstants.LOCATION_INVALID;

    // ===========================================================
    // Constructors
    // ===========================================================

    private RippleShaderProgram() {

    public static RippleShaderProgram getInstance() {
        if (RippleShaderProgram.INSTANCE == null) {
            RippleShaderProgram.INSTANCE = new RippleShaderProgram();
        return RippleShaderProgram.INSTANCE;

    protected void link(final GLState pGLState)
            throws ShaderProgramLinkException {

        RippleShaderProgram.sUniformModelViewPositionMatrixLocation = this
        RippleShaderProgram.sUniformTexture0Location = this

        RippleShaderProgram.sUniformResolution = this
        RippleShaderProgram.sUniformTime = this

    public void bind(final GLState pGLState,
            final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {

        super.bind(pGLState, pVertexBufferObjectAttributes);

                1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
        GLES20.glUniform1i(RippleShaderProgram.sUniformTexture0Location, 0);

    public void unbind(final GLState pGLState)
            throws ShaderProgramException {

share|improve this question
Can you show an example picture of how this ripple effect looks in game? – bobobobo Feb 8 '13 at 13:43
No this is not pre decided. I want to create effect something like earthquake created by weapon in some radius. – Siddharth Feb 8 '13 at 16:30
@Siddharth How can we help explain how to implement an effect (ie. visualisation) of something without knowing what you decided it looks like? – AbstractChaos Feb 8 '13 at 17:01
@Siddharth It is not clear from the question what a "ripple effect" is. Voting to close. – bobobobo Feb 8 '13 at 22:22
I edited my question with more detail. So please help me to achieve that effect. I was looking for another source also. So I found any solution that definitely reply here. – Siddharth Feb 9 '13 at 14:04

The "ripple" effect you are showing is just a radial sinewave: sin(t), where t is the distance from some center.

enter image description here

Image from here

Doing this kind of deformation in a vertex or pixel shader is easy: just set up the center of the wave as a uniform variable waveCenter, then move every vertex in z (where z is the "up" direction) by MAGNITUDE*sin( FREQUENCY*t ), where t is the distance the vertex has from that waveCenter. FREQUENCY is how fast you want the wave to ripple. You can even make the wave fade out by dividing MAGNITUDE by the distance from the waveCenter.

share|improve this answer
Thanks for your suggestion. This information become useful to me but I can't figure out for working code. So please give some more info on this. I need to create working code. – Siddharth Feb 10 '13 at 15:31
6 "The problem is that this person’s problem-solving technique is to ask for the solution [...] to just ask for the code, fully formed and ready to go. This is not problem solving ..." Sid: I am sorry but I don't think anyone will "create you the working code" without knowing anything about your game. I know it is probably difficult to write your question in English. But maybe you can ask some small, specific questions about the wallpaper code you are starting with? You will get a lot more answers that way. – Mediocritus Feb 14 '13 at 8:27
Thanks for your suggestion but I have already created working live wallpaper which has ripple effect. My question is how to port it for game that work with weapon. You can consider this type of game I am currently developing….. Also this thing not only help for me but lots of other developers save their time. I found whatever new I post it here. – Siddharth Feb 14 '13 at 13:37
The modification in shader is difficult for me and I don't able to understand how to use this concept. I have to say this thing because so many people up voted it but I can't understand.So please forgive me for I don't make it correct. – Siddharth Feb 21 '13 at 4:00
up vote 0 down vote accepted

After hard working I found working code for the ripple effect. I have to say thanks to genius guy named thepi for his effort. The link for correct working code :

I here posted because I think lot other user can get benefit from it and also want to say thank to the people who have tried for this.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.