好极了!我做的!
我正在使用简单的模拟,该模拟的第一个位置降落在目标点的垂直轴后面-从那里开始,我采用先前的模拟位置并进行分割。现在,我检查目标点是否在此线段之下。如果是,我们可以跳到那里。
它是gif上由玩家控制的角色。粉色是预测的路径,黄色段是预测的后续步进位置,如果目标点位于其下方,则最后一段变为白色,否则为红色。红色曲线是实际的飞行路径。由于打开了物理状态插值,因此存在一些轻微的错误。
计算结果出乎意料地容易,但是让我的环境像这些纯计算一样进行工作……这是一个巨大的麻烦。至少我解决了一些严重的错误,所以毕竟这是一个有用的练习。
这是Lua中用于解决原始问题的完整代码(代码假定您拥有自己的“ debug_draw”例程和带有基本方法(例如“ length_sq”(长度平方),“ normalize”或运算符+,*的向量类)的代码:
function simple_integration(p, dt)
local new_p = {}
new_p.acc = p.acc
new_p.vel = p.vel + p.acc * dt
new_p.pos = p.pos + new_p.vel * dt
-- uncomment this if you want to use quadratic integration
-- but with small timesteps even this is an overkill since Box2D itself uses traditional Euler
-- and I found that for calculations to be accurate I either way must keep the timesteps very low at the beginning of the jump
--+ p.acc * dt * dt * 0.5
return new_p
end
function point_below_segment(a, b, p)
-- make sure a is to the left
if a.x > b.x then a,b = b,a end
return ((b.x - a.x)*(p.y - a.y) - (b.y - a.y)*(p.x - a.x)) < 0
end
-- returns true or false
function can_point_be_reached_by_jump
(
gravity, -- vector (meters per seconds^2)
movement_force, -- vector (meters per seconds^2)
air_resistance_mult, -- scalar
queried_point, -- vector (meters)
starting_position, -- vector (meters)
starting_velocity, -- vector (meters per seconds)
jump_impulse, -- vector (meters per seconds)
mass -- scalar (kilogrammes)
)
local my_point = {
pos = starting_position,
vel = starting_velocity + jump_impulse/mass
}
local direction_left = movement_force.x < 0
local step = 1/60
while true do
-- calculate resultant force
my_point.acc =
-- air resistance (multiplier * squared length of the velocity * opposite normalized velocity)
(vec2(my_point.vel):normalize() * -1 * air_resistance_mult * my_point.vel:length_sq()) / mass
-- remaining forces
+ gravity + movement_force/mass
-- I discard any timestep optimizations at the moment as they are very context specific
local new_p = simple_integration(my_point, step)
debug_draw(my_point.pos, new_p.pos, 255, 0, 255, 255)
debug_draw(new_p.pos, new_p.pos+vec2(0, -1), 255, 255, 0, 255)
if (direction_left and new_p.pos.x < queried_point.x) or (not direction_left and new_p.pos.x > queried_point.x) then
if point_below_segment(new_p.pos, my_point.pos, queried_point) then
debug_draw(new_p.pos, my_point.pos, 255, 0, 0, 255)
return true
else
debug_draw(new_p.pos, my_point.pos, 255, 255, 255, 255)
return false
end
else
my_point = new_p
end
end
return false
end
接受Jason指导我朝正确的方向前进!谢谢!