Величина вашего тормоза больше, чем ваша vx
при медленном движении. Кроме того, ваше тормозное усилие действует в направлении, противоположном направлению движения. Следовательно, торможение не 0-out vx
, а вместо этого отскакивает vx
в районе 0.
Например, представьте bmag = 1
, dt = 1
и vx = 2.6
. Вместо vx
происходит 2.6 -> 1.6 -> 0.6 -> 0
вместо этого идет 2.6 -> 1.6 -> 0.6 -> -0.4 -> 0.6 -> -0.4...
Это не заметно во время торможения, потому что движения взаимно компенсируют друг друга, поскольку оно постоянно меняет направление. Но как только вы отпускаете тормоз, он продолжается либо на 0.6
, либо на -0.4
в зависимости от времени, отсюда и ваше наблюдаемое «кажущееся случайным направление».
Чтобы исправить это, просто обнулите vx
, когда bmag * dt > vx
.
// current acceleration
let ax = (keyStates.ArrowRight * amag) + (keyStates.ArrowLeft * -amag);
// forward euler method; solves (x'(t), vx'(t)) = (vx(t), ax(t) - drag * vx(t))
x += dt * vx
vx += dt * (ax - Math.sign(vx) * drag * vx * vx)
if (keyStates[' '])
if (Math.abs(vx) > dt * bmag)
vx -= dt * bmag * Math.sign(vx);
else
vx = 0;
Кстати, спасибо за предоставленный воспроизводимый пример и небольшое подмножество, которое уместно. Это помогает как потенциальным ответчикам, так и будущим читателям.