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

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

ぼーっと見てたら、たまに敵味方でカップリング出来上がって、場外に消えていくときがある。
キャラを引き離すよりもボールを蹴る判定のほうを優先してるので、
きっちり2等辺3角形が出来て同じ距離という状況になったとき、過剰に寄り過ぎるのかしら?



v011





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


心底気が付かなかったけど、凡ミスのバグがあった。


main.cpp


    // プレイヤーの移動処理
    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(player[i].getStatus()!=SUPPORT){
                if(Distance(player[i].getPx(),player[i].getPy(),ball.getBx(),ball.getBy())<1500)
                    if(ball.getSpd()<2.0) player[i].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
                // プレイヤーが他のプレイヤーの近くにいるときは、その相手から遠ざかる方向へ動く
                for(int j=0;j<10;j++){
                    if(j!=i){
                        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)<150){
                            player[i].GoLocate(SUPPORT,mPx*2-yPx,mPy*2-yPy);
                            player[j].GoLocate(SUPPORT,yPx*2-mPx,yPy*2-mPy);
                        }
                    }
                }
            }
        }

        player[i].Move();


まずはカップルをもうちょっとひき離すために、判定の距離を伸ばした。
平方距離で100→150だと、半径で10→12ピクセルだからほとんど変わらないが。
まあ、ここを変更したところで何一つ解決しないのだが。

どうにかして二人同時にボールを追いかける状況を打破しないといけないと考えてたんだけど、
もみもみ優先でボールを追わなくなったら、ゲームが進まなくなる。
ボールの前でお見合いがはじまったら、コンピューターだから一生どちらも譲らない。


それじゃあということで、重なったときのことを考える。

player.h


void Player::Move()
{
    if(Status==WAIT)return;

    double rad = atan2(SetY - Py, SetX - Px);
    double c = cos(rad);
    double s = sin(rad);

    Px += c;
    Py += s;

    if(Status!=SUPPORT){
        if(((SetY-Py)*(SetY-Py)+(SetX-Px)*(SetX-Px))<4){
            Px = SetX;
            Py = SetY;
        }
    }

    if((Status==GO_HOME)&&(getPx()==HomeX)&&(getPy()==HomeY))Status = WAIT;

}



きのう適当に落書きした計算式だと、キャラ同士の位置が近ければ近いほど
目標地点が目と鼻の先になる。
あの計算式では完全に重なったらどちらも斥力が働かなくなる。

ある程度目標地点に近づいたら、位置を丸めるように設定していたけど、これを
SUPPORT状態のときは働かさないようにしてみた。

これも杞憂。
たとえ1ピクセルでも座標が違えば、「その方向へ」「単位ベクトル」進むように作ってるから
目標地点の近さは問題じゃない。



いろいろ悩んでたけど、結果はただの凡ミスだった。
上のプログラムの青い部分、

        if(Distance(mPx,mPy,yPx,yPy)<150){
            player[i].GoLocate(SUPPORT,mPx*2-yPx,mPy*2-yPy);
            player[j].GoLocate(SUPPORT,yPx*2-mPx,yPx*2-mPy);
        }

        if(Distance(mPx,mPy,yPx,yPy)<150){
            player[i].GoLocate(SUPPORT,mPx*2-yPx,mPy*2-yPy);
            player[j].GoLocate(SUPPORT,yPx*2-mPx,yPy*2-mPy);
        }


ここが一番あやしいからって、何十回も見直したはずなんだけどなあ。
見えてないもんだなあ。





あともう1点、プログラム再アップの価値ある、大きな変更。

main.cpp


/*
void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}*/
bool wait_fanc(){
    int term;
    bool res = true;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    else res = false;
    t=GetNowCount();
    return res;
}
    :
    :

int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP, LPSTR lpC, int nC)
{
    if(DxInit()) return -1;
    if(GameInit()) {
        DxLib_End();    //Dxライブラリの開放
        return -1;
    }

    while( ProcessMessage() == 0){
        ClearDrawScreen();
        if(CheckKey()) break;

        GameFlame();

        DrawScene();
        fps();
        count++;
        if(wait_fanc()) ScreenFlip();
    }
    DxLib_End();
   
    return 0;
}




メイン関数の流れを修正した。
ちょっと思いつきで追加書いたんだけど、かなりうまくいった。

変えたのは、前回の wait_fanc() から16ms以内に1ループ回ってるかの判定の追加で、
もし超えていたら false を返して、ScreenFlip() を行わない。

うちのノートPCだけかもしれないけど、どうもScreenFlip() がうまく作動してない。
フルスクリーンだとちゃんと動いてるんだけど、ウインドウモードだとプログラムのScreenFlip() で
一度垂直同期待ちを行ったあとにウインドウズの描画管理でもう一度垂直同期待ちしてる感じで、
すごく遅くなる。2度待ちするからスピード半減。
DXライブラリの垂直同期待ちフラグ切っても変わらず 25か30fpsしか出ないから、
原因は他にあるのかもしれない。

このへんがうまくいかないから、DXライブラリ卒業しようかと本気で考えてしまうくらいに。


まあ余談というかただの愚痴だが。
これで処理の重いときはScreenFlip() を飛ばしながらゲームループを進められるわけだ。
ちゃんと作るなら、fpsの平均出して、一秒に何回処理できる(期待できる)かを測って
そこから各キャラクターの移動量を計算しないといけない。
一度その仕組みを作れば後は使いまわせるけど、結構めんどうな処理がついてまわる。

今回のサボり方は、まあいつもどおりに裏画面に画像を用意する。
そして必要なければ用意した画像を使わずに捨てて、次のフレームの用意に入る。
こんな感じ。
フルスクリーン版と比べて1フレームおきの処理になるんでカクカクしてるけど、
ゲームの進行速度自体はウインドウ版でもほとんど変わらなくなった。

fpsの変化によって1フレームの移動量が変わるわけでもないから妙な突き抜けバグも
発生しないだろうし、この方法はすごく気に入った。

新しいプログラムを作るときのベースが変更された。
プログラム起動時に「(全画面推奨)」しなくても気にならなくなった。
この差はかなり大きい。


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