Синхронизация гравитации и FPS - PullRequest
0 голосов
/ 22 ноября 2018

Я занимаюсь разработкой простой игры, но у меня проблема с FPS и гравитацией.Поэтому мне нужно синхронизировать FPS и гравитацию, потому что чем выше FPS, тем быстрее игрок падает.Как я могу их синхронизировать?

Мой код для обновления проигрывателя:

            while (true) {
            try {
                Thread.sleep(1000 / GameMain.maxFPS); //Max Fps Limiter
                GameMain.activeEntities.forEach((ent) -> { //Revalidade All Entities and Positions
                    ent.onTick(); 
                });
                gamePanel.repaint(); //Repaint Frame, Update Positions
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

Мой код для обновления гравитации:

@Override
public void onTick() {
    this.velocity = this.velocity.add(0, gravityForce()/*<- I'm using 9.807 divided by 60*/);
    if (this.velocity.y > maxSpeed)
    {
        this.velocity.y = maxSpeed;
    }
    this.getPosition().y = this.getPosition().y + (this.velocity.y);
}

1 Ответ

0 голосов
/ 22 ноября 2018

Использование 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();
}

Кроме того, вы можете перерисовать в отдельном потоке, чтобы разделить два процесса.Однако это не следует воспринимать легкомысленно, поскольку переход от однопоточного приложения к многопоточному приложению вносит значительную дополнительную сложность.

...