クラス間での当たり判定

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
C-TA-K

クラス間での当たり判定

#1

投稿記事 by C-TA-K » 14年前

こんにちは。以前一度だけ質問させていただきましたC-TA-Kと申します。
開発環境はvisualstudio2008 C++、 DXライブラリ使用です。

今回私はブロック崩しを作っているのですが、そのときのバーとボールとの当たり判定で
詰まってしまいました。詳細は下に記述します。

class Bar_base
{
public:
int img; //画像
int spd; //移動スピード
double x,y; //座標
};

class Nomal_bar : public Bar_base
{
public:

};


class Ball_base
{
public:
int img; //画像
int spd; //移動スピード
double x,y; //座標
};

class Nomal_ball : public Ball_base
{
public:

};

このようにバーならバー基本クラスを継承したノーマルバー等のバーを実装し、
ボールならボールの基本クラスを継承したノーマルボール等を実装する形で種類を増やすつもりです。
しかし、その場合当たり判定を行う場合はバーの座標とボールの座標が必要ですが、
ノーマルバーとノーマルボールの判定するならそれぞれインスタンス化し、当たり判定用の関数を用意して
void hit_bar_ball()
{
 nomal_bar.座標 と nomal_ball.座標の当たり判定処理
}

のようにすればいいのですがこれがまた新しく継承し

class Long_bar : public Bar_base
{}

等を作った場合などにはこの関数は適用できません。
だからといってほとんど同じ処理なのに当たり判定用の関数を何個も作るのはどうかと思います。
これをどうにか1つの当たり判定用の関数にまとめることはできないでしょうか?

ISLe

Re:クラス間での当たり判定

#2

投稿記事 by ISLe » 14年前

void hit_bar_ball(Bar_base *bar, Ball_base *ball)
{
 bar->座標 と ball->座標の当たり判定処理
}
というふうにすると呼び出すときの引数にNomal_barとLong_barのインスタンスのどちらでも渡せます。

C-TA-K

Re:クラス間での当たり判定

#3

投稿記事 by C-TA-K » 14年前

お早い回答ありがとうございます。 しかし私ポインタについては最近やっと分かり始めたところでして
教えていただいた関数の引数に何を渡せば良いのか考えあぐねています。
インスタンスを渡すというのはどういうことなのでしょうか?

C-TA-K

Re:クラス間での当たり判定

#4

投稿記事 by C-TA-K » 14年前

調べたところインスタンスを渡すというのは解決しました(参照渡し?というやつでよろしいのでしょうか)
そしてこの後に先程教えていただいた方法でhit_bar_ball()を実装したのですが、
確かに1つの関数で当たり判定を実装できるのですが、引数に&nomal_bar等で渡さなければなりません。
そうするともしnomal_bar と nomal_ballを入れたとき、long_bar と nomal_ballを入れたとき
nomal_bar と fast_ballなどの組み合わせを一つ一つ書き込まなければならないと思います。

例えば

hit_bar_ball(&nomal_bar, &nomal_ball);
hit_bar_ball(&nomal_bar, &fast_ball);
hit_bar_ball(&long_bar, &nomal_ball);
hit_bar_ball(&lobg_bar, &fast_ball);

するとバーやボールの種類が10種類になったころには凄まじい組み合わせの数を記述
しなければいけないのではないのでしょうか。関数を1つ挟んだとしても組み合わせによって
自動に切り替えられるようにしたいのですがどうすればよいでしょうか。
非常にわがままといいますか、都合の良すぎることを言っていると思いますがご助言いただければありがたいです。

dic

Re:クラス間での当たり判定

#5

投稿記事 by dic » 14年前

public:
     int img;    //画像
     int spd;    //移動スピード
     double x,y; //座標
の重複があったので私なりに書いてみました

#include <iostream>
using namespace std;

class    base
{
    int    img;    //    画像
    int    spd;    //    移動スピード
    double    x, y;    //    座標
public:
    double    GetX() { return x; }
    double    GetY() { return y; }
};

class    Normal_bar    :    public    base
{
};

class    Normal_ball    :    public    base
{
};

bool    hit_bar_ball( base *a, base *b )
{
    double    x1 = a->GetX();
    double    y1 = a->GetY();
    double    x2 = b->GetX();
    double    y2 = b->GetY();

    //    x1, y1, x2, y2 を使ってあたり判定処理
    bool    hit = false;

    return hit;
}

int main()
{
    base    *bar = new Normal_bar();
    base    *ball = new Normal_ball();

    hit_bar_ball( bar, ball );

    return 0;
}
継承と、ポリモーフィズムを理解してないと分からないかもしれないです

ISLe

Re:クラス間での当たり判定

#6

投稿記事 by ISLe » 14年前

No:64760の関数を
hit_bar_ball(&nomal_bar, &nomal_ball);
と呼びだすと

> void hit_bar_ball()
> {
>  nomal_bar.座標 と nomal_ball.座標の当たり判定処理
> }

のコードと同じことになります。
ポインタを使うと汎用的な関数を作ることができます。

dic

Re:クラス間での当たり判定

#7

投稿記事 by dic » 14年前

総当たりでの衝突判定です
2回判定していたりしてますので、期待どおりの処理にするにはカスタマイズが必要です
#include <iostream>
using namespace std;

class    base
{
    int    img;    //    画像
    int    spd;    //    移動スピード
    double    x, y;    //    座標
public:
    double    GetX() { return x; }
    double    GetY() { return y; }
};

class    Normal_bar    :    public    base
{
};

class    Normal_ball    :    public    base
{
};
class    Fast_ball    :    public    base
{
};


bool    hit_bar_ball( base *a, base *b )
{
    if(    a == NULL )
        return false;
    if( b == NULL )
        return false;
    double    x1 = a->GetX();
    double    y1 = a->GetY();
    double    x2 = b->GetX();
    double    y2 = b->GetY();

    //    x1, y1, x2, y2 を使ってあたり判定処理
    bool    hit = false;

    return hit;
}

int main()
{
    base    *bar = new Normal_bar();
    base    *ball = new Normal_ball();
    base    *fast = new Fast_ball();

    hit_bar_ball( bar, ball );


    base    *object[10];
    memset( object, 0, sizeof(object) );
    object[0] = bar;
    object[1] = ball;
    object[2] = fast;
    int    i, j;
    for( i=0; i<10; i++ )
    {
        for( j=0; j<10; j++ )
        {
            hit_bar_ball( object, object[j] );
        }
    }

    return 0;
}

dic

Re:クラス間での当たり判定

#8

投稿記事 by dic » 14年前

バーオブジェクトの配列と ボールオブジェクトの配列に分ければできますね

int main()
{
    base    *bar = new Normal_bar();    //    バー
    base    *ball = new Normal_ball();    //    通常のボール
    base    *fast = new Fast_ball();    //    早いボール

    hit_bar_ball( bar, ball );    //    バーと通常のボールの判定
    hit_bar_ball( bar, fast );    //    バーと早いボールの判定


    base    *object_ball[10];    //    バーオブジェクト
    base    *object_bar[10];    //    ボールオブジェクト
    memset( object_ball, 0, sizeof(object_ball) );
    memset( object_bar, 0, sizeof(object_bar) );
    object_bar[0] = bar;
    object_ball[0] = ball;
    object_ball[1] = fast;

    //    バー10個とボール10個の当たり判定
    int    i, j;
    for( i=0; i<10; i++ )
    {
        for( j=0; j<10; j++ )
        {
            hit_bar_ball( object_bar, object_ball[j] );
        }
    }

    return 0;
}

C-TA-K

Re:クラス間での当たり判定

#9

投稿記事 by C-TA-K » 14年前

ISle様、dic様お二方とも回答ありがとうございます

dic様の総当りの当たり判定は

int main()
{
base *bar = new Normal_bar(); // バー
base *long = new Long_bar(); // 長いバー

base *ball = new Normal_ball(); // 通常のボール
base *fast = new Fast_ball(); // 早いボール

hit_bar_ball( bar, ball ); // バーと通常のボールの判定
hit_bar_ball( bar, fast ); // バーと早いボールの判定
hit_bar_ball( long, ball ); // 長いバーとボールの判定
hit_bar_ball( long, fast ); // 長いバーと早いボールの判定


base *object_ball[10]; // バーオブジェクト
base *object_bar[10]; // ボールオブジェクト
memset( object_ball, 0, sizeof(object_ball) );
memset( object_bar, 0, sizeof(object_bar) );
object_bar[0] = bar;
object_bar[1] = long;
object_ball[0] = ball;
object_ball[1] = fast;

// バー10個とボール10個の当たり判定
int i, j;
for( i=0; i<10; i++ )
{
for( j=0; j<10; j++ )
{
hit_bar_ball( object_bar, object_ball[j] );
}
}

return 0;
}

長いバーを追加するとしたらこんな感じで改変していけばよいのでしょうか?
ちなみにこの場合の開放はmain()の最後で良いのですよね?

C-TA-K

Re:クラス間での当たり判定

#10

投稿記事 by C-TA-K » 14年前

たびたびすいません、丁寧に解説していただいたおかげで少し自分でも考えついたことがあるのですが、

void hit_bar_ball(Bar_base *bar, Ball_base *ball)
{
 bar->座標 と ball->座標の当たり判定処理
}


void hit_select( int i, int j )
{
base *bar[10];
base *ball[10];

bar[0] = new Nomal_bar(); //普通のバー
bar[1] = new Long_bar(); //長いバー

ball[0] = new Nomal_ball(); //普通のボール
ball[1] = new Fast_ball(); //早いボール

hit_bar_ball(bar, ball[j]);

}

そしてこのiとjにはどのバーとどのボールを当てるか決定するグローバル変数を入れると
その二つの当たり判定だけが処理される・・・とはいきませんかね・・・。

C-TA-K

Re:クラス間での当たり判定

#11

投稿記事 by C-TA-K » 14年前

void hit_bar_ball( Bar_base *bar, Ball_base *ball)
{
double bar_left = bar->x - bar->width;
double bar_top = bar->y - bar->height;
double bar_right = bar->x + (bar->width+1);
double bar_down = bar->y + (bar->height+1);

if( bar_left - (BALL_R+1) < ball->x &&
bar_right + BALL_R > ball->x &&
bar_top < ball->y &&
bar_down > ball->y )
{
ball->sign_x *= -1;
}

if( bar_left < ball->x &&
bar_right > ball->x &&
bar_top - (BALL_R+1) < ball->y &&
bar_down + BALL_R > ball->y )
{
ball->sign_y *= -1;
}

}

void hit_select(int i, int j)
{
Bar_base *bar[10];
Ball_base *ball[10];

bar[0] = &nomal_bar; //普通のバー

ball[0] = &nomal_ball; //普通のボール

hit_bar_ball(bar, ball[j]);
}

本当にありがとうございました、自分でお二人のコードを凝視して導いた結論がこれになりました
hit_selectのi,jにはグローバルな変数で、どのバーとボールを当てたいかを選択するようにしました
これで解決とさせていただきます。

閉鎖

“C言語何でも質問掲示板” へ戻る