Я считаю, что ваш подход в корне ошибочен.Это склонно к ошибкам округления, которые могут быть источником для выбросов.Также трудно добиться хорошей работы в реальном мире, где ваше приложение не единственное, поэтому процессор может быть востребован, некоторые кадры могут быть пропущены и т. Д.Лучшим подходом является использование времени, а не кадров, в качестве основного фактора событий.Ваш основной метод drawScene
принимает текущее время в качестве одного из аргументов.Когда запускается любая анимация, вы экономите время ее запуска.Тогда работа становится намного проще.Например, для линейной анимации это будет примерно так:
double animationPart = (currentTime - animationStartTime) / totalAnimationDuration;
// fix rounding error
if (animationPart > 1.0)
animationPart = 1.0;
double xCur = xStart * (1.0 - animationPart) + xEnd * animationPart;
double yCur = yStart * (1.0 - animationPart) + yEnd * animationPart;
PS «время» не обязательно должно быть реальным временем, это может быть какое-то другое «игровое время», если оно каким-то образом имеет больше смыслано все же этот подход ИМХО намного проще реализовать правильно.
Обновление
Я бы сказал, что общее качество кода довольно плохое.Проблемы плохо разделены, есть много магических чисел и глобальных статических вещей.Например, использование двух пуль в полете будет нелегко реализовать в этом коде.
В коде анимации также есть некоторые реальные ошибки.Вот некоторые очевидные ошибки:
xPerF
рассчитано неверно.Вы разделяете евклидово расстояние, а не просто разницу в координате X.
Логика для y
ошибочна.По крайней мере, вы должны добавить m * (x - x1)
вместо m * x
.Но это все равно не будет охватывать случай вертикальной съемки (т.е. случай, когда X-координата вообще не изменяется).Если вы хотите пойти по этому пути, вы должны использовать xPerF
и yPerF
и избавиться от m
и связанных с ним if
.
Это может или не может исправить проблемы с анимацией (в списке у вас все еще есть вероятность ошибок округления).Я бы все еще сказал, что изменение вашего shoot
на что-то вроде
public void shootTarget(int target) {
shotTarget = target;
shotTime = animationFrame;
}
и затем использование
double animationPart = ((double) (animationFrame - shotTime)) / animationSpeed;
, как предложено выше, является лучшим способом.Примечание: это всего лишь заглушка, потому что в вашем реальном коде вы по какой-то причине регулярно присваиваете 0
для refresh
и, следовательно, animationFrame
, так что это не будет работать так просто.