Использование Thread.sleep будет проблематичным, так как Thread.sleep не гарантирует, что поток спит ровно 1000 мс, а поток не будет спать в течение , по крайней мере, 1000 мс.Кроме того, всякий раз, когда речь заходит о работе с потоками, будут существовать различия в поведении, зависящем от действительной системы, поскольку логика планирования потоков - это не функция вашего приложения или JVM, а скорее аппаратное обеспечение.
Моя рекомендацияЛибо отсоедините логику отрисовки от логики пересчета, либо дайте ей свободно работать, не блокируя поток с помощью Thread.sleep.Оттуда, чтобы получить хорошее движение, мы должны помнить, что изменение положения - это не только фактор скорости, но и время.Поэтому нам нужно рассчитать время, проходящее между различными кадрами рисования, с помощью некоторого механизма, такого как System.currentTimeMillis()
или System.nanoTime()
.
. Оттуда вы можете пересчитать позиции, умножив их скорость на количество времени, прошедшее с моментаrecalculating.
Грубая реализация:
double c = 1 / 60; // Some constant factor to bound motion over time
long previousCycleTime = System.currentTimeMillis();
while(somePredicate()) { // Logical cycle
long t = System.currentTimeMillis() - previousCycleTime;
gameObjects.forEach( o -> {
// t -> time passage
// dx -> change on the x axis
// c -> some constant factor to bound movement to the 'virtual space'
o.x += o.dx * t * c;
o.y += o.dy * t * c;
}
redraw();
}
Кроме того, вы можете перерисовать в отдельном потоке, чтобы разделить два процесса.Однако это не следует воспринимать легкомысленно, поскольку переход от однопоточного приложения к многопоточному приложению вносит значительную дополнительную сложность.