2

我正在使用 Box2d 进行游戏,但我遇到了一个让我发疯的错误。我将情况简化为一个方形玩家在由一系列方形瓷砖组成的地板上无摩擦地来回滑动,由左右键(施加水平力)驱动。效果很好,在整个地板上来回滑动。

除了...每隔一段时间,玩家会突然粘在其中一个瓷砖的边缘,就好像它正在撞到(不存在的)墙壁一样。再往同一个方向推会失败,但只要我往相反的方向向后推一次,我就可以再次向前推过粘滞点。粘点似乎是随机的,除了在瓷砖的边缘。向左或向右时发生。

出于调试目的,我保留前两个更新刻度的位置/速度值,并在此停止发生时将它们打印出来。例如,在这里您看到玩家向右移动,略微减速;pos2 应该是 8.7 左右,但它反而停止了。

tick0:  pos= 8.4636 vel= 7.1875
tick1:  pos= 8.5816 vel= 7.0833
tick2:  pos= 8.5816 vel= 0.0000

因此,当玩家为 0.8 且瓷砖宽度为 1.0 时,玩家在即将越过下一块瓷砖时停止(8.5816 + 0.8/2 = 8.9816)。事实上,我收到了一条冲突消息(我忽略了它,只是注意到它发生了)。它似乎只在向右移动时发生在 x.5816(或 -x.4184),向左移动时发生在 x.4167(或 -x.5833)

我说这就像撞墙,但实际上,当它撞墙时,数字看起来更像:

 tick0:  pos0= 12.4131 vel2= 8.4375
 tick1:  pos1= 12.5555 vel1= 8.5417
 tick2:  pos2= 12.5850 vel0= 0.0000

所以它在最后一个滴答声上向右移动,使其与墙壁接触。

有人见过这样的吗?关于我如何导致这种行为的任何建议?

4

2 回答 2

3

不幸的是,这是 Box2d 中的一个已知问题......来自常见问题解答

基于瓷砖的环境

为您的地形使用多个框可能效果不佳,因为类似框的字符可能会卡在内部角落。Box2D 的未来更新应该允许边缘链上的平滑运动。一般来说,您应该避免使用矩形字符,因为碰撞容差仍会导致不希望出现的阻碍。

有关更多信息,请参阅此帖子: http ://box2d.org/forum/viewtopic.php?f=3&t=3048

来自 Box2d 的创建者 Eric Catto(强调添加):

我正在研究边缘链的解决方案,但没有针对相邻多边形的解决方案。您最好使用一个或多个圆圈来表示角色与环境。大多数使用现代物理引擎的专业游戏都为角色使用平滑的形状,例如胶囊。对角色使用盒子形状确实只适用于使用基于像素的碰撞与积分数学的系统(即较旧的控制台游戏)。

所以基本上,你的身体应该是一个光滑的形状,而不是一个多边形,这样它就不会在瓷砖之间卡住。

于 2012-12-18T18:53:59.493 回答
0

不,您不需要将瓷砖更改为光滑的身体。我遇到了完全相同的问题。简短的回答是

“使用 b2EdgeShape ,而不是 b2PolygonShape ”

试试这个..在我使用多边形之前,我遇到了你所说的那些意想不到的碰撞

b2PolygonShape* pBasic_1X1_Box = new b2PolygonShape();
pBasic_1X1_Box->SetAsBox(1.0f/2.f, 1.0f/2.f); 
m_mapPolygonShape["1X1_Box"] = pBasic_1X1_Box;       
....
pBody->CreateFixture(m_mapPolygonShape["1X1_Box"],0.f);

在我使用边缘形状之后,我解决了这些问题

b2EdgeShape* pBasic_1X1_Box_Up = new b2EdgeShape();    
b2EdgeShape* pBasic_1X1_Box_Down = new b2EdgeShape();  

 b2EdgeShape* pBasic_1X1_Box_Left = new b2EdgeShape();  
 b2EdgeShape* pBasic_1X1_Box_Right = new b2EdgeShape(); 
 b2Vec2 v0(-0.5f, 0.5f);                                
 b2Vec2 v1( 0.5f, 0.5f);                                
 b2Vec2 v2( 0.5f,-0.5f);                                
 b2Vec2 v3(-0.5f,-0.5f);                                
                                                        
 pBasic_1X1_Box_Up->SetOneSided(v2,v1,v0,v3);           
 pBasic_1X1_Box_Down->SetOneSided(v0,v3,v2,v1);         
 pBasic_1X1_Box_Left->SetOneSided(v1,v0,v3,v2);         
 pBasic_1X1_Box_Right->SetOneSided(v3,v2,v1,v0);        
 m_mapEdgeshape["1X1_Box_Up"]    = pBasic_1X1_Box_Up;   
 m_mapEdgeshape["1X1_Box_Down"]  = pBasic_1X1_Box_Down; 
 m_mapEdgeshape["1X1_Box_Left"]  = pBasic_1X1_Box_Left; 
 m_mapEdgeshape["1X1_Box_Right"] = pBasic_1X1_Box_Right;
...
// :x: using edge shape for tile structure                 
pBody->CreateFixture(m_mapEdgeshape["1X1_Box_Up"],0.f);    
pBody->CreateFixture(m_mapEdgeshape["1X1_Box_Down"],0.f);  
pBody->CreateFixture(m_mapEdgeshape["1X1_Box_Left"],0.f);  
pBody->CreateFixture(m_mapEdgeshape["1X1_Box_Right"],0.f); 

由于麦克沃斯的问题本身,我可以解决这个问题。

谢谢麦克沃斯

于 2021-12-06T04:41:04.623 回答