ホームへ戻る

s2.12 ゲームオーバー画面を作る


 接触判定の計算式が既に入っていますから、GameMgrは一つずつ物体とプレイヤーが接触していないか調べて、
接触していればゲームオーバー状態にして「GameOver」を表示すれば良いだけです。

ではGameMgr.javaを変更してみましょう

↓GameMgr.java (
赤字部 変更)

public class GameMgr {
        
        private enum eStatus{//状態
                NORMAL,//普通
                GAMEOVER,//ゲームオーバー
                GAMECLEAR//ゲームクリア
        };

        private static final float PI = (float) Math.PI;
        private ArrayList<Barricade> _barrList = new ArrayList<Barricade>();//障害物リスト
        private LinkedList<Task> _taskList = new LinkedList<Task>();// タスクリスト
        private eStatus _status = eStatus.NORMAL;//状態
        private Player _player;

        GameMgr() {
                _barrList.add(new BarricadeSquare(  0,  0,480, 20, null));// 画面4隅に四角形を配置
                _barrList.add(new BarricadeSquare(  0,  0, 20,800, null));
                _barrList.add(new BarricadeSquare(460,  0, 20,800, null));
                _barrList.add(new BarricadeSquare(  0,780,480, 20, null));

//              _barrList.add(new BarricadeSquare(0, 390, 480, 20, new BConf(+PI / 180)));// 中央に回転するバー(時計回り)
//              _barrList.add(new BarricadeSquare(0, 390, 480, 20, new BConf(-PI / 180)));// 中央に回転するバー(反時計回り)
//              _barrList.add(new BarricadeTriangle(240, 400, 200, new BConf(+PI / 180)));// 中央に回転する三角形(時計回り)
//              _barrList.add(new BarricadeStar(240, 400, 80, 220, new BConf(+PI / 180)));// 中央に回転する星(時計回り)
                
                for (Barricade bar : _barrList) {
                        _taskList.add(bar);     //タスクリストに障害物を追加
                }

                _player = new Player();
                _taskList.add(_player);
                _taskList.add(new FpsController());
        }

        private boolean Collision(){//衝突判定
                Vec vec = new Vec();
                final Circle cir = _player.getPt();//プレイヤーの中心円を取得
                for(Barricade barr : _barrList){//障害物の数だけループ
                        Def.eHitCode code = barr.isHit(cir, vec);//接触判定
                        switch(code){
                        case OUT://接触したものが「アウト」なら
                                _status = eStatus.GAMEOVER;//アウト状態に
                                return true;
                        }
                }
                return false;
        }
        
        public boolean onUpdate() {
                if( _status != eStatus.NORMAL ){//ゲームの状態が通常でないなら計算しない
                        return true;
                }
                if( Collision() ){//衝突判定 衝突したならメソッドを抜ける
                        return true;
                }
                for (int i = 0; i < _taskList.size(); i++) {
                        if (_taskList.get(i).onUpdate() == false) { // 更新失敗なら
                                _taskList.remove(i); // そのタスクを消す
                                i--;
                        }
                }
                return true;
        }

        private void drawStatus(Canvas c){//状態を表示する
                switch( _status ){
                case GAMEOVER:
                        Paint paint = new Paint();
                        paint.setTextSize(80);
                        paint.setColor(Color.BLACK);
                        c.drawText("GameOver", 40, 100, paint);
                        break;
                }
        }
        
        public void onDraw(Canvas c) {
                c.drawColor(Color.WHITE); // 白で塗りつぶす
                for (Task task : _taskList) {
                        task.onDraw(c);// 描画
                }
                drawStatus(c);//状態を表示する
        }

}


_status変数を追加し、今どのような状態なのかを格納します。
NORMALがゲーム中、接触するとGAMEOVERにします。

プレイヤーを変数に別途持つようにしたのは、onUpdate内でプレイヤーのあたり判定範囲を取得したいからです。

ゲームオーバー中はプレイヤーや障害物の計算をしませんから、onUpdateをすぐに抜けます。
あたり判定を計算するCollisionメソッドでは、プレイヤーのあたり判定円に対して総当たりで衝突判定を行います。
一つでも接触していればゲームオーバーにして、メソッドを抜けます。

ゲームオーバーの表示はdrawStatusメソッドで行っています。
ゲームオーバー状態の時だけ「Gameover」を表示します。

次にプレイヤーのあたり判定範囲円を取得できるようにします。

↓Player.java (
赤字部変更)

public class Player extends Task {
        private final static float MAX_SPEED = 20;              //移動する最大スピード
        private final static float SIZE = 20;                   //自機の大きさ
        private Circle _cir = null;                     //自機の円
        private Paint _paint = new Paint();     //描画設定
        private Vec _vec     = new Vec();       //自機の移動ベクトル
        private Vec _sensorVec = new Vec();     //センサーのベクトル
        
        public Player(){
                _cir = new Circle( 240, 400, SIZE );    //(240,0)の位置にSIZEの大きさの円を作る
                _paint.setColor(Color.BLUE);            //色を青に設定
                _paint.setAntiAlias(true);                      //エイリアスをオン
        }
        
        //自機中心円を取得する
        public final Circle getPt(){
                return _cir;
        }

        // ベクトルをセットする
        private void setVec(){
                float x = -AcSensor.Inst().getX()*2;    //加速度センサーの情報を取得
                float y =  AcSensor.Inst().getY()*2;
                _sensorVec._x = x < 0 ? -x*x : x*x;     //2乗して変化を大袈裟にする
                _sensorVec._y = y < 0 ? -y*y : y*y;     //2乗すると+になるので、負ならマイナスを付ける
                _sensorVec.setLengthCap(MAX_SPEED);     //ベクトルの大きさが最大スピード以上にならないようにする           
                _vec.blend( _sensorVec, 0.05f );        //センサーのベクトル方向に実際の移動ベクトルを5%近づける
        }

        // 移動ベクトルの向いている方に動かす
        private void Move(){
                _cir._x += _vec._x;     //移動ベクトル_vecが指す方向に移動させる 
                _cir._y += _vec._y;
        }
        
        @Override
        public boolean onUpdate(){
                setVec();       //移動ベクトルをセットする
                Move();         //移動ベクトルが向いている方に動かす
                return true;
        }

        @Override
        public void onDraw( Canvas c ){
                c.drawCircle(_cir._x, _cir._y, _cir._r, _paint);
        }

}


getPtメソッドを追加し、中心円を返すようにしただけです。
この値は他のクラス内で変更されないようにfinalにしておきます。

さて、これで壁に接触するとゲームオーバーになるようになりました。

実行結果


この章のプロジェクトをダウンロード

→分からないことがあれば掲示板で質問して下さい


Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.

- Remical Soft -