About me

  • Johannes Barop <jb@barop.de>
  • Hamburg, Germany
  • Freelancing web application developer
  • Java and GWT
  • Game development for fun

Motivation behind PlayN

  • Develop games for many different platforms and environments
  • PCs, Smartphones, Tablets, SmartTVs, Social Networks
  • Linux, MacOS, Windows, Android, iOS, webOS
  • This takes a huge amount of development resources
  • Hard to maintain
  • No fun at all

PlayN

  • Formerly known as "ForPlay"
  • Cross platform game abstraction library
  • Write one code base and run it natively on different platforms (Java, HTML5, Android, iOS, Flash)
  • Based on Java
  • Open sourced under Apache License 2.0
  • Active project with contributors from Google and game studios
  • Used for the Chrome version of Angry Birds
  • code.google.com/p/playn
  • developers.google.com/playn

Why Java?

  • Runs natively on Android
  • Great optimizations through GWT
  • Reuse the GWT compiler to generate other languages like Flex
  • Familiar tools and libraries
  • Box2D (C++) -> JBox2D (Java) -> GWTBox2D (GWT)

Abstraction

Implement the Game inferface using the core API

import static playn.core.PlayN.*;

public class MyGame implements playn.core.Game {

  void init() {
    /** ... **/
    playn.core.ImageLayer bg = graphics().createImageLayer(bgImage);
    graphics().rootLayer().add(bg);
  }
  /** ... **/
}
					

Each platform implements the core API

class playn.html.HtmlImageLayer implements playn.core.ImageLayer {
  /** ... **/
}
					

Abstraction

Some implemented sub systems

Graphics infrastructure

  • Hierarchical layer system
  • Transformations (translate, scale, rotate)
  • Different layer types with specialized drawing functionality
  • Acceleration (OpenGL, OpenGL ES, WebGL, HTML5 Canvas, CSS3)

Layer types

  • Group Layer: Groups multiple layers into on layer
  • Image Layer: Displays an image
  • Surface Layer: Renders multiple images into a single surface
  • Canvas Layer: Provides 2D Canvas API

Let's create a game

Create a project

mvn archetype:generate \
 -DarchetypeGroupId=com.googlecode.playn \
 -DarchetypeArtifactId=playn-archetype \
 -DarchetypeVersion=1.4
					

Run it

mvn test -Pjava # run it with java
mvn test -Phtml # run it with gwt
					

Android and iOS work too but need some setup.

See code.google.com/p/playn/w for details.

Let's create a game

public class MyGame implements Game {

  @Override
  public void init() {
    Image bgImage = assets().getImage("images/bg.png");
    ImageLayer bgLayer = graphics().createImageLayer(bgImage);
    graphics().rootLayer().add(bgLayer);
  }

  @Override
  public void paint(final float alpha) {
  }

  @Override
  public void update(final float delta) {
  }

  @Override
  public int updateRate() {
    return 25;
  }

}
					

Let's create a game

Let's create a game

@Override
public void init() {
  /** **/

  Image cloudImage = assets().getImage("images/cloud.png");
  ImageLayer cloudLayer = graphics().createImageLayer(cloudImage);
  graphics().rootLayer().add(cloudLayer);
}
					

Add a cloud

Animate the cloud

@Override
public void paint(final float delta) {
  couldX += delta;
  if (couldX > bgImage.width() - cloudImage.width()) {
    couldX = -cloudImage.width();
  }
  cloudLayer.setTranslation(couldX, couldY);
}
					

Animate the cloud

Add balls with click/touch

@Override
public void init() {
  /** **/

  ballImage = assets().getImage("images/ball.png");
  ballLayer = graphics().createGroupLayer();
  graphics().rootLayer().add(ballLayer);
  pointer().setListener(new Pointer.Adapter() {
    @Override
    public void onPointerEnd(final Pointer.Event event) {
      Ball ball = new Ball(ballImage, event.x(), event.y());
      ballLayer.add(ball.layer);
    }
  });
}
					

Add balls with click/touch

Add physics

public Ball(final Image image, final float x, final float y) {
  /** **/

  BodyDef bodyDef = new BodyDef();
  bodyDef.type = BodyType.DYNAMIC;
  bodyDef.position = new Vec2(x, y);
  body = world.createBody(bodyDef);
  FixtureDef fixtureDef = new FixtureDef();
  fixtureDef.shape = new CircleShape();
  fixtureDef.shape.m_radius = radius;
  fixtureDef.density = 1.0f;
  fixtureDef.friction = 0.3f;
  body.createFixture(fixtureDef);
  body.setTransform(new Vec2(x, y), 0.0f);
}
					

Add physics

@Override
public void init() {
  /** **/

  world = new World(new Vec2(0.0f, 10.0f), true);
  world.setWarmStarting(true);
  world.setAutoClearForces(true);
}

@Override
public void update(final float delta) {
  world.step(delta, 10, 10);
}
					

Add physics

Add some bounds to the screen

@Override
public void init() {
  /** **/

  float physWidth = physUnitPerScreenUnit * 640;
  float physHeight = physUnitPerScreenUnit * 480;
  Body ground = world.createBody(new BodyDef());

  PolygonShape bottom = new PolygonShape();
  bottom.setAsEdge(new Vec2(0, physHeight), new Vec2(physWidth, physHeight));
  ground.createFixture(bottom, 0.0f);

  PolygonShape top = new PolygonShape();
  top.setAsEdge(new Vec2(0, 0), new Vec2(physWidth, 0));
  ground.createFixture(top, 0.0f);

  PolygonShape left = new PolygonShape();
  left.setAsEdge(new Vec2(0, 0), new Vec2(0, physHeight));
  ground.createFixture(left, 0.0f);

  PolygonShape right = new PolygonShape();
  right.setAsEdge(new Vec2(physWidth, 0), new Vec2(physWidth, physHeight));
  ground.createFixture(right, 0.0f);
}
					

Add some bounds to the screen

Questions?

<Thank You!>

Please give feedback