Javaで書いたアプリをiOS、Android、HTML5、Flashなどにクロスコンパイルできるライブラリの概要や基本的な使い方を解説していきます
グーグルが開発しているクロスプラットフォームゲームライブラリであるPlayNを紹介している本連載。第1回目の前回「Angry BirdsのHTML5版にも使われた『PlayN』入門」では、PlayNを使用するための環境の準備とサンプルプロジェクトの取得・実行、新規のPlayNプロジェクトの作成と簡単なコードの書き方を説明しました。
第2回目である今回はさまざまな図形や文字、画像の画面への表示や、マウスやキーポードからのインプット情報を取得する方法を紹介します。
前回の記事でも書きましたが、PlayNは現在開発されているものであり、頻繁にバージョンアップが行われています。第1回目の時点ではバージョン1.3だったので、記事の内容も1.3を基に書きましたが、その後7月22日にバージョン1.4がリリースされたため、今回は1.4を使用しています。
前回紹介した環境構築や新規プロジェクトの作成は1.4でも同様の手順で行えます。ただ、コマンドラインで新規プロジェクトを作成する際は、バージョン1.3.1ではなく下記のように1.4と指定してください。
mvn archetype:generate -DarchetypeGroupId=com.googlecode.playn -DarchetypeArtifactId=playn-archetype -DarchetypeVersion=1.4
今回の記事の内容は主にPlayNのJavadocを参考にしていますが、このJavadoc自体もまだまだ「TODO」と表記されている部分が多々あり、詳細が分からない部分もありますが、可能な範囲で紹介したいと思います。
PlayNのライブラリには「PlayN」というクラスがあり、これはさまざまなサブシステムにアクセスするインターフェイスであり重要なクラスです。このクラスは新規のスケルトンプロジェクトを作成すると、すでにインポートされていますし、おそらくほぼすべてのPlayNのゲームを作るうえで使用するクラスだと思います。
PlayNクラスには多くのstaticメソッドがあり、例えば「PlayN.graphics();」というメソッドでGraphicsインターフェイスを実装したクラスのインスタンスを取得し、さまざまな画面表示の処理を行います。
また、resourcesディレクトリ内にある画像ファイルなどのリソースへアクセスするには「PlayN.assets();」によって取得できるAssetsインターフェイスを使用します。
その他にもキーボードやマウスのインプット情報を取得するには、「PlayN.keyboard();」「PlayN.mouse();」など、PlayNのさまざまな機能を使用する際に用います。また、「import static playn.core.PlayN.*;」としてインポートしているため、これらのメソッドは「PlayN.」を除いて、単に「graphics()」「assets()」「keyboard()」として用いられます。
PlayNには画面に描画を行うグラフィックレイヤの種類が複数あり、図形や画像、文字などを表示する際にはこれらのグラフィックレイヤに対して描画を行います。また、ルートレイヤを起点とするグラフィックレイヤの階層を作ることにより、複数のレイヤを重ね合わせて表示できます。
PlayNには、まず「Layer」というインターフェイスがあり、レイヤの位置を設定したりレイヤを回転させるなど、どのレイヤでも行うことのできる処理が定義されています。Layerのサブインターフェイスとして「ImageLayer」「SurfaceLayer」「ImmediateLayer」などがあります。
これらのレイヤはそれぞれ画面に図形や画像を表示できますが、描画処理の際のメモリの使い方や処理速度などが異なります。より速い描画処理を行うには、SurfaceLayerやImmediateLayer、より複雑な描画を行うためにはImageLayerなど、用途により使い分けるのが良いようです。
PlayNの公式サイトのグラフィックレイヤについて説明したページでは「CanvasLayer」インターフェイスもありますが、PlayNのリリースノートでは今後CanvasLayerはなくなるようで、ImageLayerを使うように推奨されています。
また、現在グーグルが提供しているサンプルゲームのコードを見てみると、落下するボールの表示にも静止した文字の表示にもImageLayerが使用され、ImageLayerは主要なグラフィックレイヤとして多くの場面で使用されているようです。そのため、本稿のサンプルコードではImageLayerを使用した図形や画像の表示の仕方を紹介します。
これらのレイヤの他にも「GroupLayer」というものがあります。これは他のレイヤとは異なり描画処理は行いませんが、他のレイヤを子要素として持てます。そのため、GroupLayerに複数の子要素を持たせることで、画面にレイヤを重ねて表示できます。また、GroupLayerの子要素に他のGroupLayerを持たせることでレイヤの階層を増やせます。
PlayNで作られるゲームにはルートとなるレイヤがあり、Graphicsインターフェイスの「rootLayer()」メソッドでルートレイヤが取得できます。このルートレイヤはグループレイヤであるため、他のレイヤを子要素として追加できます。実際に図形や画像を表示するレイヤは、このルートレイヤに追加されることで画面に表示されます。
ここからはPlayNで画面に線や図形を表示する方法を見てみます。PlayNでは「Canvas」というインターフェイスがあり、このインターフェイスを使用することでさまざまな図形を表示できます。まず以下のようにしてCanvasを実装したクラスのインスタンスを取得します。
CanvasImage canvasImage = graphics().createImage(width, height); Canvas canvas = canvasImage.canvas();
1行目のgraphics()は前述のPlayNクラスのメソッドであり、そこから幅と高さを指定してCanvasImageを取得します。2行目のcanvas()によって、このCanvasImageにさまざまな描画を行うCanvasを取得します。
また、このCanvasImageは以下のようにすることで、このCanvasImageを持ったレイヤを作れます。
Layer layer = graphics().createImageLayer(canvasImage);
ここからは、Canvasを使用して線や図形を描画するメソッドを紹介します。
drawLine(float x0, float y0, float x1, float y1) 【1】 fillRect(float x, float y, float width, float height) 【2】 fillRoundRect(float x, float y, float width, float height, float radius) 【3】 fillCircle(float x, float y, float radius) 【4】
【1】は座標[x0,y0]と[x1,y1]の2点を結ぶ線を表示します。
【2】は座標[x,y]を左上の頂点とする幅width、高さheightの四角形を表示します。
【3】は角が丸まった四角形を表示するもので、最初の4つの引数は【2】と同様ですが、5つ目のradiusで角の丸みを指定します。
【4】は3つ目の引数radiusを半径とする円を座標[x,y]の位置に表示します。このメソッドでは、[x,y]は円の中心の位置です。
これらの引数の値はfloatで渡すことになっています。また、これらの他に以下のメソッドで表示する線や図形の色を指定できます。
setFillColor(int color);
例えば、このメソッドで赤色を指定すると、次に別の色を指定するまでに書かれた図形は、すべて赤色で表示されます。このメソッドの引数は、色を指定するためにintの値を渡します。これは0x00000000(黒色)や、0xffffffff(白色)などの値を渡すこともできますし、Colorクラスの以下のようなstaticメソッドによって返されるintの値を使用することもできます。
rgb(int r, int g, int b);
このメソッドを使用するとRGBカラーの赤、緑、青のそれぞれの色を0から255までの数で指定できます。また、Colorクラスにはもう1つ以下のようなintの値を返すstaticメソッドがあり、aの値を追加することで色の透明度も指定できます。
argb(int a, int r, int g, int b);
これらを使用した線や図形を表示するサンプルコードを見てみます。
package com.playn.sample.core; import static playn.core.PlayN.*; import playn.core.Canvas; import playn.core.CanvasImage; import playn.core.Color; import playn.core.Game; import playn.core.Layer; public class SampleGraphics implements Game { @Override public void init() { CanvasImage canvasImage = graphics().createImage(graphics().width(), graphics().height()); // 【1】 Canvas canvas = canvasImage.canvas(); // 【2】 canvas.setFillColor(Color.rgb(255, 255, 255)); // 【3】 canvas.drawLine(20f, 20f, 300f, 20f); // 【4】 canvas.drawLine(20f, 40f, 250f, 40f); canvas.drawLine(20f, 60f, 200f, 60f); canvas.drawLine(20f, 80f, 150f, 80f); canvas.drawLine(20f, 20f, 20f, 300f); canvas.drawLine(40f, 20f, 40f, 250f); canvas.drawLine(60f, 20f, 60f, 200f); canvas.drawLine(80f, 20f, 80f, 150f); canvas.drawLine(20f, 20f, 150f, 150f); canvas.drawLine(40f, 20f, 200f, 100f); canvas.drawLine(20f, 40f, 100f, 200f); canvas.fillRect(300f, 40f, 200f, 60f); // 【5】 canvas.fillRoundRect(300f, 120f, 300f, 50f, 10f); canvas.fillRoundRect(130f, 190f, 200f, 200f, 30f); canvas.setFillColor(Color.rgb(0, 0, 255)); canvas.fillRect(230f, 210f, 80f, 80f); canvas.setFillColor(Color.rgb(255, 255, 0)); canvas.fillCircle(390, 240, 40); canvas.setFillColor(Color.rgb(255, 0, 0)); canvas.fillCircle(500, 340, 90); canvas.setFillColor(Color.rgb(0, 0, 0)); canvas.fillCircle(530, 360, 30); Layer layer = graphics().createImageLayer(canvasImage); // 【6】 graphics().rootLayer().add(layer); } @Override public void paint(float alpha) { } @Override public void update(float delta) { } @Override public int updateRate() { return 25; } }
このサンプルを実行すると、次のような画面が表示されます。
このサンプルでは、まずコード内の【1】と【2】でCanvasImageとCanvasのインターフェイスを実装したクラスのインスタンスを取得し、【3】で表示色を白色に指定しています。
【4】以降では縦線や横線、斜線を書き、【5】からは途中で描画色を変えながら、さまざまな円や四角形、角が丸い四角形を描画しています。【6】でこれらの線や図形が書かれたCanvasImageを持ったイメージレイヤを作成し、このレイヤを画面に表示するためにルートレイヤに追加しています。
上記の画面は、このサンプルをJavaアプリとして起動したものですが、同じサンプルをHTML5として動かした場合、図形は表示されるのですがdrawLine()メソッドによる左上の線は表示されませんでした。プラットフォームによっては、うまく表示されないものもあるようです。
このサンプルはゲーム起動時に線や図形を表示するだけなので、すべての描画処理はinit()メソッド内に書かれ、update()とpaint()メソッド内では何も処理が行われていません。
次ページでは、画面に画像を表示する方法や画面に表示した図形や画像を動かす方法を見てみます。
Copyright © ITmedia, Inc. All Rights Reserved.