在没有重力的情况下使用box2d减速物体

6
我正在制作一个桌球游戏,所以我的重力设置为零,并施加推力使球杆移动。由于没有重力,我使用线性和角阻尼来减慢球的速度。
当球有一定的速度时,它们会逐渐减速,看起来非常真实。问题出现在它们减速很多并且即将停止但实际上不会停止,需要大约4-5秒钟,这看起来非常不真实。
我想到的解决方案之一是每帧检查球的速度,如果低于某个数值(即球即将停止),则将其设置为零以停止对象。这种方法的问题是我正在制作一个多人游戏,在这个游戏中两个玩家可能具有略微不同的帧率,从而使得相同镜头下的两个模拟结果不一致。
有人能想到其他解决方案吗?

我不确定box2d是否支持它,但你要找的是摩擦力。 - André Puel
我也考虑过这个,但球下面没有任何与之摩擦的物体。球只能与其他球或垫子发生碰撞,而不能与桌子(即桌布)发生碰撞,因为它们只能在x和y方向上移动,而不能在z方向上移动。 - Alex
1
我认为你应该用一个固定的力来替代阻尼,这个力始终与球的运动方向相反,你可以调整这个力的大小,直到找到视觉上可接受的效果。 - André Puel
3个回答

4

我猜测你需要非线性阻尼,因此建议你在每个帧上编辑线性阻尼值,使用基于当前速度的公式。


问题在于我不想按帧进行计算,因为这可能会破坏多人游戏(即两个玩家的帧率略有不同可能会导致对同一射击的模拟结果不同)。 - Alex
@Alex:如果你在两个设备上都不使用固定时间步长,那么模拟结果无论如何都会有所不同。 - Andrew
我不确定我是否理解你的意思。我已经在60 FPS和10 FPS上测试了我的游戏(使用相同的射击速度、位置等,只是改变了FPS),它们提供完全相同的结果(尽管在10 FPS上速度要慢得多)。 - Alex
他所说的是那些你传递给box2d步进方法的变量。它们定义了你想要在时间上推进物理世界的程度。你可以根据帧之间的时间来定义这个值,从而始终获得视觉上逼真的行为,或者使用固定的时间步长,并相信它将始终以60fps运行。如果你选择后者,你可以相信游戏始终是相同的,即使在一侧速度较慢。或者你可以使用最好的玩家电脑来模拟物理,通过网络进行同步。 - Rui Campos

3
尝试使用 b2Body 的线性阻尼参数:
body->SetLinearDamping(0.1f);

2
我已经尝试过这样做了,当速度很快时(即逼真地减速),它运行得很好,但当球即将停止而实际上还要滑行5-10秒钟时,它看起来很奇怪。当你认为球即将停止时,它仍然会稍微滑行很长一段时间,直到它撞到靠垫或停止。我也尝试添加了角阻尼,这在某种程度上有所帮助,但它仍然需要很长时间才能以较小的速度停下来。 - Alex
2
就像我之前提到的,我正在制作一个多人游戏。据我所知,必须在帧级别上操纵物理会破坏两个玩家之间的同步,因为他们的帧速率可能略有不同。我的想法是,比如说玩家1开枪,将开枪的特定数据发送给玩家2,然后他们各自模拟开枪的过程。你所说的听起来很容易实现,但我担心这会破坏多人游戏。 - Alex
3
Alex: 离题了,但是你的同步不好。仅测试几次模拟结果是否相同是不够的。它们可能看起来相同,但如果帧速率不同-引擎进行了不同的计算。因此,没有保证结果将相同,并且差异将随时间和模拟复杂度的增加而增加。我认为你应该只在一个设备上模拟物理,然后将物体位置/旋转传输到其他设备。实际上,第二个设备只需要绘制模拟结果,甚至不需要b2world。 - Andrew
只要他有一个固定的时间步长,那么它将保持不变。只有当两个玩家都表示他们的场景在所有物体上都达到了睡眠状态时,才能通过回合。 (较慢的电脑将更慢地达到此状态,但将达到相同的状态) - Rui Campos
我现在明白你的意思了。我对帧和它们如何与固定时间步长交互有点困惑,但现在我想我理解了。非常感谢大家! - Alex
显示剩余5条评论

2
如果你正在制作一个多人游戏,你需要一名裁判来确保没有不一致的情况。可以是两个客户端都连接到的服务器,也可以是其中一个(或两个)客户端充当主机。
重要的是,在显示之前,每个击球都会被计算并发送给双方。由于台球是轮流进行的,因此每个客户端都可以主持自己的击球,并将结果发送到对手的游戏实例中“重播”。这也意味着延迟不应该是太大的问题,因此您可以逐帧发送球的位置(虽然这不是最佳选择,但很容易实现)。
如果你想要一个可以用于连接而无需设置服务器的东西,可以看看pubnub(http://www.pubnub.com/)。账户设置和开发是免费的,而且相对容易设置。
希望这有所帮助! ^^

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接