Programming a smooth change of thrust from current velocity vector to a target vector

后端 未结 7 1705
北海茫月
北海茫月 2021-02-04 16:47

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 pl

7条回答
  •  灰色年华
    2021-02-04 17:41

    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.

提交回复
热议问题