A few changes to basic project structures were made with the PlayN 1.7 release. This document describes those changes and how to update your PlayN project to accommodate them.
Previously your game implemented the Game
interface and provided implementations of a few
methods:
public class MyGame implements Game {
public void init () {}
public void update (float delta) {}
public void paint (float alpha) {}
public int updateRate () { return N; }
}
Now your game should extend Game.Default
, and pass its update rate into the Game.Default
constructor:
public class MyGame extends Game.Default {
public MyGame () {
super(N);
}
public void init () {}
public void update (int delta) {}
public void paint (float alpha) {}
}
Note also that update
takes int delta
instead of float delta
. The delta value is a number of
milliseconds and was never non-integral.
This release also improves the smoothness of update
and paint
calls. As long as you are
properly using alpha
to interpolate between simulation updates, you should simply see your game
run smoother.
If you wish to implement your own custom approach to update
and paint
you can implement Game
directly instead of using Game.Default
. In that case, you implement the tick
method (instead of
update
and paint
) and decide how to handle simulation updates and paints yourself:
public class MyGame implements Game {
public void init () {}
public void tick (int elapsed) {}
}
You can look at the source
code for
Game.Default
to see how it handles simulation and painting updates, and tweak or replace the
default algorithm.
Previously, PlayN maintained a fork of the JBox2D code base with small tweaks to make it work with GWT (so that it would work with the HTML backend). Those tweaks have been merged upstream, and now it is possible to use the latest release of JBox2D (2.2.1.1) directly with PlayN.
PlayN still provides a playn-jbox2d
artifact, which provides a DebugDraw2D
implementation that
allows one to render debug information for JBox2D games, but that artifact no longer provides
JBox2D itself. If your game does not use the HTML backend, you don’t need to make any changes to
your project configuration. If your game does use JBox2D and the HTML backend, there are two
changes that are needed.
html/pom.xml
: <dependency>
<groupId>org.jbox2d</groupId>
<artifactId>jbox2d-library</artifactId>
<version>${jbox2d.version}</version>
<classifier>sources</classifier>
</dependency>
Note that the PlayN
project POM defines jbox2d.version
, so you don’t need to define that in
your top-level POM.
GwtBox2D
to JBox2D
in your GWT module file:- <inherits name="org.jbox2d.GwtBox2D" />
+ <inherits name="org.jbox2d.JBox2D" />
Using the latest version of JBox2D will require that you update your game to use the latest JBox2D APIs. You can view the Box2D manual for information on the latest API: http://box2d.org/manual.pdf
A Surface
provides a hardware accelerated bitmap into which a game can render, and which can then
be displayed in the scene graph. Previously surfaces were tightly bound a special layer,
SurfaceLayer
, which was the only way to create and render to such a bitmap.
Now surfaces have been decoupled from layers and are just another kind of Image
. CanvasImage
provides a non-hardware accelerated bitmap into which a game can render, and now SurfaceImage
provides a hardware accelerated bitmap into which a game can render. A SurfaceImage
can then be
placed into one or more ImageLayer
instances to be included in a scene graph, or a SurfaceImage
can be drawn via the immediate-mode rendering mechanism provided by ImmediateLayer
.
If you had code like:
SurfaceLayer layer = graphics().createSurfaceLayer(width, height);
layer.surface().draw(...);
graphics().rootLayer().addAt(layer, 10, 10);
You can change that code to:
SurfaceImage image = graphics().createSurface(width, height);
image.surface().draw(...);
ImageLayer layer = graphics().createImageLayer(image);
graphics().rootLayer().addAt(layer, 10, 10);
Everything that was possible with SurfaceLayer
is still possible with SurfaceImage
and many
other previously impossible things are now possible. That said, there are some limitations in the
current implementation, some of which will be remedied in the future and some of which are simply
limitations due to the nature of surface images being GPU-managed bitmaps:
SurfaceImage
into a Canvas
. This will throw an exception. It may be possible in the future to download the bitmap data from the GPU and draw it into the CPU image.SurfaceImage
in the x or y directions unless its size is a power of two on the to-be-repeated axes.Pattern
returned by calling Image.toPattern
on a SurfaceImage
cannot currently be used when drawing to a Canvas
. It can be used to draw to a Surface
.Image.BitmapTransformer
on a SurfaceImage
.I would have preferred to restructure the class hierarchy of Image
, CanvasImage
and
SurfaceImage
to make it impossible to call methods on SurfaceImage
which can never be made to
work, but it would have required Image
to be changed to a new type, which would have been a
massive disruption to the codebase of every PlayN game in existence. So I decided that this
slightly sloppier API which admits impossible requests was a better approach.