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

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

ま~~~~~た、2chアクセス禁止だよ!!!
例の反・民主党荒らしのキチガイ、パソコンショップの店頭まわって書き込んでるらしく、
e-mobileの会社側では手に負えないみたい。
タダ同然で配りまくるから、こういうことになるんだよな。


そんなことはどうでもいいんだけど。
2日ほどサボったけど、サボってたわけでもない。いろいろ考えてたら手が動かなかっただけ。

v003.ボール





とりあえずは、ボールのクラスを作る。
現在座標(X,Y)と、移動方向Yaw、ベクトル強さをSpdで持つ。
Playerクラスから必要そうなところをコピペしてたら、なんとなく同じクラスからの派生でも
いいような気がしてくる。

Ball.h


// Ball.h

#pragma once

class Ball
{
    double Bx,By;       // ボール現在位置
    double Yaw;         // ボール進行方向
    double Spd;         // ボールの速度
    int HomeX,HomeY;    // ホームポジション(試合開始時、ピッチ中央)
public:
    void Init(int HomeX, int HomeY);
    int getBx(){return static_cast<int>(Bx);}
    int getBy(){return static_cast<int>(By);}
    double getSpd(){return Spd;}
    void Kick(int LocX, int LocY, double Spd);
    void Move();

};

void Ball::Init(int hx, int hy){
    Bx = HomeX = hx;
    By = HomeY = hy;
}

// ボールを蹴る(目標地点に向かう蹴り出し方向を決める)
void Ball::Kick(int LocX, int LocY, double Spd)
{
    Yaw = atan2(LocY - By, LocX - Bx);
    this->Spd = Spd;
}

void Ball::Move()
{
    double c = cos(Yaw);
    double s = sin(Yaw);

    Bx += c*Spd;
    By += s*Spd;

    Spd *= 0.98;     // 地面との摩擦により、転がるスピードが落ちる
    if(Spd < 0.001) Spd = 0.0;
   
}


実質、ボール蹴り出しの Kick() と、移動の Move() だけだな。
Kick() は、目標地点に向かう角度を決めて、Sin・Cos でX、Yに成分分解する。
そして Spd ベクトル長さで蹴り出しの強さを決める。

もう目標地点はいらない。目標地点に届かなくても行き過ぎても知らない。

Move() は、蹴り出した方向にSpd ベクトル分移動する。
Spd に1.0よりちょっと小さい値を掛けて、Spdを少しづつ減少させる。
一定値以下になると止まるように値を丸める。


禿げるほどいろいろ考えた割には、シンプルに収まった。
そういうものかもしれないな。案ずるより生むが安し。



main.cpp


void Game()
{
    enum GameState {GAMEINIT, PLAY};
    static GameState gs = GAMEINIT;
    int lx = 0,m = 0;

    switch(gs){
        case GAMEINIT:
            for(int i=0; i<10; i++){
                if(player[i].getStatus()!=WAIT)player[i].Move();
                else ++m;
            }
            ball.Move();

            if((m==10)&&(ball.getSpd()==0.0)) gs = PLAY;
            break;
        case PLAY:
            // プレイヤーを動かす
            for(int i=0; i<10; i++){
                if(player[i].getStatus()!=WAIT){
                    player[i].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
                    player[i].Move();
                    if(( (player[i].getPx()-ball.getBx())*(player[i].getPx()-ball.getBx())
                        +(player[i].getPy()-ball.getBy())*(player[i].getPy()-ball.getBy()))<25){

                        if(player[i].getTeam()==BLUE) lx = 600;
                        else lx = 0;
                        ball.Kick(lx, GetRand(300), 4.0);
                        player[i].setStatus(WAIT);
                    }
                } else ++m;
            }
            // もし誰も動いてなければ、誰かひとりランダムで決めてボールに走らせる
            if(m>=10){
                player[GetRand(10)].GoLocate(CHASE_BALL,ball.getBx(),ball.getBy());
            }

            ball.Move();
            break;
    }
}


こういう、この手のプログラムはお手の物。
ほとんど動作確認のテスト用。

まずは状態 GameState で今の状況を設定する。最初はGAMEINIT 。
初期化したプレイヤー・ボールが全部定位置に戻ったら PLAY 状態にする。

プレイヤーがWait 状態じゃなければプレイヤーを指示どおり動かす。このへんは後述。
Wait状態ならカウンタを+1して次のプレイヤーへ。
全員Wait状態なら、誰かひとり(ランダムに!)選んでボールに向かわせる。

ひとり選ばれたプレイヤーが、ボールを見ながら追いかける。
ボールとの距離が平方距離で25以下まで近づいたら、ボールを蹴る。
平方距離っていうのは、あの有名なピタゴラスの定理

  直角三角形斜辺の平方は、他の2辺の長さの2乗和に等しい
h=√(a^2 + b^2)
h^2 = a^2 + b^2

平方根を出すのはPC的にもちょっと手間だし、今回そんなに厳密な値が必要でもないから
下の式のまま放ったらかして、5の2乗距離25より小さいかどうかで判定しているだけ。

で、この距離より近くなれば、ボールを蹴って本人は休む。1/10の確率で連続出勤になるけど。

ボールの蹴り出しは、青チームなら右(X=600)、赤チームなら左(X=0)で、縦は0~300まで
ランダムで決める。
まあテストプログラムなので、追いかけてボールを蹴るサマが見られたらそれでいい。


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