基本上我正在研究物理游戏。横向运动需要 减少(因为接近0,而不是变成负数),但我不知道它在哪个方向,所以我不知道是添加阻力还是减去阻力。
(如果项目向右移动,则具有正向力,向左移动,负向力)
现在我正在这样做:
if (objects[i]->force.x > 0)
objects[i]->force.x -= drag;
else
objects[i]->force.x += drag;
哪种方法很好,但我觉得必须采用更时尚的方式来做到这一点。
找到一种确保它不会超过0的方法也不会有害。
答案 0 :(得分:6)
如果您试图模拟摩擦,最简单的方法是知道速度并使用数学模型或微分方程来近似它。
dx
-c * --
dt
基本上,摩擦力与速度和相反方向成比例。因此,您可以简单地计算摩擦力(或阻力),如下所示:
objects[i]->force = -drag_coefficient * objects[i]->velocity
如果你不知道速度,很难得到好的结果,因为当物体向左移动时你可能会向右推力(因此你会向正确的方向施加阻力)。
实际上,并非所有类型的摩擦都取决于速度的幅度(速度),干摩擦通常被称为仅采取方向速度考虑在内:
force = -drag_coefficient * sign(velocity)
然而,计算上当速度达到0时会变得不稳定,超过它并来回振荡。
另一个模型是湿摩擦的模型,这是我在第一个例子中使用的模型:
force = -drag_coefficient * velocity
这意味着当你的物体运行得更快时,它会因摩擦而减慢。想想空气的力量,当你跑步时,你跑得越快,空气越慢,你就越慢。
上述两种型号都不是100%准确,但对于游戏来说,它们应该足够了
答案 1 :(得分:2)
拖动应该是速度的函数:drag = r_1 * v
其中r_1 < 0
。这将导致阻力与速度相反。然后你可以添加拖拽力。
答案 2 :(得分:2)
首先,我们应该澄清这里所代表的内容。你写道:“如果一个物品向右移动,它有正向力......”通常情况下,如果物品向右移动,我们会期望它在该方向上具有正向速度,而不一定是正向力。
如果要在实体表面上拖动实体对象,阻止拖动运动的“理想”摩擦力是将物体推入表面的力(例如,重力)乘以摩擦系数(取决于所涉及的材料) )。将该力除以物体的质量会产生加速度。在物体(包括质量),材料和垂直力没有变化的情况下,您可以计算一次加速度并将其视为常数a
。
在连续模型中,此加速度将速度平滑地降低到零。在您的模型中,您可能正在使用离散的时间步长,t
。因此,在每个正常步骤中,速度通过加速乘以步进时间a*t
而减小。我们也可以计算并将其分配给某个变量,比如d
。
出现问题是因为离散时间步长可能会超过速度变为零的时刻。要解决此问题,您可以使用以下代码:
if (velocity > d)
velocity -= d; // Resist rightward velocity for a full time step.
else if (velocity < -d)
velocity += d; // Resist leftward velocity for a full time step.
else
velocity = 0; // Resist small velocity until it becomes zero.
当然可以使用其他模型,对于非实体的物体有不同的物理特性。一些在其他答案和评论中提到的简单模型是通过乘以小于1的值来减小速度。该示例不模拟拖动实体对象的真实物理。它是否适合您的游戏可能是一种美学选择。如果您使用它,您的代码可能只是:
velocity *= factor;
一个问题是某些处理器对次正规数的性能非常差。最常用的浮点算法IEEE-754指定了特殊处理的非常小的数字的间隔(以获得有助于证明和预测行为的某些数学属性)。在没有任何其他更改的情况下,诸如velocity *= factor;
之类的表达式将使数字变得越来越小,直到它们达到该次正常间隔。在易受攻击的处理器上,这将导致程序的性能突然下降。这当然可能毁了游戏物理。某些系统设置处理器模式,其中次正规数转换为零。这避免了性能问题,但违反了IEEE-754标准。游戏物理学可能是可以接受的。
答案 3 :(得分:1)
如果您对模型感到满意(请注意评论中的注意事项),您可以使用 signum 功能缩短表达式。 Although in C++ choosing one is apparently somewhat involved...
无论您选择哪一个,我都会将其称为sgn()
。然后,您希望应用拖动的符号为force.x
的相反符号:
objects[i]->force.x += -1 * sgn(objects[i]->force.x) * drag;
(我知道我可以在这里使用一元减去;我认为这会使意图更清晰)