什么可能导致 Box2D 突然停止?

问题描述 投票:0回答: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

因此它在最后一个刻度处进一步向右移动,使其与墙壁接触。

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

c++ box2d
2个回答
4
投票

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

基于图块的环境

在你的地形上使用很多盒子可能效果不好,因为像盒子一样 角色可能会被内角卡住。未来更新至 Box2D 应允许在边缘链上平滑运动。一般来说你 应避免使用矩形字符,因为会发生碰撞 公差仍然会导致不良的阻碍。

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

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

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

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


0
投票

不,您不需要更换瓷砖来平滑身体。 我遇到了完全相同的问题。

简短的回答是:

use b2EdgeShape , not 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); 

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

谢谢麦克沃斯

© www.soinside.com 2019 - 2024. All rights reserved.