我正在努力为我的游戏添加Tile碰撞。
我所做的是,我浏览每个物体并获得它们周围的边缘。
我返回一个Vec2向量,它对应于每个周围边缘区块的左上角位置。
那些被置于一组Vec2中,所以只留下唯一的。
从那里,可以构建固定大小的矩形。
但是,我要求将连续的矩形合并为1。
所以在这个例子中,我们将这8个固定矩形变为3。
最右边的一个会保持不变。
x轴上的6将变为1,x轴上的最左边和下面的那个将变为1.
鉴于我有一个Vec2表示每个tile方块的左上角位置,我知道方块的宽度,我怎么能计算一个新的Rectangle(x,y,w,h)向量并合并固定方块?
void TilePhysicsManager::update()
{
m_locationSet.clear(); //clear the unique locations
for (b2Body* b = m_b2world->GetBodyList(); b; b = b->GetNext())
{
if(b->GetType() == b2_dynamicBody)
{
PhysicsObject* obj = (PhysicsObject*)b->GetUserData();
const std::vector<Vec2>& edgeTiles = m_tileWorld->getSideTiles(*obj,1.5f);
//add in locations (duplicates will be rejected)
for(int i = 0; i < edgeTiles.size(); ++i)
{
m_locationSet.insert(edgeTiles[i]);
}
}
}
int objIndex = 0; //index of which dummy object we need
for(std::set<Vec2>::iterator it = m_locationSet.begin(); it != m_locationSet.end(); ++it)
{
//if our memory pool is not big enough, grow it
if(objIndex >= count())
{
allocNewObject();
}
m_objects[objIndex]->setLocation(*it);
objIndex++;
}
}
由于
答案 0 :(得分:1)
我认为最简单快速的方法是在“垂直连续条带”扩展之后进行“水平连续条带”扩展,反之亦然。
例如:
<强>结论:强>
<强>实施强>
以下是C#
中的优化实现private List<Rectangle> Merge(Rectangle[] r) {
// Computing the bound
Rectangle bound = new Rectangle(r[0].X, r[0].Y, r[0].Width, r[0].Height);
for (int i = 1; i < r.Length; ++i) {
bound.X = Math.Min(bound.X, r[i].X);
bound.Y = Math.Min(bound.Y, r[i].Y);
bound.Width = Math.Max(bound.Right, r[i].Right) - bound.X;
bound.Height = Math.Max(bound.Bottom, r[i].Bottom) - bound.Y;
}
// Create number of rectangle will be created by vertical strip expansion
Rectangle[] m = new Rectangle[bound.Height / RECT_HEIGHT];
for (int i = 0; i < m.Length; ++i) {
m[i] = new Rectangle(Int32.MaxValue, bound.Y + i * RECT_HEIGHT, 0, RECT_HEIGHT);
}
for (int i = 0; i < r.Length; ++i) {
int index = (r[i].Y - bound.Y) / RECT_HEIGHT;
if (m[index].Width <= 0) {
m[index].Width = r[i].Width;
m[index].X = r[i].X;
} else {
int right = m[index].Right;
m[index].X = Math.Min(m[index].X, r[i].X);
m[index].Width = Math.Max(right, r[i].Right) - m[index].X;
}
}
// Merge horozontally
for (int i = m.Length - 1; i > 0; --i) {
// can only merge when two rect has the same X and Width
if ((m[i].X == m[i - 1].X) && (m[i].Width == m[i - 1].Width)) {
m[i - 1].Height += m[i].Height; // expanse the rectangle
m[i].Width = 0; // remove one rectangle
}
}
// Remove all the empty rectangle
List<Rectangle> result = new List<Rectangle>();
for (int i = m.Length - 1; i >= 0; --i) {
if (m[i].Width > 0)
result.Add(m[i]);
}
return result;
}
以下是通过以下实现生成的结果。左侧是初始矩形,右侧是结果。
答案 1 :(得分:0)
我认为问题陈述有点模糊不清。在给出的示例中,有多种可能的方法将给定的图块分组为最大的,不重叠的较大矩形。具体来说,左上角的图块可以按照您的建议与行的其余部分合并,也可以与下面的图块合并。
就算法而言,我首先想到的是逐个从集合中取出图块并通过它们的邻居展开它们。在展开多个图块的矩形时,只需检查该边缘上的所有图块是否都有一个邻居(剩下的内容)。一旦发现矩形无法在任何方向上展开,您就完成了,并可以继续前进到下一个图块。
这种方法对我来说似乎是O(n ^ 2),可能会有所改进,但在实践中很容易成为非问题,具体取决于规模和需要评估的频率(使用静态水平几何,我不希望经常这样做。
使用这样的方法要警惕的一件事是不要错误地在迭代它时从容器中删除元素。糟糕的iterator juju。只需复印一份。