1

私は C++ でプログラミングを始めて約 6 か月になりますが、まだ初心者ですが、ゲーム用の衝突検出システムの作成をいじっています。ポリゴンを取得し、ポイントをテストして、そのポリゴン内にあるかどうかを確認する方法を考案しました。グラフィックスをうまく扱えるようになったら、アニメーション ループを実行して、すべての発射体ですべての敵をテストし、移動関数に従ってすべての敵を動かします。

私が衝突検出を処理した方法は、このリンクに示されているシステムを使用することです。私が作成したコードは、ここと以下で見ることができます。私の質問は、これらのプロセスはすべて、すべてのフレームのすべてのバウンディング ボックス (すべての敵) に対して実行するには多すぎるのでしょうか? ゲーム デザインでは処理速度と効率が非常に重要であることはわかっていますが、この種の方法論は長すぎるのでしょうか、それともプロセッサの実際の動作速度を過小評価しているのでしょうか? これらが通常どのように処理されるかについてのアドバイスをいただければ幸いです。

#include <iostream>
#include <vector>


class point
{
    public:
        point (int a, int b): x(a), y(b) {};
        ~point () {};

        int getX() {return x;}
        int getY() {return y;}

    private:
        int x;
        int y;
};


class side
{
    public:
        side(point f, point s): first(f), second(s) {};
        ~side() {};
        point getFirst() {return first;}
        point getSecond() {return second;}

    private:
        point first;
        point second;
};


class boundingBox
{
    public:
        boundingBox(std::vector <point> p);
        ~boundingBox() {};

        std::vector <side> getSides() {return boundingSides;}

    private:
        std::vector <point> boundingPoints;
        std::vector <side> boundingSides;
};


boundingBox::boundingBox(std::vector <point> p)
{
    boundingPoints = p;

    // in the constructor, create a vector of sides from the points
    for (std::vector <point>::iterator i = boundingPoints.begin(); i != boundingPoints.end()-1; i++)
    {
        boundingSides.push_back( side(*i, *(i+1)) );
    }

    boundingSides.push_back( side (*(boundingPoints.end()-1), *(boundingPoints.begin()) ) );
}






bool collisionCheck(std::vector <side> s, point p)
{
    std::vector <side> nodeSides;

    int toleft = 0;
    int toright = 0;

    for (std::vector <side>::iterator i = s.begin(); i != s.end(); i++)
    {
        //if the Y value of the point being tested is between the Y values of a side, add a node
        if (p.getY() > (*i).getFirst().getY() && p.getY() < (*i).getSecond().getY() ||
            p.getY() < (*i).getFirst().getY() && p.getY() > (*i).getSecond().getY() )
        {
            nodeSides.push_back( side ( (*i).getFirst(), (*i).getSecond() ) );
        }


        // if the Y value of the point being tested is also the Y of the second point of the side...
        if (p.getY() == (*i).getSecond().getY())
        {
            //if it isn't the last side, and this side and the next strattle that y value, add a node
            if (i != s.end()-1)
            {
                if ((*i).getFirst().getY() < p.getY() && (*(i+1)).getSecond().getY() > p.getY() ||
                    (*i).getFirst().getY() > p.getY() && (*(i+1)).getSecond().getY() < p.getY() )
                {
                    nodeSides.push_back( side ( (*i).getFirst(), (*i).getSecond() ) );
                }   
            }   

            //if it is the last side, and this side and the first side strattle that y value, add a node
            else if ((*i).getFirst().getY() < p.getY() && s.front().getSecond().getY() > p.getY() ||
                 (*i).getFirst().getY() > p.getY() && s.front().getSecond().getY() < p.getY() )
            {
                nodeSides.push_back( side ( (*i).getFirst(), (*i).getSecond() ) );
            }
        }
    }

    for (std::vector <side>::iterator i = nodeSides.begin(); i != nodeSides.end(); i++)
    {
        double deltaY = (*i).getSecond().getY() - (*i).getFirst().getY();
        double deltaX = (*i).getSecond().getX() - (*i).getFirst().getX();

        double slope = deltaX - deltaY;

        double x = ( p.getY() - (*i).getSecond().getY() + (slope * (*i).getSecond().getX()) ) / slope;

        if (x < p.getX()) 
        {
            toleft++;
        }

        else
        {
            toright++;
        }
    }


    std::cout << "Analysis: " << toleft << " nodes to the left, " << toright << " nodes to the right." << std::endl;

    if (toleft % 2 == 0)
    {
        std::cout << "return false, does not hit" << std::endl;
        return false;
    }

    else
    {
        std::cout << "return true, hits" << std::endl;
        return true;
    }
}






int main ()
{
    std::vector <point> points;

    points.push_back(point(3, 5));
    points.push_back(point(1, 13));
    points.push_back(point(7, 16));
    points.push_back(point(14, 14));
    points.push_back(point(8, 13));
    points.push_back(point(9, 11));
    points.push_back(point(17, 13));
    points.push_back(point(16, 18));
    points.push_back(point(21, 15));
    points.push_back(point(17, 9));
    points.push_back(point(9, 7));
    points.push_back(point(12, 5));
    points.push_back(point(14, 7));
    points.push_back(point(15, 2));
    points.push_back(point(6, 3));

    boundingBox enemy(points);

    point hitSimp(13, 4);
    point hitComp(19, 15);
    point missNear(10, 12);
    point missFar(100,100);

    collisionCheck(enemy.getSides(), hitSimp);

    collisionCheck(enemy.getSides(), hitComp);

    collisionCheck(enemy.getSides(), missNear);

    collisionCheck(enemy.getSides(), missFar);

    return 0;
}
4

1 に答える 1

1

あまりにも多くの衝突をチェックしてプログラムがバインドされる場合は、Quad Treesを調べてください。

また、ポリゴンの衝突テストを行う前に、軸に沿ったバウンディング ボックスや方向付けられたバウンディング ボックスなどの単純なバウンディング ボリュームを最初に確認することもできます。

于 2013-02-25T23:46:09.447 に答える