Search code examples
playn

In PlayN, how do I create a transparent CanvasImage?


I wrote a simple example that I expected would do it. The relevant code is pasted below, complete source available here.

First, the method of my game class that draws three circles as canvas images using the asCanvasImage method on my Circle class:

public void drawThreeTransparentCircles() {
    // create an immediate layer and add to root layer
    ImmediateLayer circleLayer = graphics().createImmediateLayer(
            new ImmediateLayer.Renderer() {
                public void render(Surface surf) {
                    Circle redCircle = new Circle(-25, 0, 50, Color.rgb(
                            255, 0, 0), 0.5f);
                    Circle whiteCircle = new Circle(0, 0, 50, Color.rgb(
                            255, 255, 255), 0.5f);
                    Circle blueCircle = new Circle(25, 0, 50, Color.rgb(0,
                            0, 255), 0.5f);
                    surf.drawImage(redCircle.asCanvasImage(),
                            redCircle.getScreenX(), redCircle.getScreenY());
                    surf.drawImage(whiteCircle.asCanvasImage(),
                            whiteCircle.getScreenX(),
                            whiteCircle.getScreenY());
                    surf.drawImage(blueCircle.asCanvasImage(),
                            blueCircle.getScreenX(),
                            blueCircle.getScreenY());
                }
            });

    rootLayer.add(circleLayer);
}

And then asCanvasImage method of my Circle class:

public CanvasImage asCanvasImage() {
    int diameter = radius * 2;
    CanvasImage circleImage = graphics().createImage(diameter, diameter);
    Canvas canvas = circleImage.canvas();
    canvas.setFillColor(color);
    canvas.fillCircle((float) radius, (float) radius, (float) radius);
    canvas.setAlpha(alpha);
    return circleImage;
}

The alpha value is set to 0.5 for each circle. But this is the result when I run the Java version:

enter image description here

Edit: I discovered that if I change the alpha value on the rootLayer, it makes the images transparent:

rootLayer.setAlpha(0.5f);

However I wish to make each of the circle images independently transparent with different alpha values. Does that mean I have to add each image to its own layer and set the transparency on that layer?


Solution

  • I was able to create independent transparent circles using images layers. Is this the best way to accomplish this?

    I added an asImageLayer method to my Circle class that creates a circle image using the asCanvasImage method above then creates an image layer from that and successfully applies the alpha value:

    public ImageLayer asImageLayer() {
        CanvasImage image = asCanvasImage();
        ImageLayer imageLayer = graphics().createImageLayer(image);
        imageLayer.setAlpha(alpha);
        imageLayer.transform().translate(getScreenX(), getScreenY());
        return imageLayer;
    }
    

    My game class method that calls asImageLayer which in turn gets called by the paint method:

    public void drawTransparentImageLayers() {
        GroupLayer groupLayer = graphics().createGroupLayer();
        groupLayer.add(bgLayer);
        groupLayer.add(redCircle.asImageLayer());
        groupLayer.add(whiteCircle.asImageLayer());
        groupLayer.add(blueCircle.asImageLayer());
        rootLayer.add(groupLayer);
    }
    

    The result (the circles moves slightly at random leaving a trace):

    enter image description here

    It works but the movement appears to slow down over time. Performance issue?