This is about as basic as it gets. I don't want to use an image file. Rather, I want to programmatically draw a circle and blit it to a surface (as they say in pygame).
I tried to follow the "Using CanvasLayers" example here:
From my game class:
// Surface
SurfaceLayer surface;
// Background
int width = 640;
int height = 480;
//ImageLayer bgLayer;
CanvasImage bgImage;
Canvas canvas;
// Circle
CanvasImage circleImage;
//ImageLayer circleLayer;
int circleRadius = 20;
int circleX = 0;
int circleY = 0;
@Override
public void init() {
// create a surface
surface = graphics().createSurfaceLayer(width, height);
graphics().rootLayer().add(surface);
// create a solid background
// http://code.google.com/p/playn101/source/browse/core/src/main/java/playn101/core/J.java#81
bgImage = graphics().createImage(width, height);
canvas = bgImage.canvas();
canvas.setFillColor(0xff87ceeb);
canvas.fillRect(0, 0, width, height);
//bgLayer = graphics().createImageLayer(bgImage);
//graphics().rootLayer().add(bgLayer);
// create a circle
circleImage = graphics().createImage(circleRadius, circleRadius);
canvas = circleImage.canvas();
canvas.setFillColor(0xff0000eb);
canvas.fillCircle(circleX, circleY, circleRadius);
//circleLayer = graphics().createImageLayer(circleImage);
//graphics().rootLayer().add(circleLayer);
}
@Override
public void paint(float alpha) {
// the background automatically paints itself, so no need to do anything
// here!
surface.clear(0);
surface.drawImage(bgImage, 0, 0);
surface.drawImage(circleImage, 100, 100);
}
But I get a blank window in Java and Eclipse complains:
The method drawImage(CanvasImage, int, int) is undefined for the type
SurfaceLayer
That, however, is the way it is used in the example at the link.
解决方案
If the code you provided even compiles, then you are using some very old version of PlayN.
Update to PlayN 1.1.1 and fix the compilation errors that result, and your code will work fine.
The following is your code updated to work with PlayN 1.1.1:
private SurfaceLayer surface;
private CanvasImage bgImage;
private CanvasImage circleImage;
@Override
public void init() {
// create a surface
int width = graphics().width(), height = graphics().height();
surface = graphics().createSurfaceLayer(width, height);
graphics().rootLayer().add(surface);
// create a solid background
bgImage = graphics().createImage(width, height);
Canvas canvas = bgImage.canvas();
canvas.setFillColor(0xff87ceeb);
canvas.fillRect(0, 0, width, height);
// create a circle
int circleRadius = 20;
int circleX = 0;
int circleY = 0;
circleImage = graphics().createImage(circleRadius, circleRadius);
canvas = circleImage.canvas();
canvas.setFillColor(0xff0000eb);
canvas.fillCircle(circleX, circleY, circleRadius);
}
@Override
public void paint(float alpha) {
Surface s = surface.surface();
s.clear();
s.drawImage(bgImage, 0, 0);
s.drawImage(circleImage, 100, 100);
}
If you really intend to make a game using this approach, you should use ImmediateLayer not SurfaceLayer. ImmediateLayer will issue your drawImage, etc. calls directly against the framebuffer. SurfaceLayer will make an off-screen framebuffer and render everything into that and then copy that off-screen framebuffer to the main framebuffer every frame (in addition to the double buffering naturally performed by OpenGL, etc.), resulting in a needless copy of your entire screen.