サイトのトップへ戻る

libGDX ドキュメント 日本語訳

サイト内検索

Scene2D Part 2 – アクション

LibGDX Scene2Dチュートリアルの第二パートでは、Actionについて見ていきます。 Actionとは、ゲームのactorに“仕事をしてもらう”ための便利な方法です(しかもこれを使うかどうかは完全に任意です)。

それでは、さっそく例を見てみましょう:

package com.gamefromscratch;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;


public class SceneDemo3 implements ApplicationListener {
    
    public class MyActor extends Actor {
        Texture texture = new Texture(Gdx.files.internal("data/jet.png"));
        public boolean started = false;

        public MyActor(){
            setBounds(getX(),getY(),texture.getWidth(),texture.getHeight());
        }
        
        @Override
        public void draw(Batch batch, float alpha){
            batch.draw(texture,this.getX(),getY());
        }
    }
    private Stage stage;
    
    @Override
    public void create() {        
        stage = new Stage();
        Gdx.input.setInputProcessor(stage);
        
        MyActor myActor = new MyActor();
        
        MoveToAction moveAction = new MoveToAction();
        moveAction.setPosition(300f, 0f);
        moveAction.setDuration(10f);
        myActor.addAction(moveAction);
        
        stage.addActor(myActor);
    }

    @Override
    public void dispose() {
    }

    @Override
    public void render() {    
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }
}

この例を実行すると、飛行機が(300,0)の位置までゆっくりと移動します。

MoveToActionReduced



このコードの大部分は前回のScene2D の例を使い回しているので、create()内の新しく追加した部分についてだけ説明します:

@Override
public void create() {        
    stage = new Stage();
    Gdx.input.setInputProcessor(stage);
    
    MyActor myActor = new MyActor();
    
    MoveToAction moveAction = new MoveToAction();
    moveAction.setPosition(300f, 0f);
    moveAction.setDuration(10f);
    myActor.addAction(moveAction);
    
    stage.addActor(myActor);
}

ここではMoveToActionを作成しています。MoveToActionは、割り当てられたActor を指定位置まで移動させます。 移動先の位置はsetPosition()メソッドを使って設定し、setDuration()を使ってactionの稼働時間を設定します。 addAction()を使ってActor に対してaction を割り当てます。 全てのactionはActionクラスを継承しており、 一方でMoveToAction はTemporalActionを継承しています。TemporalActionは稼働時間を持つaction です。 MoveToActionの他にも、MoveByAction, ScaleToAction, ColorAction, DelayAction, RepeatAction, RotateByAction,などいくつかあります。

注意すべき重要な点が一つあります。 前回のScene2D チュートリアルにて、 カスタムActor のMyActor ではact メソッドの上書きを行いました。 Actorに繋がっている全てのAction を更新するのは、Actor のact()メソッドです。 したがって、独自のActor クラスを作成した場合は、そのクラスの親のact()を呼び出すか、以下のように割り当てられている全てのAction を手動で呼び出すようにしてください:

@Override
public void act(float delta){
    for(Iterator<Action> iter = this.getActions().iterator(); iter.hasNext();){
        iter.next().act(delta);
    }
}

複数のactionを実行する場合は、以下のようにします:

MoveToAction moveAction = new MoveToAction();
RotateToAction rotateAction = new RotateToAction();
ScaleToAction scaleAction = new ScaleToAction(); 

moveAction.setPosition(300f, 0f);
moveAction.setDuration(5f);
rotateAction.setRotation(90f);
rotateAction.setDuration(5f);
scaleAction.setScale(0.5f);
scaleAction.setDuration(5f);

myActor.addAction(moveAction);
myActor.addAction(rotateAction);
myActor.addAction(scaleAction);

stage.addActor(myActor);

実行すると以下のように表示されます:

RotateScaleMoveActionReduced

ご覧の通り、既定では全てのactionは同時に実行されます。

注意すべき重要な点が一つあります。 これまでに使用しているMyActor のdraw()メソッドでは、既定では回転処理と拡大縮小処理を描写することができません。 上記のように回転/拡大縮小処理の描写を有効にしたい場合は、以下のように draw()を少し変更する必要があります。:

@Override
public void draw(Batch batch, float alpha){
    batch.draw(texture,this.getX(),getY(),this.getOriginX(),this.getOriginY(),this.getWidth(),
            this.getHeight(),this.getScaleX(), this.getScaleY(),this.getRotation(),0,0,
            texture.getWidth(),texture.getHeight(),false,false);
}

actionを遅らせたり、順番通りに実行したいという機会はきっとたくさんあることでしょう。 幸い、LibGdx はまさにこれをサポートしています。 Actorを拡大縮小し、その後回転させ、それから移動させたい場合は、以下のようにSequenceAction を使ってこれを行えます:

final MyActor myActor = new MyActor();

SequenceAction sequenceAction = new SequenceAction();

MoveToAction moveAction = new MoveToAction();
RotateToAction rotateAction = new RotateToAction();
ScaleToAction scaleAction = new ScaleToAction(); 

moveAction.setPosition(300f, 0f);
moveAction.setDuration(5f);
rotateAction.setRotation(90f);
rotateAction.setDuration(5f);
scaleAction.setScale(0.5f);
scaleAction.setDuration(5f);

sequenceAction.addAction(scaleAction);
sequenceAction.addAction(rotateAction);
sequenceAction.addAction(moveAction);


myActor.addAction(sequenceAction);

stage.addActor(myActor);

全てのactionを SequenceActionへ追加し、それから各actionを順々に実行しているだけです。

以下のように Actionsを静的にインポートすることで:

import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;

複数のactionを連鎖させることができ、前述の動作を実現することができます:

myActor.addAction(sequence(scaleTo(0.5f,0.5f,5f),rotateTo(90.0f,5f),moveTo(300.0f,0f,5f)));
stage.addActor(myActor);

もしくは、以下のようにしてactionを並行して実行することができます。:

myActor.addAction(parallel(scaleTo(0.5f,0.5f,5f),rotateTo(90.0f,5f),moveTo(300.0f,0f,5f)));
stage.addActor(myActor);


他にも、経過時間の値を変更できるIntActionやFloatAction、遅延させた後にactionを実行するためのDelayAction 、Action を何度も実行するためのRepeatActionといったいくつかのactionがあります。 ですがそれらactionは全て同じ基本レイアウトに従っているので、今のところは簡単に理解することができるでしょう。 最後の指摘事項として、全てのactionは プールすることが可能です。 つまり、何度もactionを割り当てるのではなく、actionのプールを使い回すことができるということです。 以下がMoveToActionをプールする際の一例です:

final MyActor myActor = new MyActor();
Pool<MoveToAction> actionPool = new Pool<MoveToAction>(){
    protected MoveToAction newObject(){
        return new MoveToAction();
    }
};

MoveToAction moveAction = actionPool.obtain();
moveAction.setDuration(5f);
moveAction.setPosition(300f, 0);

myActor.addAction(moveAction);

stage.addActor(myActor);


また、任意のコードでactionを記述することもできます。 前述の例で考えてみましょう。MoveToAction が完了した時にログを出力したいとします。 以下のようにしてこれを行うことができます:

myActor.addAction(sequence(moveAction,
        run(new Runnable(){
            @Override
            public void run() {
                Gdx.app.log("STATUS", "Action complete");
            }
            
})));

Runnable action は、実行されるとrun メソッド内に記述されるコードを実行するだけです。 Actionについての説明はこれで終わりです。Action単体ではとても単純な動きしかしませんが、それらを組み合わせることでとても複雑な動作をすることができます。