Игра работает на скорости 60 кадров в секунду, но после замедления она работает очень быстро в течение нескольких секунд
Я разрабатываю игру с плиткой. В большинстве случаев игра "уважает" ограничение 60 кадров в секунду, однако, когда я намеренно устанавливаю fps равным 10 кадрам в секунду в течение 5 секунд (с помощью отладки), чтобы проверить, что игровой рендеринг и логика игры работают раздельно, происходит то, что после того, как я возвращаюсь назад игра fps до 60 кадров в секунду, в течение нескольких секунд игра игнорирует "кепку" и работает со скоростью 10000 к / с, затем возвращается к пределу. Причина всего этого заключается в том, что я хочу, чтобы моя игра работала с переменной частотой кадров / с, но с постоянной логической скоростью на всех машинах, однако я не понимаю, почему моя игра в большинстве случаев соблюдает ограничение и никогда не поднимается выше 60 кадров / с, но когда происходит замедление или скачок задержки, игра проходит супер быстрее в течение 1-2 секунд, а затем возвращается в нормальное состояние. Независимо от того, работает ли пользователь на плохом компьютере, а игра работает на скорости 5 кадров в секунду, я хочу, чтобы игра никогда не превышала мою жесткую кепку.
Мне нужно было реализовать систему "пропущенных кадров" или что-то в этом роде? Просто для информации, моя игровая логика очень легкая, но рендеринг довольно тяжелый.
new Thread(){
public void run(){
long hintPoint = System.currentTimeMillis();
long nexttickG = System.currentTimeMillis();
long nexttickL = System.currentTimeMillis();
long nexttickV = System.currentTimeMillis();
long ticktimeV = 1000;
long LogicCap = 60;
long ticktimeL = 1000/LogicCap;
short frames = 60;
while(isRunning){
if(Main.servbot){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);
short FramesCap = GLOBAL_FPS_CAP;
long ticktimeG = 1000/FramesCap;
if (System.currentTimeMillis()>nexttickG){
Render();
long elapsed = System.currentTimeMillis() - hintPoint;
frames=(short)((long)1000/(Math.max(elapsed,1)));
hintPoint = System.currentTimeMillis();
nexttickG+=ticktimeG;
}
if (System.currentTimeMillis()>nexttickL){
GameLoop();
nexttickL+=ticktimeL;
}
if (System.currentTimeMillis()>nexttickV){
GLOBAL_FPS_HINT = frames;
nexttickV+=ticktimeV;
}
Thread.yield();
}
}
}.start();
}
2 ответа
Могут ли эти изменения помочь? (см. код ниже, ищите /* новый */).
Причина: вы устанавливаете точку останова в своем методе run ()? Какие вар (ы) вы изменяете
Сколько миллисекунд тикает в System.currentTimeMillis(), пока вы изменяете переменную (я) для изменения частоты кадров? Похоже, если вам потребуется 3 или 4 (возможно, 12) секунды, чтобы внести изменения и возобновить выполнение, ваши значения nextTickL и nextTickG будут значительно отставать от System.currentTimeMillis() и могут потребовать МНОГО добавлений += ticktimeG, чтобы наверстать упущенное на системные часы.
new Thread(){
public void run(){
long hintPoint = System.currentTimeMillis();
long nexttickG = System.currentTimeMillis();
long nexttickL = System.currentTimeMillis();
long nexttickV = System.currentTimeMillis();
long ticktimeV = 1000;
long LogicCap = 60;
long ticktimeL = 1000/LogicCap;
short frames = 60;
while(isRunning){
if(Main.servbot){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);
short FramesCap = GLOBAL_FPS_CAP;
long ticktimeG = 1000/FramesCap;
if (System.currentTimeMillis()>nexttickG){
Render();
long elapsed = System.currentTimeMillis() - hintPoint;
frames=(short)((long)1000/(Math.max(elapsed,1)));
hintPoint = System.currentTimeMillis();
nexttickG+=ticktimeG;
/*new*/ if( nexttickG < System.currentTimeMillis() ) {
/*new*/ // major clock skew somehow, reset.
/*new*/ nexttickG = System.currentTimeMillis() + ticktimeG;
/*new*/ }
}
if (System.currentTimeMillis()>nexttickL){
GameLoop();
nexttickL+=ticktimeL;
/*new*/ if( nexttickL < System.currentTimeMillis() ) {
/*new*/ // major clock skew somehow, reset.
/*new*/ nexttickL = System.currentTimeMillis() + ticktimeL;
/*new*/ }
}
if (System.currentTimeMillis()>nexttickV){
GLOBAL_FPS_HINT = frames;
nexttickV+=ticktimeV;
}
Thread.yield();
}
}
}.start();
Во-первых, если это возможно, используйте .nanoTime()
вместо .currentTimeMillis()
потому что второй гораздо более подвержен ошибкам.
И во-вторых, рассмотреть вопрос о реализации DELTA-TIME
система, где FPS
а также Game-World Time
независимы друг от друга.
Delta-Time - это правильный шаблон петли для таких вещей, как анимация и игры (которые в основном являются программными, систематическими, а иногда и хаотичными анимациями game-world
данные), потому что это самый простой шаблон, который избегает time-drift bugs
из наиболее наивных / упрощенных animation-loop
или же game-loop
Реализации.
Вот пример того, как реализовать Delta-Time
игровой цикл в Java.
Для полного объяснения проблемы с реализациями наивного цикла, и как Delta-Time
решает проблему смещения времени (и, следовательно, почему она используется), взгляните на эту статью и эту статью, в которых подробно объясняются различия в игровых циклах.