連載
» 2012年08月16日 10時00分 公開

PlayNアプリでグラフィックや入力情報を使うにはPlayNでクロスプラットフォームのゲーム開発(2)(2/3 ページ)

[中田亮平, 高良完彰,@IT]

PlayNアプリで画像を表示するには

 PlayNでは画像やオーディオファイルなどのリソースファイルを置く「resources」フォルダがあり、この中のファイルにはPlayNクラスの「assets()」メソッドを使いアクセスできます。

 例えば、「resources/images/sample.png」という画像を使用する場合には、以下のようにすることでImageインターフェイスのインスタンスが取得し、このImageを持ったImageLayerを作れます。

Image image = assets().getImage("images/sample.png");
ImageLayer imageLayer = graphics().createImageLayer(image);

 また、以下のようにメソッドを使用することで、この画像の情報を取得できます。

image.width();
image.height();

 後は、このImageLayerをルートレイヤに追加するとsample.pngを画面に表示できます。

 また、このImageLayerの以下のようなメソッドにより、画像の大きさや繰り返し表示などを設定できます。

setWidth(float width)
setHeight(float height);
setSize(float width, float height);
setRepeatX(boolean repeat);
setRepeatY(boolean repeat);

 この外にもImageLayerのsuperインターフェイスであるLayerインターフェイスの下記のメソッドでレイヤの位置と角度が設定できます。

setTranslation(float x, float y);
setRotation(float angle);

 このsetRotationメソッドはレイヤの角度を設定しますが、引数で渡す角度の単位がラジアンなので、1fは度数では「約57°(180°/π)」を表し、正の値は時計回り、負の値は反時計回りにレイヤを回転させます。この回転では初期の設定として、レイヤの左上の角を基点として回転しますが、以下によって[x,y]の位置に起点を変えて回転できます。

setOrigin(float x, float y);

 これらのメソッドを使用したサンプルを見てみます。

package com.playn.sample.core;
 
import static playn.core.PlayN.*;
 
import playn.core.Game;
import playn.core.Image;
import playn.core.ImageLayer;
 
public class SampleGraphics2 implements Game {
    @Override
    public void init() {
        Image image1 = assets().getImage("images/smile.png");
        ImageLayer imageLayer1 = graphics().createImageLayer(image1);
        graphics().rootLayer().add(imageLayer1);
    
        Image image2 = assets().getImage("images/smile.png");
        ImageLayer imageLayer2 = graphics().createImageLayer(image2);
        imageLayer2.setWidth(200f);
        imageLayer2.setHeight(80f);
        imageLayer2.setTranslation(130f, 0f);
        graphics().rootLayer().add(imageLayer2);
    
        Image image3 = assets().getImage("images/star.png");
        ImageLayer imageLayer3 = graphics().createImageLayer(image3);
        imageLayer3.setWidth(480f);
        imageLayer3.setRepeatX(true);
        imageLayer3.setTranslation(20f, 140f);
        graphics().rootLayer().add(imageLayer3);
    
        Image image4 = assets().getImage("images/earthGreen.png");
        ImageLayer imageLayer4 = graphics().createImageLayer(image4);
        imageLayer4.setSize(50f, 200f);
        imageLayer4.setRepeatX(true);
        imageLayer4.setRepeatY(true);
        imageLayer4.setTranslation(60f, 230f);
        graphics().rootLayer().add(imageLayer4);    
    
        Image image5 = assets().getImage("images/earthBlue.png");
        ImageLayer imageLayer5 = graphics().createImageLayer(image5);
        imageLayer5.setSize(250f, 100f);
        imageLayer5.setRepeatX(true);
        imageLayer5.setRepeatY(true);
        imageLayer5.setTranslation(300f, 230f);
        imageLayer5.setRotation(0.5f);
        graphics().rootLayer().add(imageLayer5);    
    }
  
    @Override
    public void paint(float alpha) {
    }
  
    @Override
    public void update(float delta) {
    }
  
    @Override
    public int updateRate() {
        return 25;
    }
}

 それぞれの画像にImageLayerを作成し、それにより作られた複数のImageLayerをルートレイヤに追加しています。このサンプルを実行すると以下のような画面が表示されます。

画面

PlayNアプリで図形や画像を動かすには

 これまでのサンプルではゲーム起動時に静止した画像などを表示するだけだったので、すべてinit()メソッド内で処理を行っていました。

 しかしPlayNでは、起動時にinit()が実行された後、update()メソッドとpaint()メソッドが繰り返し実行されます。そのため、これらのメソッド内でこれまで紹介してきた処理を行うと、図形や画像の位置やサイズが変わる動きや、回転する動きなどを加えることができます。

 下記が、これらの動きを加えたサンプルのコードです。

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.GroupLayer;
import playn.core.Image;
import playn.core.ImageLayer;
import playn.core.Layer;
 
public class SampleGraphics3 implements Game {
    private Layer image1Layer;  // 【1】の白い円のレイヤ
    private float image1X;  // 【1】のX座標の値
  
    private ImageLayer image2Layer;  // 【2】の星の画像のレイヤ
    private float image2Y;  // 【2】のY座標の値
    private boolean image2MovingDown;  // 【2】が上下どちらに動いているかを示すフラグ
  
    private Layer image3Layer;  // 【3】の赤い長方形のレイヤ
    private float image3Angle;  // 【3】の角度の値
  
    private Layer image4Layer;  // 【4】の緑の長方形のレイヤ
    private float image4Angle;  // 【4】の角度の値
    
    private ImageLayer image5Layer;  // 【5】の地球の画像のレイヤ
    private float image5Size;  // 【5】のサイズ
    private boolean image5Expanding;  // 【5】が拡大しているか縮小しているかのフラグ
  
    private Layer image6Layer;  // 【6】の黄色い長方形のレイヤ
    private float image6Y;  // 【6】のY座標の値
    private boolean image6MovingDown;  // 【6】が上下どちらに動いているかを示すフラグ
  
    private ImageLayer image7Layer;  // 【7】のドーナツのレイヤ
    private float image7Angle;  // 【7】の角度の値
  
    private GroupLayer groupLayer;  // 【6】と【7】を子要素として持つグループレイヤ
    private float groupLayerX;  // グループレイヤのX座標の値
    private boolean groupLayerMovoingRight;  // グループレイヤが左右どちらに動いているかを示すフラグ
  
    @Override
    public void init() {
        initImage1();  // 【1】の初期表示
        initImage2();  // 【2】の初期表示
        initImage3();  // 【3】の初期表示
        initImage4();  // 【4】の初期表示
        initImage5();  // 【5】の初期表示
        initImageGroup();  // グループレイヤの初期表示
        initImage6();  // 【6】の初期設定とグループレイヤへの追加
        initImage7();  // 【7】の初期表示とグループレイヤへの追加
    }
  
    // それぞれのレイヤの表示を更新
    @Override
    public void paint(float alpha) {
        updateImage1();
        updateImage2();
        updateImage3();
        updateImage4();
        updateImage5();
        updateImage6();
        updateImage7();    
        updateImageGroup();
    }
  
    @Override
    public void update(float delta) {
    }
  
    @Override
    public int updateRate() {
        return 25;
    }
  
    //【1】の初期表示
    private void initImage1() {
        CanvasImage canvasImage = graphics().createImage(graphics().width(), graphics().height());
        Canvas canvas = canvasImage.canvas();
        canvas.setFillColor(Color.rgb(255, 255, 255));
        canvas.fillCircle(25f, 25f, 25f);
        image1Layer = graphics().createImageLayer(canvasImage);
        image1X = 0f;
        image1Layer.setTranslation(image1X, 20f);
        graphics().rootLayer().add(image1Layer);
    }
  
    //【2】の初期表示
    private void initImage2() {
        Image image = assets().getImage("images/star.png");
        image2Layer = graphics().createImageLayer(image);
        image2Layer.setWidth(48f);
        image2Layer.setHeight(48f);
        image2Y = 60f;
        image2Layer.setTranslation(20f, image2Y);
        image2MovingDown = false;
        graphics().rootLayer().add(image2Layer);
    }
  
    //【3】の初期表示
    private void initImage3() {
        CanvasImage canvasImage = graphics().createImage(graphics().width(), graphics().height());
        Canvas canvas = canvasImage.canvas();
        canvas.setFillColor(Color.rgb(255, 0, 0));
        canvas.fillRect(0f, 0f, 60f, 20f);
        image3Layer = graphics().createImageLayer(canvasImage);
        image3Layer.setTranslation(200f, 120f);
        image3Angle = 0;
        graphics().rootLayer().add(image3Layer);
    }
  
    //【4】の初期表示
    private void initImage4() {
        CanvasImage canvasImage = graphics().createImage(graphics().width(), graphics().height());
        Canvas canvas = canvasImage.canvas();
        canvas.setFillColor(Color.rgb(0, 255, 0));
        canvas.fillRect(0f, 0f, 60f, 20f);
        image4Layer = graphics().createImageLayer(canvasImage);
        image4Layer.setTranslation(300f, 120f);
        image4Layer.setOrigin(25f, 10f);
        image4Angle = 0;
        graphics().rootLayer().add(image4Layer);
    }
  
    //【5】の初期表示
    private void initImage5() {
        Image image = assets().getImage("images/earthBlue.png");
        image5Layer = graphics().createImageLayer(image);
        image5Size = 0f;
        image5Layer.setWidth(image5Size);
        image5Layer.setHeight(image5Size);
        image5Layer.setTranslation(400f, 120f);
        image5Expanding = true;
        graphics().rootLayer().add(image5Layer);
    }
  
    //【6】の初期設定とグループレイヤへの追加
    private void initImage6() {
        CanvasImage canvasImage = graphics().createImage(graphics().width(), graphics().height());
        Canvas canvas = canvasImage.canvas();
        canvas.setFillColor(Color.rgb(255, 255, 0));
        canvas.fillRect(0f, 0f, 80f, 20f);
        image6Layer = graphics().createImageLayer(canvasImage);
        image6Y = 0f;
        image6MovingDown = true;
        groupLayer.add(image6Layer);
    }
  
    //【7】の初期表示とグループレイヤへの追加
    private void initImage7() {
        Image image = assets().getImage("images/donut.png");
        image7Layer = graphics().createImageLayer(image);
        image7Layer.setWidth(48f);
        image7Layer.setHeight(48f);
        image7Layer.setTranslation(0f, 120f);
        image7Layer.setOrigin(image.width() / 2, image.height() / 2);
        image7Angle = 0;
        groupLayer.add(image7Layer);
    }
  
    //グループレイヤの初期表示
    private void initImageGroup() {
        groupLayer = graphics().createGroupLayer();
        groupLayerX = 200f;
        groupLayer.setTranslation(groupLayerX, 300f);
        graphics().rootLayer().add(groupLayer);
    }
  
    // 【1】の図形を左から右に移動させ、画面から外れると再び左から移動させる
    private void updateImage1() {
        image1X += 3f;
        if (image1X >= graphics().width()) {
            image1X = -50f;
        }
        image1Layer.setTranslation(image1X, 20f);
    }
  
    // 【2】の画像を画面上部と下部の間で上下に移動させる
    private void updateImage2() {
        if (image2MovingDown) {
            image2Y -= 5f;
        } else {
            image2Y += 2f;
        }
    
        if (image2Y <= 60f) {
            image2MovingDown = false;
        } else if (image2Y >= graphics().height() - 48f) {
            image2MovingDown = true;
        }
    
        image2Layer.setTranslation(20f, image2Y);
    }
  
    // 【3】の長方形を回転させる
    private void updateImage3() {
        image3Angle += 0.05f;
        image3Layer.setRotation(image3Angle);
    }
  
    // 【4】の長方形を回転させる
    private void updateImage4() {
        image4Angle += 0.05f;
        image4Layer.setRotation(image4Angle);
    }
  
    // 【5】の図形の拡大と縮小を繰り返す
    private void updateImage5() {
        if (image5Expanding) {
            image5Size += 1f;
        } else {
            image5Size -= 1f;
        }
        if (image5Size >= 150f) {
            image5Expanding = false;
        } else if (image5Size <= 0f) {
            image5Expanding = true;
        }
        image5Layer.setWidth(image5Size);
        image5Layer.setHeight(image5Size);
    }
  
    // 【6】の長方形を上下に動かす
    private void updateImage6() {
        if (image6MovingDown) {
            image6Y -= 3f;
        } else {
            image6Y += 3f;
        }
    
        if (image6Y <= 0f) {
            image6MovingDown = false;
        } else if (image6Y >= 60f) {
            image6MovingDown = true;
        }
    
      image6Layer.setTranslation(20f, image6Y);
    }
  
    // 【7】の画像を回転させる
    private void updateImage7() {
        image7Angle -= 0.1f;
        image7Layer.setRotation(image7Angle);
    }
  
    // グループレイヤを左右に移動させる
    private void updateImageGroup() {
        if (groupLayerMovoingRight) {
            groupLayerX += 2f;
        } else {
            groupLayerX -= 2f;
        }
    
        if (groupLayerX <= 200f) {
            groupLayerMovoingRight = true;
        } else if (groupLayerX >= 500f) {
            groupLayerMovoingRight = false;
        }
    
        groupLayer.setTranslation(groupLayerX, 300f);
    }
}

 このサンプルを実行すると、次のような画面が表示され、図形や画像はそれぞれ動いています。

画面

 【1】の図形は左から右に動き、画面から外れると再び左から現れます。

 【2】の画像は上から下へ動き、画面の下へ達すると上向きへ動きます。画面上部へ達すると再び下向きへ動きます。

 【3】の長方形は、左上の頂点を基点として回転します。

 【4】の長方形は、図形の中心を基点として回転します。

 【5】の図形は、拡大と縮小を繰り返します。

 【6】の長方形は上下に動き、【7】は画像の中心を基点に回転しますが、これらはさらに左右にも繰り返し動きます。

 init()メソッド内で各図形や画像のレイヤを作っています。そして【1】から【5】のレイヤとグループレイヤはルートレイヤに追加していますが、【6】と【7】のレイヤはグループレイヤに追加しています。そのため、ルートレイヤの子要素としてグループレイヤがあり、そのグループレイヤの子要素として【6】と【7】のレイヤがあります。

 これにより、ゲーム実行中にこのグループレイヤが動くと、【6】と【7】のレイヤにも同じ動きが反映されます。

 それぞれのレイヤに動きを加える処理はpaint()メソッド内に書いてあります。update()メソッドとpaint()メソッドはどちらも繰り返し呼ばれるため、動きを加えるコードはどちらに書いても同じように処理は行われるのですが、ここでは描画処理を行うためのものなのでpaint()メソッド内で処理を行っています。

 図形や画像の位置やサイズを変えるメソッドはこれまで紹介してきたメソッドと同じですが、これらに動きを加えるためには、設定した位置やサイズ、角度の値をメンバ変数として保持しておき、paint()メソッドからそれらの値を使用できるようにしておきます。paint()メソッドが1度実行されるたびに、これらの値を少し変えます。

 これにより、paint()メソッドが繰り返し呼ばれることで画面では図形や画像が移動し、回転しているように見えます。

 updateImage6()のメソッドは【6】のレイヤを上下に動かすだけであり、updateImage7()のメソッドは【7】のレイヤを回転させるだけの処理ですが、【6】と【7】はグループレイヤの子要素でもあるため、updateImageGroup()メソッドによるグループレイヤを左右に動かす処理の影響も受けます。そのため【6】は上下に動きながら左右にも動き、【7】は回転しながら左右にも動きます。

 続いて次ページでは、テキストを表示する方法や、キーボード、マウス/スマホのタッチによる入力情報の取得方法を見てみます。

INDEX

PlayNでクロスプラットフォームのゲーム開発(2)

PlayNアプリでグラフィックや入力情報を使うには

Page1
PlayN 1.4に対応するには
すべての基となり、重要な「PlayN」クラス
PlayNのグラフィックレイヤ「Layer」インターフェイス
PlayNで線や図形を表示する「Canvas」

Page2
PlayNアプリで画像を表示するには
PlayNアプリで図形や画像を動かすには

Page3
PlayNアプリでテキストを表示するには
マウス/スマホのタッチによる入力情報の取得
キーボードによる入力情報を取得するKeyboardリスナ
次回はオーディオやストレージ、ネットへのアクセス


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。