忍者ブログ
なんとなくだらだらと。方向性はまだ決まってない。 当方のプログラムでは、山田巧さん作成のDXライブラリを利用させていただいてます。 本サイト http://homepage2.nifty.com/natupaji/DxLib/index.html DX Library Copyright (C) 2001-2008 Takumi Yamada.
[49] [48] [47] [46] [45] [44] [43] [42] [41] [40] [39]
×

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

気になってたAIを整備してみた。
ゴールキーパーは自分のゴールを守り、他のプレイヤーは一番近いヤツにボールを追わせる。

あとはAIを整備していけばそれなりに見られるようになる予感。
そこ以外は、もう足すものも無い引くものもない、ひじょうに原理主義な俺っぽいプログラム。

画面SSは代わり栄えしないなあ。



v005

ダウンロード http://hiyayakko.sarashi.com/SimpleSoccer/SC07.zip (2009.08.15)



ブログ書くためじゃなく、ホントに試行錯誤しながら余裕無いプログラム書いてるんで
動くようになったときに、どこをどこまで触ったのかほとんど覚えてない。


どのプレイヤーを動かすかを決めたりする、総合監督的な位置の GamePlay() 関数を
ばっさり作り直したような気がする。

main.cpp

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.getBx(),ball.getBy());
            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();
            } else {
                if(ball.getBx()>200)player[i].GoHomePos();
            }
        }
    }
    if(bc!=-1) player[bc].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
    if(rc!=-1) player[rc].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());

    // プレイヤーの移動処理
    for(i=0;i<10;i++){
        if(player[i].getPos()==GOALKEEPER){
            if(Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy())<6400){
                player[i].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
                // ゴールキーパーだけ、守備範囲を広く取る
            }
        } else if(Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy())<500)
            player[i].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());

        player[i].Move();

        // ボールを蹴られる位置にいるか。
        dist = Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy());
        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);
    }
}




まずは、両軍からボールにいちばん近い人を探す。
rc はRed側から選ばれた人、rc_dist はその人とボールとの距離。blue側も同じく。
プレイヤー番号に -1 、距離に999999とか、ありえない数字を設定しておく。
ところで、red_C???? Cって何でつけたんだっけ?

で、for 文で全員ボールからの距離を計る。
ゴールキーパー以外で最もボールに近い存在なら、プレイヤー番号と距離を書き換える。
赤軍と青軍で同じような処理を書くのが気に入らない。

ゴールキーパーの場合は、単純にボールの横軸だけ見てゴールから遠そうなら自分の
ポジションに戻ろうとするだけ。

これで、青軍赤軍からそれぞれ最もボールに近いプレイヤーが追っかけ組に選ばれるわけだ。


今度はホントの本番の移動処理。
もういちど全プレイヤー for で判定する。
ゴールキーパーは平方距離で6400、その他のプレイヤーは500より近いところに
ボールが来れば、 ボールを追いかけることにする。
ゴールキーパーの守備範囲がとんでもなく広い範囲に見えるけど、6400=80×80、ちょうど
画面中央にある円と同じ程度の広さだ。
プレイヤーは2500の円、50×50で四角マスの真ん中に立てばちょうど納まる円の広さが
自分の守備範囲だった はずなんだけど、いつのまにか守備範囲狭くなってるなあ。

で、そんなこんなでプレイヤーが動いて、ボールの近くにいたら問答無用で相手ゴール側に
蹴り返す。
赤軍も青軍も同じ思考回路で動いてるから、いつもいっしょに動くんだよなあ。
で、青軍が蹴る→赤軍が蹴るの判定順だと、いつでも赤軍有利な状況になってしまう。
ボールのスピードにちょっと注目して、蹴った瞬間のスピードには対応できないようにしてみた。

いろいろあってゴールキーパーは例外にしたけど。
そして、ゴールキーパーの蹴り返し判定範囲を拡大し、蹴る力もかなり大きくした。超ひいき。


赤軍青軍ゴールキーパーそれ以外で4通りの判定押し込んでるから、ちょっと単調に長い。
どうにかすれば、もうちょっとすっきりするとは思うんだけど。



なんか、ぼーっと見てて楽しい。
ゲームで遊ぶ人が介入しなくてもいいような感じ。環境プログラム。スクリーンセーバー。
プログラム的に青有利なはずだけど、絶対的な差がつくわけでもない。
一時的に1.5倍ぐらいの差が出ることはあっても、いつのまにか収束してる。
ゲームバランスも糞も無いはずなのに、自分の知らないところで神の手が動いてる。


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
アクセス解析
カウンター