CodeS-SourceS
Rechercher un code, un tuto, une réponse

[mirc] animation et synchronisation du fps

Juin 2017


= =ANIMATION ET SYNCHRONISATION DU FPS==




Version : 1.0
Niveau requis : débutant/intermédiaire
Domaine : PicWin
Crédits : Un grand merci à ToKeN pour ses très bonnes idées.
Auteur : Epsilon
Traduction et mise en forme : moo

<HR>
1) Avant propos

Introduction



Calcul du FPS



Régler la vitesse des objets en mouvements



Exemple de démonstration



Conclusion


<HR>
1) Avant propos

Ce tutoriel à été écrit par Epsilon et traduit moo, avec l'accord de son auteur; pour la communauté francophone de scripteurs mIRC. Vous pourrez trouver l'original sur
Picwin.tk
. : *
Dans le but de faciliter la lecture des codes mIRC présents dans ce tutoriel, nous utiliserons certaines conventions. A savoir :
  • Rouge

: relatif aux commandes
<LI>Bleu : relatif aux identifieurs
<LI>Violet : relatif aux variables
<LI>Gris foncé : relatif aux commentaires


Sur ce, bonne lecture ! : *

2) Introduction

Si vous avez déjà essayé d'animer un objet en fenêtre image (texte en mouvement, balle rebondissante, ...), vous avez certainement dû utiliser un alias un grand nombre de fois à l'aide d'un timer en milliseconde.

Par exemple :

.timeranim
-m 0 200
/game_anim


Et vous avez certainement dû incrémenter les coordonées de l'objet avec une constante dans cet alias.

Par exemple :

/inc

%ball.x 10


Si c'est ce que vous faisiez, alors OUBLIEZ TOUT ÇA C'EST UNE TRÈS MAUVAISE MÉTHODE !

Pourquoi ?

Parce que mettre un intervalle millisecondes dans un timer (ici, 200) ne signifie pas que l'alias sera éxécuté toutes les 200 millisecondes, cela à cause de plusieurs raisons :
  • /timer -m n'est pas précis (certaines fois il s'éxécutera après 210ms, d'autres fois après 204ms, ...)

<LI>Cette méthode ne prend pas en compte le temps que mettra votre alias pour dessiner, une fois celui-ci éxécuté. La rapidité dépendra grandement du processeur et de la carte graphique de l'utilisateur.
<LI>La valeur fixée pour Delta (comme le nombre de pixels à incrémenter par frames) donnera différents résultats d'un processeur à un autre. Si vous incrémentez un valeur de 10 à chaque frame, à 60 FPS, cette valeur sera incrémentée de 600 toutes les secondes, et à 20 FPS, seulement de 200 pixels. Cela signifie que la vitesse dépend donc du FPS. Et le FPS dépendra de beaucoup d'autres choses (autres programmes lancés, une augmentation soudaine de la mémoire vive utilisée par votre processeur, etc.), il vous sera donc impossible de définir une vitesse moyenne exacte.
<LI>Quelque chose qui tourne bien sur votre PC tournera trop vite sur les prochaines générations de PC (et trop lentement sur les vieux PCs). Vous devez vous assurer que votre animation tournera aussi bien sur un vieux PC que sur un PC très récent..
Avec ce tutoriel, vous apprendez comment calculer la vitesse en pixel par seconde au lieu de la vitesse en pixel par frame.
Peu importe la machine, la mémoire utilisée et le FPS courant, votre animation doit toujours tourner à la même vitesse.

Oui, c'est possible. La seule chose qui variera est la fluidité de l'animation, mais pas la vitesse.

Remarque importante : dans ce tutoriel, nous utiliserons le nombre de ticks avec $ticks, mais vous pouvez d'ores et dejà oublier cet identifieur, car il n'est pas assez précis pour la synchronisation du FPS. Un grand calcul sur le FPS nécessite une grande précision (plus ou moins 1ms), et l'identifieur $ticks est limité à une précision de 10ms sur WinXP/2K (et à 55ms sur Win9x). Si vous voulez tester la précision :


| alias

test.tick {
var
%i = 0 |
while (
%i <= 100) {
echo -a
$ticks |
inc
%i } }


Vous aurez donc besoin d'un DLL avec une fonction retournant le nombre de ticks précis, comme Game Tools
, ou vous ne pourrez pas synchroniser le FPS au-dessus de 60 FPS (et également en-dessous avec Win9x)



3) Calcul du FPS

Tout d'abord, nous avons besoin d'un alias d'initialisation, et d'un alias 'boucle' (qui permettra de dessiner).


{
%fps = 0
%frame.counter = 0%fps.tick $ticksloop==
; charge l'animation

}
alias init

Cet alias initialise %fps et %frame.counter (compteur de frames) à 0, et %fps.tick à $ticks (nombre de ticks, souvenez-vous de ne pas utiliser $ticks dans votre jeu mais un DLL qui donnera le nombre de ticks précis).

Ensuite, l'alias 'boucle', qui sera éxécuté [FPS * fois par seconde.

alias

main.loop {
(...) on dessine ici (...)

if (
$calc(
$ticks -
%fps.tick) >= 1000) {

%fps =
%frame.counter ; le FPS est égal au nombre de frames pendant cette seconde

%frame.counter = 0
; on réinitialise le compteur de frames à 0

%fps.tick =
$ticks ; on réinitialise %fps.tick au nombre de ticks
}
(...)
}


Ceci
calculera le FPS (le nombre de fois que l'alias a été éxécuté). N'utilisez jamais un second timer avec un délai d'une seconde pour calculer le FPS.

Maintenant, nous avons besoin de déclencher l'alias 'boucle'. La meilleure méthode pour utiliser le moins de mémoire possible est d'appeler l'alias une nouvelle fois avec un /.timer -h 1 0 /main.loop.

ToKeN a trouvé cette méthode. Cela appelle l'alias immédiatement, mais sans utiliser de mémoire vive comme le ferait un while() par exemple. Ceci n'est valable qu'une fois, n'utilisez donc pas de /.timer -h 0 0, pour faire une boucle continuellement, ce n'est pas la meilleure méthode.

Placez cette ligne à la fin de boucle principale (main.loop) :

.timeranim -ho 1 0
/main.loop


Astuce : Vous pouvez utiliser cet 'unique' timer pour retarder le prochain appel de la boucle, vous limiterez ainsi le FPS maximum. Le délai est de (1000 / [maxFPS * ).

Exemple :

.timeranim -ho 1
$calc(1000/20)
/main.loop ;Pour limiter l'animation à 20 FPS, peu importe le PC utilisé (cela ne signifie pas qu'il tournera toujours à 20 FPS, mais au plus à 20 FPS).

Mais
, il y a une chose à prendre en compte pour fixer une valeur appropriée au FPS de façon certaine quand vous retardez le timer : c'est le temps que met l'alias à être éxécuté. Donc mettez une variable %start_ticks = $ticks au début de votre code, et soustrayez la différence entre le nombre de ticks de départ et le nombre de ticks de fin de la valeur du délais :

.timerdot -ho 1
$calc((1000 /
%desiredFPS) - (
$ticks -
%star_ticks))
/main.loop

Il
n'y a aucun avantage à limiter le FPS, puisque vous apprendrez comment adapter la vitesse, peu importe le FPS, dans ce tutoriel. Mais c'est une bonne astuce à connaître si vous voulez limiter le FPS dans le but de faire un débogage.



4) Régler la vitesse des objets en mouvement

Maintenant, la partie la plus intéressante : le réglage de la vitesse.

Comme nous l'avons vu plus haut, nous ne devrions jamais fixer une valeur à Delta (cf. introduction). Au lieu de cela, vous devez calculer le temps écoulé depuis la dernière frame, puis, déterminer la nouvelle valeur de Delta basée sur ce temps.

Exemple : si votre animation tourne à 20 FPS, et que vous voulez qu'une balle se déplace à gauche à 100 pixels/seconde, vous devriez augmenter les coordonnées de x (de la balle) de 5 pixels à chaque frame (5 * 20 = 100).

Mais, soundainement, un logiciel occupe 80% de mémoire vive, et le FPS tombe à 10. La balle devrait donc se déplacer de 10 pixels à chaque frame pour maintenir la vitesse de 100 pixels/seconde.

Seulement, le FPS n'est déterminé qu'une fois toutes les secondes... et une seconde, c'est beaucoup trop ! Cela mènera donc à la désinchronisation de la vitesse.

Vous devez donc ajuster la vitesse de Delta par rapport aux objets à chaque fois que vous dessinez une frame !

Comment ?

Bien, nous avons tout d'abord besoin de calculer le temps écoulé depuis la dernière frame.

Stockez le nombre de ticks à la fin de l'alias 'boucle'.

%old_ticks =
$ticks

Puis,
lors du prochain appel, nous ferons un simple calcul qui retournera le nombre de millisecondes entre le nombre de ticks stocké et le nombre de ticks actuel.
Maintenant, vous devez calculer la vitesse de Delta. Nous utiliserons un entier. Mais le résultat de ce calcul sera une valeur à virgule flottante. Donc, gardez en tête que vous devez stocker la partie décimale quelque part afin de l'utiliser dans la prochaine frame. En effet, imaginez que le Delta calculé soit de 10.9, si nous ne retenons que la partie entière (ici 10), nous perdrons 0.9 de Delta. Après 500 frames, l'erreur sera de 500 * 0.9 450 (en admettant que le Delta soit toujours le même) !! Donc, nous additionnerons 0.9 à la prochaine valeur de Delta : 10.9 + 0.9 11.8, puis nous stockons la partie décimale (0.8) et nous ajoutons 11 pixels aux coordonnées de x de la balle, etc...

Pour obtenir la valeur de Delta, utilisez cette méthode :

%new_delta =
$calc(
%speed / 1000 *
%loop.time)

Le
nouvelle valeur de Delta est la vitesse en pixel/seconde divisée par 1000, le tout multiplié par le temps écoulé depuis la dernière frame (qui pourrait, éventuellement, avoir été retardée par le timer, donc ce n'est pas le temps d'éxécution de l'alias, mais bien le temps depuis la dernière frame).

Dans la prochaine frame, ajoutez %new_delta aux coordonées de x de la balle. Et voilà, la balle devrait toujours se déplacer à la vitesse désirée, peu importe le FPS.

Code :

; Temps écoulé depuis la dernière frame dessinée

var
%loop_time =
$ticks -
%old_ticks

; Nouveau Delta, basé sur le temps et la vitesse de 200 pixels/seconde + la partie décimal du Delta précédent

var
%new_delta_tmp =
$round(
$calc(200 /1000 *
%loop_time),2) +
%old_delta_decimal_part

; Le nouveau Delta est la partie entière de la valeur

%new_delta =
$int(
%new_delta_tmp)

; On stocke la partie décimale pour un usage ultérieur (dans la prochaine frame où l'on calculera Delta). On a donc : (valeur décimale - valeur entière). Ex : 10.9 - 10 = 0.9

%old_delta_decimal_part =
$calc(
%new_delta_tmp - %new_delta)

; Maintenant, on stocke le nombre de ticks actuel pour la prochaine frame où l'on calculera Delta

%old_ticks =
$ticks

; Puis nous éxécutons le timer pour revenir au début de la boucle...

.timerloop -ho 1 0
main.loop



5) Exemple de démonstration

Jetez un ?il sur la démo "
Moving Dot
" qui complètera ce tutoriel. Elle est entièrement documentée.


6) Conclusion

Note de l'auteur :

"
Je sais que cela peut être un peu dur à comprendre. Si vous n'y parvenez pas, lisez ce tutoriel encore et encore car c'est la meilleure méthode pour être sûr que votre animation (ou votre jeu) tournera à la même vitesse, que ce soit sur un PentiumII 266Mhz que sur un Pentium 4 3 Ghz. C'est indéniablement l'une des choses les plus importantes dans les jeux multi-joueurs.
Cette méthode peut être (ou plutôt devrait être) appliquée à tous les objets en mouvemements.
"

Note du traducteur :

"Si vous trouvez des fautes d'orthographe et/ou pensez qu'un passage à mal été traduit, merci de m'en faire part. Si vous avez besoin d'une traduction du fichier d'aide du DLL game_tools.dll et/ou de l'exemple de démonstration, je vous la ferai sur demande. : * "



Original :
Epsilon

Traduction / Mise en forme par :
moo

Adresse d'origine

A voir également

Publié par tidds.
Ce document intitulé «  [mirc] animation et synchronisation du fps  » issu de CodeS-SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
[mirc scripting] gestion des erreurs particulière (à partir de mirc 6.14)
[mirc] les bases du picwin