Horodatage semi-fixe ou entièrement fixe?

15

Je fais un shmup pour iPhone et j'essaie de décider quel type de boucle de jeu utiliser. Je veux utiliser un pas de temps semi-fixe ou un pas de temps entièrement fixe.

Avec un pas de temps semi-fixe, je ferai zéro ou plusieurs appels de mise à jour (FIXED_INTERVAL) suivis d'un appel de mise à jour (dt) où dt <= FIXED_INTERVAL par boucle de jeu. Si je comprends bien, les inconvénients de cette méthode sont que ma logique de mise à jour physique (dt) sera plus difficile à programmer car je dois essentiellement assumer une variable dt pour chaque mise à jour. Et puis j'ai aussi entendu dire que chaque manche de mon jeu sera légèrement différente car les valeurs à virgule flottante ne sont pas les mêmes à chaque fois.

Ensuite, avec un pas de temps entièrement fixe, je fais zéro ou plusieurs appels de mise à jour (FIXED_INTERVAL) suivis d'un appel d'interpolation (dt / FIXED_INTERVAL) où dt <FIXED_INTERVAL par boucle de jeu.

Il semble donc que la grande décision que je dois vraiment prendre soit: est-ce que je veux relever le défi d'implémenter une mise à jour (dt) avec une variable dt ou est-ce que je veux relever le défi d'implémenter l'interpolation?

Maintenant, d'après ce que j'ai lu, la majorité des gens disent d'utiliser entièrement fixe et de faire l'interpolation. Mais quand je pense à l'implémentation de l'interpolation, il semble que je serais beaucoup plus complexe qu'une mise à jour (dt) avec une variable dt. En effet, si j'utilise l'interpolation, je dois me souvenir à la fois de l'état précédent et de l'état actuel. Donc, si je veux utiliser l'interpolation, je dois proposer une couche supplémentaire d'indirection qui résume des états de jeu individuels. Alors qu'avec un pas de temps semi-fixe où je n'ai pas à utiliser d'interpolation, je n'ai pas à proposer une abstraction d'état de jeu car il n'y a toujours qu'un seul état de jeu et ce sont simplement les "tableaux globaux" qui représentent mes ennemis, et l'ennemi balles etc.

Alors, quel est le choix le plus pratique: dois-je l'implémenter semi-fixe sachant que mes mises à jour physiques pourraient se compliquer avec la variable dt. Ou dois-je utiliser entièrement fixe et essayer de proposer une abstraction de l'état du jeu afin de pouvoir suivre l'état précédent et l'état actuel afin d'effectuer une interpolation?

Ryan
la source
Couvert assez bien ici: gamedev.stackexchange.com/questions/1589/...
michael.bartnett
1
J'ai lu cette discussion et les liens à plusieurs reprises. C'est en fait comment je suis arrivé à ce poste. Ma question porte principalement sur la façon de mettre en œuvre des états de jeu afin de réaliser l'interpolation - ce qui n'est pas du tout couvert dans cette discussion.
Ryan

Réponses:

12

Entièrement fixe

Vous perdez la plupart des avantages d'un pas de temps fixe lorsque vous lancez une étape variable une fois par image.

Noel Lopis a une grande écriture sur la façon dont il a mis en œuvre un pas de temps fixe dans son jeu Casey's Contraptions . En prime, il est un développeur d'iphone, bien que sa technique ne soit pas spécifique à l'iphone.

Quelques faits saillants de l'article

  • Utilisez un accumulateur de temps.
  • Utilisez un taux physique de 120 Hz pour une fréquence d'images de 60 Hz.
  • Simulez une étape fixe dans le futur et utilisez l'accumulation de temps restant pour lerp le code de dessin entre l'état physique actuel et l'état physique futur.
  • divers pièges
deft_code
la source
2

Ce que vous appelez un pas de temps "semi-fixe" et "entièrement fixe" sont, à mon avis, tous les deux un pas de temps fixe - le dt que vous passez à votre updateappel ne change pas entre les images.

Donc, votre question est en fait "est-ce que je veux implémenter l'interpolation à des fins de rendu?" La réponse est: probablement pas .

L'interpolation est quelque chose que vous ne voudriez faire que si votre pas de temps fixe updateest nettement différent de votre pas de temps cible render. Il n'est pas rare pour les jeux qui ont une updatephase intense d'appeler uniquement updateà, disons, 10 Hz, mais de rendre à plein débit.

Puisque vous écrivez un shmup iPhone, ni votre updateni votre renderbesoin ne sont particulièrement gourmands en CPU; vous pouvez facilement verrouiller votre fréquence d'images à 30 Hz ou 60 Hz, sans vous soucier de la mise en œuvre, tout en conservant un jeu fluide.

Blair Holloway
la source
Je ne comprends pas. Vous dites que je peux verrouiller le gros dt que je calculerais dans ma boucle de jeu - que ma physique consomme? Comment je fais ça? Puis-je le faire avec CADisplayLink? Je veux dire, quel% de CPU supposez-vous que j'utilise? Devez-vous vraiment assumer la boucle de jeu verrouillée dt?
Ryan
Ce que je dis se résume vraiment à ceci: faire la chose la moins compliquée qui fonctionnerait.
Blair Holloway
1
Élaboration: utiliser une variable dtpour updateet renderest la chose la plus simple qui fonctionnerait, mais généralement évitée lors de l'utilisation de moteurs physiques pour l'instabilité qu'elle provoque. Par conséquent, appelerupdate avec un fixe dtet rendre au même rythme (tout en supprimant des images si votre updateexécution est longue) est généralement la chose la plus simple qui fonctionnerait. L'écriture de code pour interpoler des objets entre les updateappels ajoute de la complexité à votre code; complexité que vous ajoutez pour résoudre aucun problème en particulier.
Blair Holloway