J'écris une boucle de jeu, j'ai trouvé le code dans l'exemple ci-dessous ici . J'ai également examiné d'autres façons de faire une boucle de jeu, comme à partir de cet article . Je n'ai pas réussi à faire fonctionner ceux-là. J'ai donc gardé celui du premier lien.
Ce que j'aimerais savoir:
Thread.sleep();
dans ma boucle de jeu?Voici mon code actuel:
public void run(){
long lastLoopTime = System.nanoTime();
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
long lastFpsTime = 0;
while(true){
long now = System.nanoTime();
long updateLength = now - lastLoopTime;
lastLoopTime = now;
double delta = updateLength / ((double)OPTIMAL_TIME);
lastFpsTime += updateLength;
if(lastFpsTime >= 1000000000){
lastFpsTime = 0;
}
this.updateGame(delta);
this.repaint();
try{
Room.gameTime = (lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000;
System.out.println(Room.gameTime);
Thread.sleep(Room.gameTime);
}catch(Exception e){
}
}
Finalement, vous voudrez passer à quelque chose comme LWJGL , mais permettez-moi de souligner, continuez à faire ce que vous faites ici pour l'instant. Il vous apprendra les bases.
Bon travail sur votre boucle. Looks Nice, permettez-moi de vous offrir quelques conseils:
Repeindre ne rendra pas l'écran immédiatement. Il indique au RepaintManager de s'afficher lorsqu'il est prêt. Utilisation invaliderpaintImmediately à la place. paintImmediately
bloquera l'exécution jusqu'à ce que le composant soit redessiné afin que vous puissiez mesurer le temps de rendu.
Thread.sleep
a généralement une dérive de quelques millisecondes. Vous devriez l'utiliser pour éviter que votre boucle n'utilise trop de CPU, mais assurez-vous de comprendre que si vous dormez 10 millisecondes, vous pouvez dormir 5 millisecondes ou vous pouvez dormir 20.
Enfin:
double delta = updateLength / ((double)OPTIMAL_TIME);
Si updateLength
est inférieur à OPTIMAL_TIME, n'appelez pas update. En d'autres termes, si delta est inférieur à un, ne mettez pas à jour. Ce tutoriel explique pourquoi mieux que jamais.
Dans l'ensemble, c'est une bonne boucle, mais il y a quelques aspects manquants à ce que j'ai trouvé par expérience comme la meilleure boucle.
Vous voudrez éventuellement passer à LWJGL ou à un autre Java API de jeu, mais pour l'instant, apprenez les bases de la façon dont les boucles de jeu fonctionnent et ce qui convient le mieux à vos besoins.
Tout d'abord, en réponse à l'un de vos points, non. Vous ferez mieux de rester loin de
Thread.sleep ()
cela peut s'écarter de la durée réelle de mise en veille.
par exemple. si vous le mettez en veille pendant 10 millisecondes, il peut mettre le programme en veille pendant 5 à 20 millisecondes.
Le deuxième problème que je vois immédiatement est que vous n'avez aucun moyen d'arrêter la boucle de jeu pour une méthode stop () personnalisée. Essayer
boolean running = true;
en courant) {
// Votre code ici //
}
Troisièmement, vous voudrez peut-être envisager de modifier la façon dont vous utilisez votre variable delta. Le chemin dans le code ci-dessous peut être une meilleure utilisation et construction pour vous.
Voici un exemple de ma boucle de jeu que j'utilise dans mes programmes:
@Override
public void run() {
long initialTime = System.nanoTime();
final double timeU = 1000000000 / UPS;
final double timeF = 1000000000 / FPS;
double deltaU = 0, deltaF = 0;
int frames = 0, ticks = 0;
long timer = System.currentTimeMillis();
while (running) {
long currentTime = System.nanoTime();
deltaU += (currentTime - initialTime) / timeU;
deltaF += (currentTime - initialTime) / timeF;
initialTime = currentTime;
if (deltaU >= 1) {
getInput();
update();
ticks++;
deltaU--;
}
if (deltaF >= 1) {
render();
frames++;
deltaF--;
}
if (System.currentTimeMillis() - timer > 1000) {
if (RENDER_TIME) {
System.out.println(String.format("UPS: %s, FPS: %s", ticks, frames));
}
frames = 0;
ticks = 0;
timer += 1000;
}
}
}