ユーザーID パスワード

技術情報

  • FAQ よくある質問
  • 個人ユーザー向けサービスのお手続きについて
  • M2Mソリューション
  • (PR)FAQを利用してお問い合わせコスト削減

コード&コラム

第11回
ARゲームを作ってみよう(3)


前へ 1 |2 |3 |4

Step3 OpenGLのタップ処理とスコア表示

敵が視界に入り(画面に写っている)状態でそのオブジェクトをタップすると敵を倒せるという処理を追加します。加えて、ゲーム開始前/プレイ中/ゲームオーバーとなる状態遷移を実装し、ゲームとして完成させましょう。

1.敵を倒す処理の追加
処理の流れとしては、タップされた座標の取得、OpenGLで使われる3次元座標から、画面上の2次元座標に変換し、タップされた座標と照らし合わせるというものになります。

タップされた座標の取得はARGame.javaで行います。

// 画面に触れたときに呼び出される関数
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mGLRenderer.onTouch((int) event.getX(), displayY
                    - (int) event.getY());
            break;
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_CANCEL:
            break;
        }
        return super.onTouchEvent(event);
    }

取得した座標は画面左下を原点とした座標になっています。OpenGLでは、画面左上を原点とした座標になるため、その変換を行なって座標の受け渡しを行います。

GLRendererに以下のようなメソッドを追加します。座標の取得と共に、画面にタッチされたかを判定するフラグも作成します。

public void onTouch(int x, int y) {
        isTouched = true;
        touchX = x;
        touchY = y;
    }

作成したフラグを利用してonDrawFrame中の処理で当たり判定を行う処理を呼びします。

            ・・・(中略)・・・
            if (isTouched) {
                isTouched = false;
                slap(gl);
            }
            ・・・(中略)・・・

当たり判定を行う処理は以下のようになります。

            private void slap(GL10 gl) {
        int color[] = new int[1];
        ByteBuffer buf = ByteBuffer.allocateDirect(4);
        buf.order(ByteOrder.nativeOrder());
        gl.glReadPixels(touchX, touchY, 1, 1, GL10.GL_RGBA,
                GL10.GL_UNSIGNED_BYTE, buf);
        buf.asIntBuffer().get(color);
        if (color[0] != 0) {
            vibrator.vibrate(100);
            enemy.initPosition();
            score += 1;
        }
    }

当たり判定は、画面中に描画されるOpenGLの画素を取得し、その色を判別することで行います。ここでは、タップされた座標の画素を取得し、背景でなければ撃墜処理を起こっています。撃墜処理は、端末を振動させる、敵を初期値(ランダム)に移動する、スコアを増やすといったものになっています。

2.状態遷移の作成
ゲームの状態遷移を行う処理を追加します。onDrawFrame内の処理をstateの値によって変化させることで実現します。

            switch (state) {
        case STATE_START:
            if (isTouched) {
                isTouched = false;
                state = STATE_PLAY;
            }
            break;
        case STATE_PLAY:

            ・・・(中略)・・・
            さきほど記述したonDrawFrameの内容
            ・・・(中略)・・・


            break;
        case STATE_GAMEOVER:
            if (isTouched) {
                isTouched = false;
                initialize();
            }
            break;
        }
        

STATE_STARTでは画面がタップされたらゲームを開始するようにします。STATE_GAMEOVERでは、内容の初期化を行います。初期化の内容は以下のようになります。

            private void initialize() {
        enemy = new Enemy();
        state = STATE_START;
        score = 0;
    }

ゲームの処理はひと通り完成しました。最後に、スコアの表示などを行う部分を作成しましょう。

3.スコアの表示
スコアの表示は3Dではないため、ARView.java内でCanvasクラスを使用して行います。ARViewの内容は以下のようになります。

            public class ARView extends View {

    private int displayX;
    private int displayY;

    private int mScore;
    private int mState;

    privat ARView(Context context) {
        super(context);
        // 画面サイズの取得
        Display disp = ((WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        displayX = disp.getWidth();
        displayY = disp.getHeight();
        mState = GLRenderer.STATE_START;
    }

    // (1)描画処理
    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        // スコアの描画
        paint.setTextSize(16);
        paint.setColor(Color.WHITE);
        canvas.drawText("SCORE:" + Integer.toString(mScore), 10, 20, paint);
        
        if(mState == GLRenderer.STATE_START){
            String str = new String("TAP TO START!");
            paint.setTextSize(32);
            paint.setColor(Color.WHITE);
            float textWidth = paint.measureText(str) / 2;
            canvas.drawText(str, displayX/2-textWidth, displayY/2, paint);
        }else if (mState == GLRenderer.STATE_GAMEOVER){
            String str = new String("GAME OVER");
            paint.setTextSize(32);
            paint.setColor(Color.WHITE);
            float textWidth = paint.measureText(str) / 2;
            canvas.drawText(str, displayX/2-textWidth, displayY/2, paint);
        }

    }

    // (2)更新処理の呼び出し
    public void drawScreen(int state, int score) {
        // 状態の更新
        mState = state;
        mScore = score;
        /// onDrawを呼び出して再描画
        invalidate();
    }

(1)描画処理
ゲームの状態によって描画内容を変化させます。スコアの描画に加えて、STATE_STARTでは、画面に触れるとゲームが開始される旨を、STATE_GAMEOVERではGAME OVERと表示します。

(2)更新処理の呼び出し
各パラメータを引渡、画面の再描画を行います。

ARView.javaの処理を行うために、GLRendererに情報を取得するメソッドを加えます。

            public int getState() {
        return state;
    }

    public int getScore() {
        return score;
    }

これらの処理を利用して、ARGame.javaのonSensorChangedメソッド内で、画面の更新処理を行うようにします。

            ・・・(中略)・・・
            mGLRenderer.setState(actual_orientation[0], actual_orientation[2]);

            arView.drawScreen(mGLRenderer.getState(), mGLRenderer.getScore());
        }

これでARGame.javaは完成です。実際にプレイすると、以下のような画面が現れます。 実際には背景にカメラ画像が映るので、自分の周りにいる見えない敵がこちらに近づいてくるような形になります。

以上でARアプリの作成は終了です。ここまで3回にわたってARを取り上げてきましたが、いかがだったでしょうか。ARといってもマーカー検出、位置情報、センサー利用やOpenGLの利用など、様々なアプローチがあることがお分かり頂けたと思います。工夫次第で面白いアプリが作成できると思いますので、是非皆さんも考えてみて下さい。

次回は作成したアプリをAndroid マーケット™ に登録するという内容を取り挙げます。 12回に渡る連載も、次回で最終回となります。最後までよろしくお願いします。



今回コラムで使用したプログラムはこちらとからダウンロード出来ます。


第11回 ARゲームを作ってみよう(3)
 Step1 Android OpenGLの導入とセンサーによる紐付け
 Step2 敵の動作と終了判定
 Step3 OpenGLのタップ処理とスコア表示

(文責:株式会社ベストクリエイト)

■免責事項

本コラム内で提供する情報のご利用は、利用者ご自身の責任において行われるものとします。本コラムで提供される各種情報については、慎重に作成、管理をしておりますが、当社は、これらの情報の正確性、有用性、完全性等を保証するものではありません。当社は、利用者がこれらの情報をご利用になったこと、またはご利用になれなかったことにより生じたいかなる損害についても責任を負いません。
本コラムで提供される各種情報に関し、利用者と他の利用者あるいは第三者と紛争が生じた場合、利用者は自己の費用と責任においてこれを解決するものとし、当社に損害を与えないものとします。
当社は、本コラムに掲載する情報の全部又は一部を予告なく変更する場合がございます。また、本コラムの運用を休止または停止する場合がございます。
当社は、理由の如何を問わず本コラムの提供が遅延し、または中断したことに起因して利用者または第三者が被った被害について、一切の責任を負いません。
当社は、利用者が、本コラムで提供している情報からリンクが張られている第三者のウェブサイト、または本サイトへリンクを張っている第三者のウェブサイトから取得された各種情報のご利用によって生じたいかなる損害についても責任を負いません。
通信環境、利用者のコンピューター環境その他の理由により、本コラムが正常にご利用できない場合がございます。
当社は、本コラムから入手された文書・写真・イラスト・動画・リンクその他各種情報(以下総称して「情報」といいます)に関して技術的サポート、機能改善等のいかなる技術的役務の提供もいたしかねますので、あらかじめご了承ください。
本掲載内容・各種名称は公開日時点のものであり、団体・サービス・ツール等の名称が変更されることがあります。

サンプルコード

第1回 リファレンスコード(文字列編)

第2回 リファレンスコード2(グラフィックス編)

第3回 リファレンスコード3(タッチイベント編)

第4回 リファレンスコード4(チェックボックス/ラジオグループ編)

第5回 リファレンスコード5(スピナー編)

第6回 リファレンスコード6(サウンド/ムービー編)

第7回 リファレンスコード7(トースト編)

第8回 リファレンスコード8(Google Maps API利用編)

第9回 リファレンスコード9(SQLite編)

第10回 リファレンスコード10(音声認識編)

第11回 リファレンスコード11(日付/時刻ダイアログ編)

第12回 リファレンスコード12(Bluetooth編)