我已经用 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;
}