libGDXの基礎７ イベント

libGDXとはWindows、Linux、Mac、Android、iPhone、HTMLに対応したクロスプラットフォームゲームライブラリです。有名なIngressでも利用されています。欧米ではわりとメジャーどころです。

#入力イベントとは

タッチやクリック、キーボードなどの入力に応じてよばれる仕組みです。と書くと難しそうですが、仕組みは簡単です。

Scene2Dには各種Actorにイベントリスナーを設定することが可能です。ちゃんと重なった場所も優先度の高い（手前に表示されているもの）Actorがそのイベントを受け取ります。




#イベント登録に利用するメソッドは１つだけ

イベントの登録メソッドは```Actor#addListener()```のみです。

イベントリスナーはいくつか用意されていますが、一番単純なクリックイベントをここでは実装してみます。


#ソース

```java

package test.libgdx;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;

public class MainListener7 implements ApplicationListener{

    TextureAtlas atlas;
    Stage stage;
    
    @Override
    public void create() {

        FileHandle fh = Gdx.files.internal("atlas/data.txt");
        atlas = new TextureAtlas(fh);
        
        stage = new Stage();
        Gdx.input.setInputProcessor(stage);//ここがポイント１
        
        {   
            TextureAtlas.AtlasRegion region = atlas.findRegion("001");
            Image image = new Image(region);
            image.setPosition(0, 0);
            
            ClickListener listener = new ClickListener(){//ここがポイント２

                @Override
                public void clicked(InputEvent event, float x, float y) {
                    System.out.println("001がクリックされた！");
                }
                
            };
            image.addListener(listener);//ここがポイント３

            
            stage.addActor(image);
        }
        
        {   
            TextureAtlas.AtlasRegion region = atlas.findRegion("002");
            Image image = new Image(region);
            image.setPosition(50, 50);
            
            ClickListener listener = new ClickListener(){

                @Override
                public void clicked(InputEvent event, float x, float y) {
                    System.out.println("002がクリックされた！");
                }
                
            };
            image.addListener(listener);

            stage.addActor(image);
        }

        
    }

    @Override
    public void resize(int w, int h) {
    }

    @Override
    public void render() {
        
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        Gdx.gl.glClearColor(0, 0, 0, 1);
        
        
        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    @Override
    public void dispose() {
    }
    
    //起動部分
    public static void main(String[] args) {
        new LwjglApplication(new MainListener7());
    }
}

```

軽く解説をすると、コメントにある「ポイント1」のところが各種入力イベントをScene2Dへ処理をさせるという宣言です。ここがないとイベントは発生していてもイベントリスナーへはまともに飛んできません。

「ポイント２」でリスナーの作成。GUI系ではこう言ったインナークラスはよく使うので覚えておいてください。

「ポイント３」でリスナーをActorへ登録します。今回はImageですが、Image以外のActorでも構いません。


#実行！

![20141011-01.png](https://qiita-image-store.s3.amazonaws.com/0/46371/9b26f91d-bc90-8961-56ea-8bdf257545b2.png)


クリックやタッチした場合、重なっている部分は上にある画像(002)のが優先されている・・・と思います。

思うというのは、いまいち余白の部分がどの辺までなのか微妙にわかりにくいからです。どこまでがイベントの範囲、Actorのサイズなのかがわからないですね。


#クリック判定をわかりやすく

そこで以下の一行をそれぞれのImageのインスタンスの初期化のところに追加します。positionの設定の直後のところにでもおいてください。

```java

image.setDebug(true);
```

なお、この機能が使えるのはバージョンが比較的新しめのものが必要になるので、古いバージョンを利用している人はバージョンを上げましょう。

Gradleを利用している場合はバージョンを1.4.1に設定、そうでない場合は以下のところから直接とってこれます。置き換えましょう。
http://libgdx.badlogicgames.com/releases/

実行すると以下のようになります。

![20141011-02.png](https://qiita-image-store.s3.amazonaws.com/0/46371/701e5d03-e14f-68be-d6a2-f83a149433a7.png)


これで判定がばっちりですね。重なっている部分は上の方が優先されてクリックされているのがわかると思います。


#さらに回転と拡大縮小を加える

回転や拡大縮小をした場合はどうなるでしょうか？以下のコードを002のイメージにのみ追加して実行してみます。

```java

image.setRotation(-45);
image.setScale(0.75f);
```
![20141011-03.png](https://qiita-image-store.s3.amazonaws.com/0/46371/61ef1ec2-caf1-d848-a3c2-255a5b238e44.png)


境目を重点的にクリックしてみてください。ちゃんと回転後、拡大縮小後のサイズで計算されているのがわかりますね。

キーボードを使いたい場合はInputListenerをstageに設定してkeyupやkeydownのイベントを利用するとよいでしょう。

ここまでの記事で、画像の描画、クリック（タッチ）イベントの実装ときました。アドベンチャーやRPGはもう作れますね。