碰撞检测方法

时间:2013-02-25 23:22:37

标签: c++ collision

我已经用C ++编程了大约6个月,现在仍然是初学者,但我一直在为游戏创建碰撞检测系统而烦恼。我设计了一种获取多边形的方法,并测试一个点以查看它是否在该多边形内。一旦我对图形有了更好的处理,我将运行一个动画循环,用所有射弹测试所有敌人,然后根据它们的移动功能移动它们。

我处理碰撞检测的方法是使用图示的系统in this link。我创建的代码可以在here及以下看到。我的问题是,对于每一帧,每个单独的边界框(每个敌人)都运行所有这些过程吗?我知道处理速度和效率在游戏设计中非常重要,所以这种方法是否过于冗长或者我低估了处理器的实际运行速度?关于如何处理这些事情的任何建议都值得赞赏。

#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;
}

1 个答案:

答案 0 :(得分:1)

如果您的程序受到太多碰撞的约束,请查看Quad Trees

在进行多边形碰撞测试之前,您还可以先检查简单的边界体,例如轴对齐和定向边界框。