# How do I create a World Healing Wave effect?

I want to change my dark and depressing background to a happy grassy background, in real-time, such that the happy background is shown in a radius around a game character.

A forcefield of happiness, if you will.

How can this be done as performantly as possible when rendering to a canvas in a custom view?

UPDATE: Here's how it works in my head:

    private int hModeX, hModeY;
private float hModeStart = 0;
happyModeBg = Bitmap.createScaledBitmap(happyModeBg, getWidth(),getHeight(), true);
hModeX = getWidth()/2;
hModeY = getHeight()/2;

private void initHappyMode(Canvas canvas){

hModeStart = timestep; //What is timestep?
}

canvas.save();
canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint) // <- my version
//context.clip(); <- dont know what this does or if there is an equivilant
canvas.drawBitmap(happyModeBg, 0, 0, null);
canvas.restore();
//requestAnimationFrame(step); <- dont know what this does since I cant seem to find it for android

}


I'm using canvas.drawArc() to make a circle, but I'm definitely missing something.

• technically it is called World Healing Wave – ratchet freak Jan 30 '14 at 10:55
• I just use canvas on a custom view run by my own game-loop at 60fps – Green_qaue Jan 30 '14 at 13:55
• Could you render the scene twice? Once for the healed version, once for the dead version, and then draw the healed over the dead in an ever increasing circle until the circle covers the whole screen. – Wolfgang Skyler Jan 30 '14 at 15:09
• Thats kind of what I have been thinking. Just dont know how to go about that with a bitmap. And I thout maybe there is a better way since rendering 2 bgs at once is very costly – Green_qaue Jan 30 '14 at 15:37
• I think I see what the confusion was about -- Android's Canvas does things a little bit differently than the HTML <canvas>, which I thought you meant! I've edited my answer to explain how clipping works in general, with some Android-specific links and example code. – Anko Feb 5 '14 at 11:21

# Demo

GameDev Meta: Henshin Main!! :D

The code uses a canvas clip region and requestAnimationFrame for maximum quality and efficiency. (It's better live.)

I assumed you meant HTML canvas! Even if you didn't, other rendering engines (such as Android's 2D rendering pipeline, which you might have meant) also support hardware-accelerated clip regions. The code will likely look similar.

Requesting animation frames with requestAnimationFrame (or another platform's provided solution) results in higher-quality animation by letting the engine determine render timing.

This renders smoothly on a low-range netbook and on my Android phone.

# Explanation

To make this more generally useful, let's really understand clipping.

Let's say we have these two rectangles:

Clipping works just as well on lines, points, images or anything else you might want to render. I'm just sticking to rectangles for simplicity.

We don't want the red rectangle to be visible here (black circle) at all.

So we can instruct the renderer to clip the red rectangle by that circle.

In other words, when the red rectangle is drawn, it is drawn everywhere except where that black circle would have been.

Different renderers have different ways of specifying what region to clip by. In JavaScript, with the HTML <canvas>, I did essentially

// Draw the blue rectangle

context.save(); // Save the current state of the graphics context,
// so we can go back to it.

// Draw the black circle
context.clip(); // Tell the renderer that was our clip region,
// since the last context.save().

// Draw the red rectangle.
// It will appear clipped by the black circle.

context.restore(); // Tell the renderer we should restore all
// the clipping settings back to what they were
// context.saved as.

// From here on, nothing is clipped anymore.


Now, in an Android Canvas, you'll want to be doing a similar thing, but the renderer expects slightly different code:

// Draw the blue rectangle

canvas.save(); // Same idea as above -- just setting a point we can
// restore to later.

// Now, canvas.clipPath expects a Path object.
// Let's create one that contains a circle.
Path path = new Path();
canvas.clipPath(path);

// Draw the red rectangle
// It will be clipped by the circle defined in the path that we
// used as the clipPath.

canvas.restore(); // Aaaand restore the state.

// Things drawn here won't be clipped anymore.


Android documentation on the matter might be handy. There are good questions like this one on StackOverflow about more things you might want to try with it.

Working implementation using Ankos method:

canvas.drawBitmap(depressingBg, 0, 0, null);
canvas.save();