忍者ブログ
なんとなくだらだらと。方向性はまだ決まってない。 当方のプログラムでは、山田巧さん作成のDXライブラリを利用させていただいてます。 本サイト http://homepage2.nifty.com/natupaji/DxLib/index.html DX Library Copyright (C) 2001-2008 Takumi Yamada.
[1] [2] [3] [4] [5] [6] [7] [8]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

プログラムが綺麗にならないか見直す。

main.cpp


// 2点間の平方距離を求める(ax,ay,bx,byの4点指示)
int Distance(int ax, int ay, int bx, int by)
{
    return (ax-bx)*(ax-bx) + (ay-by)*(ay-by);
}
// 2点間の平方距離を求める(プレイヤーとボール)
int Distance(Player &p, Ball &b)
{
    int ax,ay,bx,by;
    ax = p.getPx();
    ay = p.getPy();
    bx = b.getBx();
    by = b.getBy();
    return Distance(ax,ay,bx,by);
}
// 2点間の平方距離を求める(プレイヤーとボール予想位置)
int DistanceY(Player &p, Ball &b)
{
    int ax,ay,bx,by;
    ax = p.getPx();
    ay = p.getPy();
    bx = b.getYBx();
    by = b.getYBy();
    return Distance(ax,ay,bx,by);
}

void GamePlay()
{
    int i,dist;
    int rc=-1,bc=-1,rc_dist=999999,bc_dist=999999;

    for(i=0;i<10;i++)player[i].setStatus(WAIT);

    for(i=0;i<10;i++){
        // ゴールキーパー以外で、両軍ともにボール予測位置に一番近いプレイヤーを探す
        if(player[i].getPos()!=GOALKEEPER){
//          dist = Distance(player[i].getPx(),player[i].getPy(),ball.getYBx(),ball.getYBy());
            dist = DistanceY(player[i], ball);
            if(player[i].getTeam()==RED){
                if(dist<rc_dist){
                    rc=i;               // このプレイヤーが今のところ一番近い
                    rc_dist=dist;
                }
            } else {
                if(dist<bc_dist){
                    bc=i;               // このプレイヤーが今のところ一番近い
                    bc_dist=dist;
                }
            }
        } else {
        // ゴールキーパーは自分のエリアからある程度ボールが離れれば、自分のポジションに戻る
            if(player[i].getTeam()==RED){
                if(ball.getBx()<400)player[i].GoHomePos();
                if(ball.getArea() == Area::Red)
                    player[i].GoLocate(SUPPORT, ball.getKBx(), ball.getKBy());
            } else {
                if(ball.getBx()>200)player[i].GoHomePos();
                if(ball.getArea() == Area::Blue)
                    player[i].GoLocate(SUPPORT, ball.getKBx(), ball.getKBy());
            }
        }
    }
    // いちばん近いプレイヤーに目標地点に向かう指令を出す
    if(bc!=-1) player[bc].GoLocate(CHASE_BALL,ball.getYBx(),ball.getYBy());
    if(rc!=-1) player[rc].GoLocate(CHASE_BALL,ball.getYBx(),ball.getYBy());

    // プレイヤーの移動処理
    for(i=0;i<10;i++){
        if(player[i].getPos()==GOALKEEPER){
            // ゴールキーパーだけ、守備範囲を広く取る
//          if(Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy())<6400){
            if(Distance(player[i], ball)<6400){
                player[i].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
            }
        } else {
            if(player[i].getStatus()!=SUPPORT){
//              if(Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy())<1500)
                if(Distance(player[i], ball)<1500)
                    if(ball.getSpd()<2.0) player[i].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
                // プレイヤーが他のプレイヤーの近くにいるときは、その相手から遠ざかる方向へ動く
                for(int j=i+1;j<10;j++){
                    int mPx = player[i].getPx();
                    int mPy = player[i].getPy();
                    int yPx = player[j].getPx();
                    int yPy = player[j].getPy();
                    if(Distance(mPx,mPy,yPx,yPy)<100){
                        player[i].GoLocate(SUPPORT,mPx*2-yPx,mPy*2-yPy);
                        player[j].GoLocate(SUPPORT,yPx*2-mPx,yPy*2-mPy);
                    }
                }
            }
        }

        player[i].Move();

        // ボールを蹴られる位置にいるか。
//      dist = Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy());
        dist = Distance(player[i], ball);
        if(((player[i].getPos()==GOALKEEPER)&&(dist<81))||(dist<25)){
            if((player[i].getPos()==GOALKEEPER)||(ball.getSpd()<2.0)){
                // ボールの近くにいて、なおかつボールスピードが低いとき
                // スピード判定は、重なってるプレイヤー同士でもみもみして後攻有利になるので。
                if(player[i].getTeam()==BLUE) {
                    if(player[i].getPos()==GOALKEEPER) ball.Kick(600,GetRand(300),8.0);
                    else if(ball.getBx()>400) ball.Kick(600,GetRand(80)+110,6.0);
                    else ball.Kick(600,GetRand(300),4.0);
                } else {
                    if(player[i].getPos()==GOALKEEPER) ball.Kick(0,GetRand(300),8.0);
                    else if(ball.getBx()<200) ball.Kick(0,GetRand(80)+110,6.0);
                    else ball.Kick(0,GetRand(300),4.0);
                }
                for(int j=0;j<10;j++)player[j].setStatus(WAIT);
            }
        }
    }
                   
    // ボールの移動、ゴール処理
    if(ball.Move()){
        // ゴール!!
        if(ball.getBx()<300)game.addRedScore();
        else game.addBlueScore();

        // ボールを中央に戻し、プレイヤーも元のポジションに帰らせる
        for(int i=0; i<10; i++)player[i].GoHomePos();
        ball.Init(300,150);
        game.setState(GAMEINIT);
    }
}


Distance() 関数の呼び出しをちょっと変更してみた。
もともと、だらっと書くのが単調なんで関数にまとめたはずなのに、まとめてもまだ無神経に長い。
もう一声がんばることにした。

懸念してたのは、相手の組み合わせがどれだけ多くなるかわからなかったことだけど、
ここまで作って、「プレイヤーとボール」「プレイヤーとボール予想位置」「プレイヤー同士」の
3パターンになるので、それぞれ書き出してみる。

やってることは、呼び出したインスタンスから座標を引っ張り出して、ax ay bx by に分けて
いままでのDistance() 関数を再度呼び出す、なんかまわりくどいやり方。

これでも呼び出し元のほうがかなりすっきりと見える。
インスタンスそのものを渡すやり方、見た目にも矛盾なくきれいに映る。

ボールの実座標と予想位置でうまくオーバーロードする仕組みが思いつかなかったので
DistanceY() とかちょっと重い感じの別関数にしてしまった。

もしかして、
    Distance( player[i], ball, enum 実体 or 予想位置 )
の3パラメーターで呼ぶようにしても綺麗だったかな?



あと、この GamePlay() 関数、仕事しすぎ。
そろそろ、ちょっと分けること考えたほうがいい。
PR


忍者ブログ [PR]
カレンダー
11 2024/12 01
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
フリーエリア
バーコード
ブログ内検索
P R
アクセス解析
カウンター