今日のlibGDX(20150525):E. 開発記 1 ボールと跳ね返る処理

今日のlibGDX目次

http://snoopopo.hatenablog.com/entry/2015/04/27/220545

今日のテーマ:E. 開発記 1 ボールと跳ね返る処理

今回からlibGDXを使った簡単なミニゲームを作っていきます。

同時に、id:jtakaoka さんにコメントを頂きまして、libgdxの作者のひとがlibGDXを使って作ったゲームがgithubに公開されているとの情報を頂いたので、 それを参考にしながらいきます!

今回はボールを表示して画面の中で跳ね返る処理までです。

libgdx作者の方が作ったゲーム.

https://github.com/badlogic/theplanethatcouldntflygood

作るゲームについて

バウンドするボールを落とさないようにしながら、そのボールでターゲットのブロックを壊す…という昔からよくあるゲームを作ることを目指していきます.

オリジナル要素は、ひと通りできてから取り込んでいこう.

とりあえず作るソース

まあ名前は何でもいいと思うけど、今までこれでやっていたので今回はそのまま流用します。

今までのとりあえずやってみた編では、ApplicationListener の実装クラスを用意していたけど、 デモソースで、

com.badlogic.gdx.ApplicationAdapter という実装してるけど、処理が何も書かれてないクラスを継承していて、便利そうなので今回のMainLisnerはこいつを継承します。

・MainLisner.java

import com.badlogic.gdx.ApplicationAdapter;
public class MainLisner extends ApplicationAdapter {}

あと、デスクトップ専用のMainLisnerを呼ぶためのmainメソッドを持ったクラスを作ります。

こちらもデモソースをまねて、今回は、

com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration クラスを使って設定をクラス化しておきます。 といっても、今はwindowのサイズぐらいですが。

・Main.java

public class Main {
    public static void main (String[] arg) {
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        config.width = 800;
        config.height = 480;
        new LwjglApplication(new MainLisner(), config);
    }
}

・ボールクラス

このゲームとなるボールの情報を保持するクラスを作っときます。 今の想定だと、今いる座標を持っておけばいいくらいしか思いつかないけど、とりあえず用意。

ボールを表示する

まず、単純にボールとなる画像を表示します。

以下でやったScene2Dを使おう。

http://snoopopo.hatenablog.com/entry/2015/05/11/154201

・MainLisner.java

   Stage stage = null;

    @Override
    public void create() {
        stage = new Stage();
        Image boll = new Image(new Texture("img/boll.gif"));
        stage.addActor(boll);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0, 0, 0.2f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }

今回はボールの画像は適当です!

ボールを動かす処理のイメージ

動作をさせるのは、アクションを使う、というのは以前やりましたが、

僕のイメージは、アクションを使うのではなく、 ゲームループの中で描画する画像の位置をずらしていって、動いているように見せるというかんじです。(ひらしょー本とかやってて)

なのでそのイメージでいきます。

デモのプロジェクトを見るとわかりますが、

初回起動時にcreateメソッドが一度呼ばれていて そのあとはrenderメソッドが何回も呼ばれています。

今までわかってなかったけど、このrenderがゲームループの中で呼ばれるところっぽいので、 デモのソースを参考に今回はrenderメソッドの中でゲームの更新と描画を行います。

とりあえず動かす

setPositionの値を可変にして、座標をずらしてから描画します.

画面からはみ出すとまずいので、画面サイズ分以上は動かしません。

・MainLisner.java

   @Override
    public void render() {
        Gdx.gl.glClearColor(0, 0, 0.2f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        updateGame();
        draw();
    }

    private void updateGame() {
        stage.act(Gdx.graphics.getDeltaTime());

        // 座標を更新
        if (boll.getX() < 750) {
            boll.setX(boll.getX() + 2);
        }
        if (boll.getY() < 400) {
            boll.setY(boll.getY() + 2);
        }
        boll.getImage().setPosition(boll.getX(), boll.getY());
    }

    private void draw() {
        stage.draw();
    }

あたり判定と跳ね返る処理

壁にぶつかったら跳ね返ってほしいので、先ほどのupdateGameメソッドの処理を変えてきます。

・MainLisner.java

   private void updateGame() {
        stage.act(Gdx.graphics.getDeltaTime());

        // 座標を更新
        if (boll.getX() == 0 || boll.getX() == 750) {
            boll.setDirectionX(boll.getDirectionX() * -1);
        }
        boll.setX(boll.getX() + boll.getDirectionX());

        if (boll.getY() == 0 || boll.getY() == 430) {
            boll.setDirectionY(boll.getDirectionY() * -1);
        }
        boll.setY(boll.getY() + boll.getDirectionY());

        boll.getImage().setPosition(boll.getX(), boll.getY());
    }

壁というかウィンドウの大きさにぶつかったら、 移動方向を逆にします。

逆にするの部分は、移動方向を保持しておいて、-1 を掛算してあげれば、 移動方向が + なら - になって、 - なら + になるので、とりあえずできました。

    boll.setDirectionX(boll.getDirectionX() * -1);

もっとビット演算とかを使った方が処理が早いとかあるのかもしれないけど。

このあと

とりあえず、なんとかウィンドウの中でボールが跳ね返る部分ができたので 明日はボールがぶつかって壊す的の部分を作っていきます。