Zastanawiałem się, czy istnieje jakakolwiek szkoda, gdy moja pętla gry działa tak szybko, jak pozwala na to system?
Obecnie mam pętlę, która mierząc upływ czasu w nanosekundach, uruchamia logikę gry i renderuje logikę z predefiniowanymi prędkościami bez problemu. W rzeczywistości każda logika, którą wykonuję w pętli, jest taktowana na określoną liczbę wywołań co sekundę.
Sama pętla działa jednak tak szybko, jak chce, a na mojej maszynie dochodzi do około 11,7 miliona pętli na sekundę.
Pętla (prosty pseudokod):
while(!isGameOver){
if(canPollInputs){
pollInputs()
}
while(canStepLogic){
stepLogic()
}
if(canRender){
render()
}
}
Moje pytanie jest w zasadzie, czy ta prosta pętla, jeśli nie działa z kontrolowaną prędkością, może wyrządzić szkodę systemowi?
Edycja: Oznacza to, że moja logika działa 30 razy na sekundę (30 tps), mój renderer działa przy 60 fps, odpytuję dane wejściowe 100 razy na sekundę, a także jest trochę logiki, aby poradzić sobie z logiką lub renderowaniem trwającym dłużej niż oczekiwano . Ale sama pętla nie jest dławiona.
Edycja: użycie Thread.sleep()
np. Przepustnicy głównej pętli w dół do 250 pętli na sekundę prowadzi do zmniejszenia, ale pętle działają z prędkością około 570 pętli na sekundę zamiast pożądanych 250 (doda kod, gdy będę na komputerze stacjonarnym ..)
Edycja: Proszę bardzo, działająca gra java w celu wyjaśnienia rzeczy. Możesz też z niego korzystać, ale nie rób sobie tego;)
private void gameLoop() {
// Time that must elapse before a new run
double timePerPoll = 1000000000l / targetPPS;
double timePerTick = 1000000000l / targetTPS;
double timePerFrame = 1000000000l / targetFPS;
int maxFrameSkip = (int) ( (1000000000l / MINIMUM_FPS) / timePerTick);
int achievedPPS = 0;
int achievedFPS = 0;
int achievedTPS = 0;
long timer = TimeUtils.getMillis();
int loops = 0;
int achievedLoops = 0;
long currTime = 0l;
long loopTime = 0l;
long accumulatorPPS = 0l;
long accumulatorTPS = 0l;
long accumulatorFPS = 0l;
long lastTime = TimeUtils.getNano();
while(!isRequestedToStop) {
currTime = TimeUtils.getNano();
loopTime = currTime - lastTime;
lastTime = currTime;
loops = 0;
accumulatorPPS += loopTime;
accumulatorTPS += loopTime;
accumulatorFPS += loopTime;
if(accumulatorPPS >= timePerPoll) {
pollInputs();
playerLogic();
achievedPPS++;
accumulatorPPS -= timePerPoll;
}
while(accumulatorTPS >= timePerTick && loops < maxFrameSkip) {
tick();
achievedTPS++;
accumulatorTPS -= timePerTick;
loops++;
}
// Max 1 render per loop so player movement stays fluent
if(accumulatorFPS >= timePerFrame) {
render();
achievedFPS++;
accumulatorFPS -= timePerFrame;
}
if(TimeUtils.getDeltaMillis(timer) > 1000) {
timer += 1000;
logger.debug(achievedTPS + " TPS, " + achievedFPS + " FPS, "
+ achievedPPS + " Polls, " + achievedLoops + " Loops");
achievedTPS = 0;
achievedFPS = 0;
achievedLoops = 0;
}
achievedLoops++;
}
}
Jak widać, prawie nie ma kodu uruchamianego w każdej pętli, ale zawsze określony wybór na podstawie czasu, który upłynął. Pytanie dotyczy tej „pętli roboczej” i tego, jak wpływa ona na system.