在基于旋转的方向上移动时限制 x 和 y 跟踪的对象的最高速度

Limit top speed of an object tracked by x and y when moving in a rotation-based direction

假设我有一些可以 360 度旋转的角色,我正在跟踪它的 x 和 y 位置。

我正在使用 sincos 来确定它的移动:

x += speed * cos(rotation)
y += speed * sin(rotation)

这很好用,但我想我想要一个基于加速的系统。因此,我不是提高速度,而是提高加速度,然后提高速度:

x_velocity += speed * cos(rotation)
y_velocity += speed * sin(rotation)
x += x_velocity
y += y_velocity

但是,我不希望这个角色能够无限加速,因此我想限制它的最高速度。现在,我可以这样做:

if x_velocity > maxspeed then x_velocity = maxspeed
if y_velocity > maxspeed then y_velocity = maxspeed

但这并不完美,因为这意味着如果沿完美对角线移动,比沿基本方向移动快 44%。

所以我用了勾股定理,但是我马上运行陷入了一个问题

if sqrt(x_velocity^2 + y_velocity^2) > maxspeed then ???

有解决办法吗?我不能像以前那样简单地将它定义为等于 maxspeed,但我也不能将所有速度完全分配给一个轴,因为那样会改变方向。如何确定将其限制在的速度?

只使用整体速度

 velocity = Min(max_velocity, velocity + speed) //really acceleration instead of speed
 x_velocity  = velocity * cos(rotation)
 y_velocity  = velocity * sin(rotation)
 x += x_velocity
 y += y_velocity

如果你必须保持 x_velocity 和 y_velocity(出于某种奇怪的原因),那么你可以通过其保持方向的组件来限制整体速度:

... update x_velocity, y_velocity
vel = sqrt(x_velocity^2 + y_velocity^2) 
if vel > max_velocity then
    x_velocity = x_velocity * max_velocity / vel
    y_velocity = y_velocity * max_velocity / vel

拖动

您想添加阻力(摩擦力)来设置最大速度(就像自由落体阻力产生终端速度)

定义运动

acceleration = 2.0; // the constant acceleration applied     
vx = 0.0;           // velocity x
vy = 0.0;           // velocity y
x = 0.0;            // current position
y = 0.0;
direction = 0.0;    // direction of acceleration
drag = 0.01;        // drag as a fraction of speed

应用加速

vx += cos(direction) * acceleration ;
vy += sin(direction) * acceleration ;

应用拖动

vx *= 1 - drag;
vy *= 1 - drag;

获取当前速度

speed = sqrt(vx * vx + vy * vy);

计算最大速度的阻力。

如果要设置阻力的最大速度。

maxSpeed = 100.0;
drag = accel / (maxSpeed + accel);

只需对速度应用加速度和拖动(按此顺序),角色将永远不会超过 maxSpeed

重要的一点是,如果角色在接近 maxSpeed 时改变方向,速度将会下降,这与速度变化量有关。 EG 如果方向改变 180,那么角色将以等于 accel + speed * drag 的速度减速(拖动有助于减速)直到速度再次开始增加,此时加速度为 accel - speed * drag

根据阻力设置最大速度的最终解决方案,

acceleration = 2.0; // the constant acceleration applied     
vx = 0.0;           // velocity x
vy = 0.0;           // velocity y
x = 0.0;            // current position
y = 0.0;
direction = 0.0;    // direction of acceleration
maxSpeed = 100.0;
// set drag to give a maxSpeed 
drag = acceleration / (maxSpeed + acceleration);  

应用加速和拖动如下

vx += cos(direction) * acceleration ;
vy += sin(direction) * acceleration ;
vx *= 1 - drag;
vy *= 1 - drag;
x += vx;
y += vy;

速度永远不会超过最大速度。但是速度也永远不会达到最大速度,它只会越来越近,但永远不会完全到达那里,尽管我们说的是一个单位的微不足道的分数每帧 0.00000000001 像素