ホームへ戻る

s2.8 障害物を作る.2


 では実際に障害物を作ってみましょう。
・・と、その前に障害物のあたり判定を計算する準備をします。
簡単に障害物との当たり判定や回転を計算するにはこれだけメソッドが必要そうです。
中身は後で書くことにしましょう。

↓DiagramCalcr.java
(新規追加
)
public class DiagramCalcr {
        
        //centerを中心に角度ang、頂点群ptを回転する
        public static void RotateDiagram(PointF pt[], final PointF center, final float ang){
        }
        
        //rotaPtを中心に角度ang、origPtを回転する
        public static void RotatePt(PointF rotaPt, final PointF origPt, final float ang){
        }
        
        //頂点群ptの線分とcirが接触していたらその接触しているベクトルをverに格納して返す
        public static boolean Collision( PointF pt[], final Circle cir, Vec vec ){
                return false;
        }

        //線分lineと円cirが当たっていればtrueを返す
        public static boolean CollisionLC(Line line,Circle cir){
                return false;
        }
        
}


回転させる系のメソッドとあたり判定を計算する系のメソッド群で、いわゆるstatic utilsクラスです。

線分を表すLineクラスを追加しておきます。

↓Line.java (新規追加)

public class Line {   // 線分定義構造体
        public float _x,_y;   // x,y:始点座標
        public float _sx,_sy;   // sx,sy:サイズ
        Line( float x1, float y1, float x2, float y2 ){
                _x  = x1;
                _y  = y1;
                _sx = x2-x1;
                _sy = y2-y1;
        }
        public Line() {
                _x = _y = _sx = _sy = 0;
        }
};


数学的な面倒な計算は後回しにしましょう。

次に、この関数を Barricade クラスから呼んでみます。

↓Barricade.java
(
赤字部一部変更)
public class Barricade extends Task {
        public enum eType{
                OUT,
                GOAL
        }
        
        protected PointF  _center = new PointF(0,0);            //図形の中心点
        protected PointF  _pt[];                                                        //図形の頂点
        protected Paint   _paint = new Paint();                         //ペイント
        protected eType   _type = eType.OUT;                            //タイプ(当たるとアウトな壁、ゴールの壁、等)
        protected float   _rotaSpeed = 0;                                       //回転スピード

        //コンストラクタ。 type=タイプ、 n=頂点の数、 conf=設定情報
        public Barricade(int n, BConf conf){
                if( conf != null ){
                        _rotaSpeed      = conf.speed;   //回転スピード
                        _type           = conf.type;    //物体のタイプ
                }
                switch(_type){
                case OUT:       //接触してアウトな物
                        _paint.setColor(Color.RED);
                        break;
                case GOAL:      //接触してゴールな物
                        _paint.setColor(Color.GREEN);
                        break;
                }
                _pt = new PointF[n];    //頂点配列を作る
                for( int i=0; i<n; i++ ){
                        _pt[i] = new PointF();  //頂点を作る
                }
        }

        //更新する
        public boolean onUpdate(){
                if( _rotaSpeed != 0 ){  //回転するなら
                        DiagramCalcr.RotateDiagram( _pt, _center, _rotaSpeed ); //頂点リスト(_pt)を_centerを中心に回転する
                }
                return true;
        }

        //接触しているかを問う。円cirが線分vecと接触していれば接触した物体のタイプを返す。接触していなければNOを返す
        public Def.eHitCode isHit( final Circle cir, Vec vec ){
                if( DiagramCalcr.isHit( _pt, cir, vec ) == true ){//頂点群_ptが示す各辺と円cirが接触していればベクトルをvecに入れてtrueを返す
                        switch(_type){
                        case OUT://アウトな線なら
                                return Def.eHitCode.OUT;
                        case GOAL://ゴールな線なら
                                return Def.eHitCode.GOAL;
                        }
                }
                return Def.eHitCode.NO; //何も接触していない
        }
        
        //描画する
        public void onDraw(Canvas c){
                if( _pt.length < 1 ){   //頂点が1未満なんて図形はありえない
                        return;
                }
                Path path = new Path();
                path.moveTo(_pt[0].x, _pt[0].y);        //パスの初期位置をセット
                for( int i=0; i<_pt.length; i++ ){
                        path.lineTo(_pt[i].x, _pt[i].y);        //頂点の位置へラインを引いていく
                }
                c.drawPath(path, _paint);       //引いたラインを描画する
        }
}


ではいよいよ実際に Barricade を継承して障害物を作ります。まず四角形にしてみましょう。
・・といっても必要なことはほとんど親クラスでやっているので、コンストラクタに座標を設定するコードを書けば良いだけです。

↓BarricadeSquare.java (新規追加)
public class BarricadeSquare extends Barricade {

        public BarricadeSquare( float x, float y, float w, float h, BConf conf ){
                super(4,conf);
                _pt[0].x  = x;          _pt[0].y = y;
                _pt[1].x  = x+w;        _pt[1].y = y;
                _pt[2].x  = x+w;        _pt[2].y = y+h;
                _pt[3].x  = x;          _pt[3].y = y+h;
                _center.x = x+w/2;
                _center.y = y+h/2;
        }
        
}


障害物の生成は今まで通りGameMgrが行います。
GameMgrはどんな形の障害物であるか知る必要はありませんが、あたり判定を計算する都合上、持っている物が障害物であるかどうか知る必要があるので、
障害物は _barrList に追加します。
ただ障害物もタスクを継承しているので、更新や描画はタスクリストに任せます。

↓GameMgr.java (
赤字部変更)
public class GameMgr {

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

        GameMgr() {
                _barrList.add(new BarricadeSquare(  0,  0,480, 20, null));// 画面4隅に四角形を配置
                _barrList.add(new BarricadeSquare(  0,  0, 20,800, null));// コンフィグを特に設定しない時は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)));// 中央に回転するバー(反時計回り)

                for (Barricade bar : _barrList) {
                        _taskList.add(bar);     //タスクリストに障害物を追加
                }

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

        public boolean onUpdate() {
                for (int i = 0; i < _taskList.size(); i++) {
                        if (_taskList.get(i).onUpdate() == false) { // 更新失敗なら
                                _taskList.remove(i); // そのタスクを消す
                                i--;
                        }
                }
                return true;
        }

        public void onDraw(Canvas c) {
                c.drawColor(Color.WHITE); // 白で塗りつぶす
                for (Task task : _taskList) {
                        task.onDraw(c);// 描画
                }
        }

}


実行結果を見たら分かる通り、画面4隅に四角形を配置し、中央に回転するバーを2つ設置しています。
この辺の座標は複雑になると訳が分からなくなりますが、それはゲーム制作における必然・・。
本格的なゲームを作る時は、どんなゲームでもまず制作支援ツールを作ることからはじまります。
しかし今回はそんなことしたくないので、頑張って手打ちします。
ガッツリ作りたい時はマップ作成エディタを先に作ると良いでしょう。

このプログラムを実行してもまだバーは回転しません。
まだDiagramCalcr の中身が空だからですね。
次の章から中身を書いていきましょう。

実行結果


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

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


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 -