如何在考虑其角度的同时限制具有max_speed值的汽车的 X 和 Y 偏移量?

How can I limit the X and Y offsets of a car with a max_speed value while taking its angle into account?

提问人:diogeek 提问时间:8/25/2023 最后编辑:diogeek 更新时间:8/25/2023 访问量:73

问:

上下文:

我有这个游戏,我以自上而下的视角控制一辆汽车。我使用多个变量来移动它。

  • 是 .(这意味着它每个刻度最多可以移动 5px)MAX_SPEED5
  • (加速)是(表示加速时速度每刻增加四分之一像素)。FORWARD_ACC0.25
  • 汽车的(这是一个向量:)。speed[0,0][x offset, y offset]
  • 汽车的(这也是一个矢量)。acceleration[x acc, y acc]
  • 最后,汽车(以弧度为单位)。angle

这些变量允许我在自上而下的视图中根据汽车的角度为汽车分配加速度。

我用三角函数计算值:。accelerationacceleration = [cos(angle)*FORWARD_ACC, sin(angle)*FORWARD_ACC]

因此,当以 pi/2 弧度加速 (px) 时(下降,因此在 pygame 中为 90 度),我的向量将是 .当以圆周率弧度(向左走,所以在 pygame 中为 180 度)时,我的向量将是 .0.25angleacceleration[0, 0.25]angleacceleration[-0.25, 0]

然后,我使用此功能将速度添加到速度中:acceleration

def add_acc_to_speed(speed, acceleration):
    returned_speed = [speed[0]+acceleration[0], speed[1]+acceleration[1]]
    return(returned_speed if abs(returned_speed[0])+abs(returned_speed[1])<MAX_SPEED else speed)

这个函数应该使 的总和不能超过 。这样一来,汽车就不能比 px 跑得更快。|x offset| + |y offset|MAX_SPEED5

怎么了:

问题是,如您所见,如果总和大于 5,则此函数将返回传递的参数。这样做的副作用是,不考虑作为参数传递并取决于汽车角度的 new。speedacceleration

基本上,假设你的车开了一会儿,然后迅速达到最大速度。如果您尝试向下转弯,只要您与加速度变量的 Y 偏移量不高于 x 偏移量,您的汽车就不会转弯,而是侧向行驶。因此,例如,如果我有,我仍然会在考虑开始之前向右走 30 秒(只是因为 0.19 不是 0.25,所以 x 偏移量正在慢慢减少,在我允许的窗口中允许更多“空间”,这受到max_speed的限制。[0.19, 0.16]0.16

现在假设你再转一点,你的价值现在是.由于加速度的 Y 偏移现在高于 X 偏移,因此汽车将按预期转弯。acceleration[0.17,0.18]

这会导致奇怪的、急转弯,汽车大多向上、向下、向左或向右行驶:sharp turns.

TL;博士:

我在速度向量上设置的限制使得其中一个偏移量需要降低才能使另一个偏移量上升,只要需要降低的偏移量具有更高的值,这种情况就不会发生。acceleration

我已经尝试了什么?

  • 在每个偏移量上设置一个单独的限制(这导致两个偏移量都能够达到 5 () 并且汽车在对角线行驶时速度太快)。MAX_SPEED[5,5]
  • 在每个偏移量上设置一个单独的限制(这解决了对角线问题,但即使朝上、向下、向左或向右(例如),汽车现在也只能达到 2.5)。MAX_SPEED//2[2.5,0]
  • 我还没有尝试过,但也许可以动态修改值,以便我在这两种尝试之间有一个中间地带?MAX_SPEED

我知道这比仅仅将整数设置为限制要复杂得多,而且导致这些急转弯的错误是返回传递的参数,因此没有考虑新的和。speedaccelerationangle

我希望我清楚地解释了自己!请随时提出更多问题或获取代码片段:)

编辑:

根据 @SimonGoater 的评论,我的车现在可以绕圈子了,但似乎在较低的偏移量值接管另一辆车之前,汽车实际上不会转弯的问题仍然影响着我的游戏。acceleration

在这里,您可以看到顶部的值,然后在括号中看到其下方的值。如您所见,汽车面向屏幕的右下角,并且仍然不会转弯,因为当返回的速度超过 时,函数返回传递的参数(因此不考虑汽车的角度)。accelerationspeedspeedMAX_SPEED

car going almost completely right even though it's facing the bottom right corner of the picture(注意,如果速度说加速度在哪里,那是因为我的游戏里也有摩擦,这个问题可以忽略不计。0.050.17

Python 数学 游戏-物理 三角角

评论

0赞 Simon Goater 8/25/2023
如果 returned_speed[0]*returned_speed[0]+returned_speed[1]*returned_speed[1]<MAX_SPEED*MAX_SPEED 其他速度),您不希望 return(returned_speed 使用向量的实际长度(在本例中为平方)吗?
0赞 diogeek 8/25/2023
在试图解决这个问题时,我已经阅读了一段时间的平方和平方根,但我从来没有真正理解我们为什么要使用平方值?请您解释一下吗?
0赞 diogeek 8/25/2023
@SimonGoater 嗯,这似乎已经做到了!我真的很想知道为什么,但终于让我的汽车制作圆圈而不是那些奇怪的钻石感觉令人耳目一新。介意将此作为答案发布,以便我可以接受它,因为它解决了我的问题?编辑:它解决了我的“转弯时的方块”问题,但似乎我仍然有这个问题,我的车无法转弯,因为x_offset没有为y_offset留下足够的“空间”。我会编辑我的问题。
1赞 MJK 8/26/2023
我以前不确定,但现在我知道你错过了什么:一定要阅读有关向量和标量的信息。当你只是向上-向下-向左-向右移动时,这一切都很好,但是当涉及到二维平面(也称为笛卡尔平面)中的其他方向时,你需要间接使用勾股定理——这就是平方和平方根的用武之地。矢量很漂亮!

答:

1赞 MJK 8/25/2023 #1

注意:这不是一个全面的答案。它旨在帮助您找出问题所在,因为我需要更多的上下文(和时间:p)才能给出确切的答案。

我假设该函数在每次报价时都会被调用。add_acc_to_speed(speed, acceleration)

你为什么不尝试对以下方面施加限制:

new_speed = math.sqrt(((speed[0]+acceleration[0])**2 + (speed[1]+acceleration[1])**2)),

这基本上是.square_root(x_component^2 + y_component^2)

这是汽车的实际速度,这将处理“我已经尝试了什么?”下的点 #1 和 #2。

如果加速度后的此速度值大于 5,则可以通过以下方式返回考虑角度后速度的 x 和 y 分量:

x_comp = float(format(math.cos(angle),".2f")) # ".2f" for 2 decimal places

y_comp = float(format(math.sin(angle),".2f"))

这些 x_comp 和 y_comp 值将是给出最大速度 5 的浮点值。您可以根据需要修改它们的类型。

注意:您可以修改函数并添加“角度”作为参数,或者使用加速度的 y 和 x 分量之比的反 tan 函数从加速度中提取角度。math.atan()

希望这有帮助!

评论

0赞 diogeek 8/25/2023
感谢您的回答!我会研究这个。如果您需要我为您提供更多有关任何内容的背景信息,请随时询问!
2赞 Simon Goater 8/25/2023 #2

您正在计算速度矢量长度的曼哈顿距离 abs(x) + abs(y)。您应该使用正常的笛卡尔距离 sqrt(x^2 + y^2)。由于最大值不会改变,因此直接比较平方更有效,因为平方根计算相对较慢。我认为对于一个幼稚的解决方案,您只需要更改返回线

return(returned_speed if returned_speed[0]*returned_speed[0]
  +returned_speed[1]*returned_speed[1]
  <MAX_SPEED*MAX_SPEED else speed)

最好还是对 MAX_SPEED*MAX_SPEED 使用常量。如果长度超过 MAX_SPEED,则最好将向量缩放到最大长度,而不仅仅是返回前一个向量。这可以通过将两个分量乘以

MAX_SPEED / sqrt(returned_speed[0]*returned_speed[0]
  +returned_speed[1]*returned_speed[1])

如果分母超过 MAX_SPEED。

需要考虑的是,速度是通常用于位置变化率的术语,而“速度”通常是该矢量的标量长度。

评论

1赞 diogeek 8/25/2023
吃了一口又回来后,我把你的答案读了几遍,终于明白了。这是一些聪明的伎俩!当然比我自己能想出的更高水平的数学。它创造了奇迹,非常感谢