编程推力从当前速度矢量到目标矢量的平滑变化 [英] Programming a smooth change of thrust from current velocity vector to a target vector

查看:64
本文介绍了编程推力从当前速度矢量到目标矢量的平滑变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; dr:我不确定如何计算一个向量与另一个向量之间的推力平滑过渡."

我正在编写一个简单的游戏,敌人在空旷的地方(没有墙壁)追击玩家.我正在计算敌人的x& y速度独立地进行,如果它们将它们带向玩家方向则加速它们,如果它们以错误的方式走,则迅速减慢它们的速度(例如EnemyVelocity.x> 0& player.x <敌人.x,然后是EnemyVelocity.x -2.)

虽然躲避敌人的游戏玩法相当有趣,但我希望让敌人使用适当的物理表现.我目前正在做的是让敌人根据他们和玩家之间的角度来设定他们的推力(想像一艘太空飞船),并让他们的推力加速到最大速度(计算EnemyVelocity三角形的c边).一旦发生这种情况,我不确定是否可以自行调整推力的最佳方法.如果我没有留下最大速度,敌人会加速加速,但会轻易地使玩家超越,然后花很长时间才能获得足够的动量,使其朝着玩家的方向前进.

我想做的是让敌人在到达玩家的路上不断调整他们的速度,瞄准他们所处的位置(我不想让他们预测你的位置).然后,当他们想念玩家时,我想要相同的推力&加速公式来重新调整它们的速度并将其发送回播放器.

我认为这将涉及两个向量:一个是敌人当前正在旅行的地方,另一个是敌人想要旅行的地方(将它们直接带到玩家的向量).我不确定如何计算一个向量与另一个向量之间的推力平滑过渡.

任何提示,公式或问题将不胜感激!谢谢你堆栈溢出.

解决方案

这一切都回到牛顿方程:

F = m * a
s = s_o + v * t + a * t^2 / 2
v = v_o + a * t

在这种情况下,F是力(推力),a是加速度,m是船的质量. s是当前位置,s_o是原始位置,v是速度,t是当前时间.

当然这是一条直线,因此,如果要转换为二维或三维,则必须做一些数学运算. Fsva都是向量,这意味着它们的方向同样重要.从技术上讲,t也是一个向量,但是由于时间通常只沿一个方向,因此我们不必为此担心.

2d:
F^2 = F_x^2 + F_y^2 (use Pythagorean theorem to split force into components)
F_x = m * a_x
F_y = m * a_y
s_x = s_o_x + v_x * t + a_x * t^2 / 2
s_y = s_o_y + v_y * t + a_y * t^2 / 2
v_x = v_o_x + a_x * t
v_y = v_o_y + a_y * t

3d:
F^2 = F_x^2 + F_y^2 + F_z^2 (surprisingly, this works)
F_x = m * a_x
F_y = m * a_y
F_z = m * a_z
s_x = s_o_x + v_x * t + a_x * t^2 / 2
s_y = s_o_y + v_y * t + a_y * t^2 / 2
s_z = s_o_z + v_z * t + a_z * t^2 / 2
v_x = v_o_x + a_x * t
v_y = v_o_y + a_y * t
v_z = v_o_z + a_z * t

现在可以将速度调整到播放器的方向,您将获得固定的总力(F),以便更改当前朝向播放器的速度.在物理学中,事情不会立即发生,但您的目标应该是最大程度地减少发生变化的时间.

根据您的目标速度(忽略加速度),您可以根据当前位置((s_o_x,s_o_y)(s_o_x,s_o_y,s_o_z))和对手的当前位置或目标位置((s_x,s_y)(s_x,s_y,s_z))得出方程式

v_x = (s_x - s_o_x) / t
v_y = (s_y - s_o_y) / t

v_x = (s_x - s_o_x) / t
v_y = (s_y - s_o_y) / t
v_z = (s_z - z_o_y) / t

我们可以用其他方程式代替

(s_x - s_o_x) / t = v_o_x + a_x * t
(s_y - s_o_y) / t = v_o_y + a_y * t

(s_x - s_o_x) / t = v_o_x + a_x * t
(s_y - s_o_y) / t = v_o_y + a_y * t
(s_z - z_o_y) / t = v_o_z + a_z * t

然后我们求解加速度(这与力有关,这就是我们要计算的力).

(s_x - s_o_x) / t^2 - v_o_x / t = a_x
(s_y - s_o_y) / t^2 - v_o_y / t = a_y

(s_x - s_o_x) / t^2 - v_o_x / t = a_x
(s_y - s_o_y) / t^2 - v_o_y / t = a_y
(s_z - z_o_y) / t^2 - v_o_z / t = a_z

将其插入力方程:

F_x = m * (s_x - s_o_x) / t^2 - m * v_o_x / t
F_y = m * (s_y - s_o_y) / t^2 - m * v_o_y / t

F_x = m * (s_x - s_o_x) / t^2 - m * v_o_x / t
F_y = m * (s_y - s_o_y) / t^2 - m * v_o_y / t
F_z = m * (s_z - z_o_y) / t^2 - m * v_o_z / t

现在解决t:

t = (-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
t = (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y

t = (-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
t = (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
t = (-m * v_o_z +/- sqrt(m^2 * v_o_z^2 - 4 * F_z * m * (s_z - s_o_z))) / 2 / F_z

时间应该收敛,所以时间将相等!这为每个坐标(平面和球面)提供了一个方程式系统.请注意,存在多个可能的值,但其中一些涉及虚数,因此您必须消除这些解:

(-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
= (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
F^2 = F_x^2 + F_y^2

(-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
= (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
= (-m * v_o_z +/- sqrt(m^2 * v_o_z^2 - 4 * F_z * m * (s_z - s_o_z))) / 2 / F_z
F^2 = F_x^2 + F_y^2 + F_z^2

求解(F_x,F_y)(F_x,F_y,F_z)坐标,您便拥有了所需的力量.

如果您有任何疑问或在数学中发现错误,请告诉我.

TL;dr: "I am not sure how to calculate a smooth transition of thrust between one vector and another."

I am programming a simple game where an enemy chases after the player in an open space (no walls). I was calculating the enemy's x & y velocities independently, accelerating them if they were taking them in the direction of the player and quickly slowing them if they were going the wrong way (e.g. EnemyVelocity.x > 0 & player.x < enemy.x, then EnemyVelocity.x - 2.)

While the gameplay is decently fun trying to dodge the enemy, it is my desire to have the enemy behave using proper physics. What I am currently doing is have the enemy set their thrust (think a spaceship) based on the angle between them and the player, and have their thrust accelerate up to a max speed (calculating side c of the EnemyVelocity triangle). Once that happens, I'm not sure the best way to have the thrust adjust itself. If I leave no max speed, the enemy accelerates nicely but will easily overshoot the player, and then take a long time to get enough momentum heading back in the player's direction.

What I'd like to happen is have the enemy constantly adjust their velocity on the way to the player, targeting wherever they are at (I don't want them to predict where you will be). Then, when they miss the player, I'd like for the same thrust & acceleration formulas to readjust their velocity and send them back at the player.

I'm thinking this will involve two vectors: one where the enemy is currently traveling, and one where the enemy wants to travel (the vector that will take them straight to the player). I am not sure how to calculate a smooth transition of thrust between one vector and another.

Any tips, formulas or questions will be much appreciated! Thank you Stack Overflow.

解决方案

It all comes back to Newton's equations:

F = m * a
s = s_o + v * t + a * t^2 / 2
v = v_o + a * t

In this case F is the force (thrust), a is the acceleration, and m is the mass of the ship. s is the current location, s_o is the original location, v is the velocity, and t is the current time.

Of course this is along a straight line, so if you want to convert to two or three dimensions you'll have to do some math. F, s, v, and a are all vectors, meaning that their direction is equally important. Technically t is also a vector, but since time generally only goes one direction, we don't have to worry about that.

2d:
F^2 = F_x^2 + F_y^2 (use Pythagorean theorem to split force into components)
F_x = m * a_x
F_y = m * a_y
s_x = s_o_x + v_x * t + a_x * t^2 / 2
s_y = s_o_y + v_y * t + a_y * t^2 / 2
v_x = v_o_x + a_x * t
v_y = v_o_y + a_y * t

3d:
F^2 = F_x^2 + F_y^2 + F_z^2 (surprisingly, this works)
F_x = m * a_x
F_y = m * a_y
F_z = m * a_z
s_x = s_o_x + v_x * t + a_x * t^2 / 2
s_y = s_o_y + v_y * t + a_y * t^2 / 2
s_z = s_o_z + v_z * t + a_z * t^2 / 2
v_x = v_o_x + a_x * t
v_y = v_o_y + a_y * t
v_z = v_o_z + a_z * t

Now to adjust your velocity to the direction of the player, you've got a fixed total force (F) in order to change your current velocity toward the player. In physics things don't happen instantaneously, but your goal should be to minimize the time in which the change happens ('t').

This gives you an equation in terms of your current location ((s_o_x,s_o_y) or (s_o_x,s_o_y,s_o_z)) and your opponent's current location or your target location ((s_x,s_y) or (s_x,s_y,s_z)), for your target velocity (ignores acceleration).

v_x = (s_x - s_o_x) / t
v_y = (s_y - s_o_y) / t

v_x = (s_x - s_o_x) / t
v_y = (s_y - s_o_y) / t
v_z = (s_z - z_o_y) / t

We can substitute this for our other equation:

(s_x - s_o_x) / t = v_o_x + a_x * t
(s_y - s_o_y) / t = v_o_y + a_y * t

(s_x - s_o_x) / t = v_o_x + a_x * t
(s_y - s_o_y) / t = v_o_y + a_y * t
(s_z - z_o_y) / t = v_o_z + a_z * t

We then solve for the acceleration (this is related to the force, which is what we are trying to calculate).

(s_x - s_o_x) / t^2 - v_o_x / t = a_x
(s_y - s_o_y) / t^2 - v_o_y / t = a_y

(s_x - s_o_x) / t^2 - v_o_x / t = a_x
(s_y - s_o_y) / t^2 - v_o_y / t = a_y
(s_z - z_o_y) / t^2 - v_o_z / t = a_z

Plug this into the force equation:

F_x = m * (s_x - s_o_x) / t^2 - m * v_o_x / t
F_y = m * (s_y - s_o_y) / t^2 - m * v_o_y / t

F_x = m * (s_x - s_o_x) / t^2 - m * v_o_x / t
F_y = m * (s_y - s_o_y) / t^2 - m * v_o_y / t
F_z = m * (s_z - z_o_y) / t^2 - m * v_o_z / t

Now solve for t:

t = (-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
t = (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y

t = (-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
t = (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
t = (-m * v_o_z +/- sqrt(m^2 * v_o_z^2 - 4 * F_z * m * (s_z - s_o_z))) / 2 / F_z

The times should converge, so the times will be equal! This gives us a system of equations for each coordinate (plane and sphere). Note that there are multiple possible values, but some involve imaginary numbers so you'll have to eliminate those solutions:

(-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
= (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
F^2 = F_x^2 + F_y^2

(-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
= (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
= (-m * v_o_z +/- sqrt(m^2 * v_o_z^2 - 4 * F_z * m * (s_z - s_o_z))) / 2 / F_z
F^2 = F_x^2 + F_y^2 + F_z^2

Solve for the (F_x,F_y) or (F_x,F_y,F_z) coordinates and you've got the force you need.

Let me know if you have any questions or if you find mistakes in my math.

这篇关于编程推力从当前速度矢量到目标矢量的平滑变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆