Weird Behavior with Canvas.clear()

28 views
Skip to first unread message

Scott Le Grand

unread,
Jan 8, 2012, 9:10:09 PM1/8/12
to pl...@googlegroups.com
If my gameLoop implements the following update and paint methods:

@Override
    public void init() {
        gameLayer = graphics().createCanvasLayer(graphics().width(), graphics().height());
        graphics().rootLayer().add(gameLayer);
    }

    @Override
    public void paint(float alpha) {
        Canvas canvas = gameLayer.canvas();
        canvas.clear();
        canvas.setFillColor(0x01ff0000);
        canvas.fillRect(0, 0, canvas.width(), canvas.height());
    }

Instead of seeing a constant very faint red with a near-transparent alpha specified, I instead see the screen go gradually from grey to pink.  Obviously, I'm messing up compositing somehow.  But calling:

canvas.setCompositeOperation(Canvas.Composite.SRC); does not seem to change this at all.

Paradoxically, if I don't call canvas.clear, nothing appears whatsoever which would make sense if I'm doing some sort of blend operation instead of allowing source to replace destination data.

So I'm confused.  What exactly is canvas.clear() doing because it doesn't seem like it's doing the obvious thing?

Matt Mastracci

unread,
Jan 8, 2012, 11:16:09 PM1/8/12
to pl...@googlegroups.com

I think this is a bug in JavaCanvas.clear(): it calls clearRect without setting the fill color beforehand. I've got some fixes in this area- if you file a bug I can try to sneak a fix in with them.

As a workaround, you should be able to use fillRect with the appropriate composite operation.

Matt Mastracci

unread,
Jan 9, 2012, 12:36:03 AM1/9/12
to pl...@googlegroups.com
Looking into this further it turns out that this is issue 115: http://code.google.com/p/playn/issues/detail?id=115

You can apply the patch in that issue to fix the problem. As a workaround, you can also add a canvas layer filled with an opaque solid color to your root layer as the hindmost layer. This will ensure that the Java platform correctly wipes the old frame when painting the new one. The patch to fix this problem should land sometime in the next few days.
Matt Mastracci
Twitter@mmastrac
Bloggrack.com

Scott Le Grand

unread,
Jan 12, 2012, 10:54:04 AM1/12/12
to PlayN
I think I'll stick with fillRect. I actually *like* the ability to do
additive blending without a clear between frames now that I know
what's happening. That's a port from which a thousand music
visualizers were launched. So whatever fix you make, please don't
destroy the ability to do this entirely :-)...

Scott

On Jan 8, 9:36 pm, Matt Mastracci <matt...@mastracci.com> wrote:
> Looking into this further it turns out that this is issue 115:http://code.google.com/p/playn/issues/detail?id=115
>
> You can apply the patch in that issue to fix the problem. As a workaround, you can also add a canvas layer filled with an opaque solid color to your root layer as the hindmost layer. This will ensure that the Java platform correctly wipes the old frame when painting the new one. The patch to fix this problem should land sometime in the next few days.
>
> On 2012-01-08, at 9:16 PM, Matt Mastracci wrote:
>
>
>
>
>
>
>
>
>
> > I think this is a bug in JavaCanvas.clear(): it calls clearRect without setting the fill color beforehand. I've got some fixes in this area- if you file a bug I can try to sneak a fix in with them.
>
> > As a workaround, you should be able to use fillRect with the appropriate composite operation.
>
> > On Jan 8, 2012 7:10 PM, "Scott Le Grand" <varelse2...@gmail.com> wrote:
> > If my gameLoop implements the following update and paint methods:
>
> > @Override
> >     public void init() {
> >         gameLayer = graphics().createCanvasLayer(graphics().width(), graphics().height());
> >         graphics().rootLayer().add(gameLayer);
> >     }
>
> >     @Override
> >     public void paint(float alpha) {
> >         Canvas canvas = gameLayer.canvas();
> >         canvas.clear();
> >         canvas.setFillColor(0x01ff0000);
> >         canvas.fillRect(0, 0, canvas.width(), canvas.height());
> >     }
>
> > Instead of seeing a constant very faint red with a near-transparent alpha specified, I instead see the screen go gradually from grey to pink.  Obviously, I'm messing up compositing somehow.  But calling:
>
> > canvas.setCompositeOperation(Canvas.Composite.SRC); does not seem to change this at all.
>
> > Paradoxically, if I don't call canvas.clear, nothing appears whatsoever which would make sense if I'm doing some sort of blend operation instead of allowing source to replace destination data.
>
> > So I'm confused.  What exactly is canvas.clear() doing because it doesn't seem like it's doing the obvious thing?
>
> Matt Mastracci
> matt...@mastracci.com
> Twitter: @mmastrac
> Blog: grack.com

Matt Mastracci

unread,
Jan 12, 2012, 11:50:24 AM1/12/12
to pl...@googlegroups.com
The fix is in the latest HEAD of the PlayN repo now.

The problem with the old behaviour is that it was specific to the Java platform and not at all portable to the other platforms that use layers natively (DOM and Flash). You can, however, reproduce the same previous-frame-blending by drawing shapes and images manually to a full-sized CanvasImage in an ImageLayer and not clearing it fully between frames.
Reply all
Reply to author
Forward
0 new messages