Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1286 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [C++] Reglage du fps pour un jeu 2D

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C++] Reglage du fps pour un jeu 2D

n°1552227
Fred051
Posté le 02-05-2007 à 12:21:33  profilanswer
 

Bonjour les gens
 
Dans le cadre d'un projet à la fac, je dois réaliser un petit jeu en 2D en utilisant la classe Sprites de DirectX 9.
C'est un jeu façon space invaders, avec un vaisseau en bas de l'écran et des méchants à dégommer en haut.
J'ai un petit problème au niveau de la vitesse du jeu, sur ma machine : Athlon 64 3000+, 1.5Go de ram et Radeon 9800 256mo, j'obtiens un FPS qui tourne autour des 500fps. Sur un portable AMD Turion 64, Go de ram, et carte graphique 6150 128mo, le FPS passe à 50fps environ.
 
Le problème c'est que cela ralentit totalement le jeu, et notamment la vitesse du tir, qui va à 2 à l'heure.
 
Dans mon render(), fonction qui tourne en boucle, j'ai écrit :
 

Code :
  1. timeNow=timeGetTime();
  2. if(!ready){
  3.   if(timeNow-Tir.lastUpdate>1){
  4.    if(Tir.done)
  5.     TirP.pos.y-=3.45;
  6.    compteur_tir--;
  7.    if(compteur_tir==0){
  8.     Tir.done=false;
  9.     ready=true;
  10.    }
  11.   Tir.lastUpdate=timeGetTime();
  12.   }
  13.  }


 
Donc en gros :
si le tir n'est pas déjà en cours (if !ready), je teste  
le temps écoulé entre la dernière mise a jour du tir et maintenant. Si c'est supérieur à 1, l'ordonnée du tir augmente de 3.45. De même, le compteur diminue, ce compteur a été initialisé à 200. Quand ce compteur arrive à zéro, on peut retirer : le Tir est à faux, et le ready repasse à vrai. Le ready est utilisé dans la fonction qui récupère les touches appuyées sur la manette, si ready est à faux elle ne prend pas en compte la pression.
Et à la fin on remet à jour le Tir.lastUpdate().
 
Pour régler ce problème de vitesse, j'avais pensé à augmenter la valeur dans "TirP.pos.y-=3.45;", avec une valeur proportionnelle au fps. J'ai créé une variable vitesse_tir, qui vaudrait donc  
 

Code :
  1. vitesse_tir=(3.45*500)/fps;


 
500 étant la valeur de référence du FPS sur mon PC fixe, et fps étant la valeur du fps récupérée toutes les secondes, donc mise à jour constamment.
 
Mais cela ne fonctionne pas, cela va toujours au ralenti sur le portable... Si quelqu'un a une idée sur ce problème, ce m'aiderait bien, merci  :).


Message édité par Fred051 le 02-05-2007 à 12:23:39
mood
Publicité
Posté le 02-05-2007 à 12:21:33  profilanswer
 

n°1552233
MagicBuzz
Posté le 02-05-2007 à 12:31:39  profilanswer
 

Question : as-tu multi-threadé ton application ?
 
De façon classique, on trouve 3 threads dans un jeu :
- 1 thread pour l'interface clavier/souris et autres DirectInput
- 1 thread pour l'IA et autres traîtements (déplacements des balles, rendu des impacts, déplacement des vilains méchants pas bô, etc.)
- 1 thread pour le rendu
 
La premier thread a une priorité haute, et ne fait quasi rien : il a donc systématiquement une réactivité totale
Le second thread, qui est plus important que le rendu, tourne à vitesse fixe (timer par exemple) et une piorité moyenne (plus élevée que celle du rendu) afin d'avoir une régulatiré totale dans les mouvements et autres éléments (il peut lui-même lancer des threads fils plus longs, tels que des recherches de path AI et autres par exemple qui ne peuvent être effectuées en une seule passe sans bloquer le jeu).
Le troisième, enfin, à une prioriré faible, et tourne en boucle sans la moindre pause : "while (true) {redner();}". Il va s'occuper de faire le rendu de la scène qui a été modifiée par le tread des traîtements.
 
Ainsi, si le PC est "trop rapide", tu vas avoir 5000 fps, mais un jeu qui tourne à vitesse constante.
Si le PC est trop lent, alors il sera très sacadé, et sera légèrement ralenti, mais toujours aussi jouable car réactif aux actions de l'utilisateur.

n°1552240
Fred051
Posté le 02-05-2007 à 12:39:44  profilanswer
 

Mon code est composé d'une fonction qui gère les entrées sorties : ReadInput(), d'une fonction qui gère tous les timers, toutes les positions de chaque sprite : UpdateWorld(), et enfin d'un render().
 
Dans le winmain(), je lance ces fonctions de cette manière :
 

Code :
  1. while( msg.message!=WM_QUIT ) {
  2.  if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) {
  3.   TranslateMessage( &msg );
  4.             DispatchMessage( &msg );
  5.  } else {
  6.   UpdateWorld(hWnd);
  7.   ReadInput();
  8.   Render();
  9.  }
  10. }


 
Je me demande si le fait d'écrire "if(timeNow-Tir.lastUpdate>1)" change quelque chose au problème en fait, normalement ça voudrait dire que les calculs se font à temps constant peu importe la vitesse de la machine, mais pourtant cela ne fonctionne pas.
 
Sinon ce que tu dis concernant les PC plus rapides est vrai : sur un pc récent, mon jeu tourne à 1200fps, et pratiquement aucune différence avec pc.


Message édité par Fred051 le 02-05-2007 à 12:59:23
n°1552284
MagicBuzz
Posté le 02-05-2007 à 13:45:39  profilanswer
 

Moi je ferais des threads.
 
Car si tu ne fais pas de thread, tu es bien d'accord que si (timeNow - Tir.lastUpdate >> 1) (genre 2 ou 3) ton application ne tourne plus à vitesse constante, ce qui t'oblige à prendre en compte la vitesse dans tes traîtements.
De plus, si ça se met à rammer (genre 10 ou 100) ça fait un readinput qui n'est lancé que très peu souvent. Ainsi, l'utilisateur doit appuyer "2 heures" sur une touche pour qu'elle soit prise en compte... Et vu que ton UpdateWorld() est avant le ReadInput, les modifs liées à l'appui de cette touche ne seront faites qu'à l'affichage suivant. Donc s'il se passe deux secondes pour chaque itération, alors le joueur appuie 4 secondes, puis voir enfin une action, et à la 6° seconde, alors qu'il a lâché la touche, il son action est à nouveau effectuée.

n°1552543
Fred051
Posté le 02-05-2007 à 18:24:36  profilanswer
 

Je vais voir ce que je peux faire avec des threads alors, merci.

n°1555584
ptitchep
Posté le 04-05-2007 à 22:35:15  profilanswer
 

Faire des threads...
Faut jouer avec les sémaphores alors?
Que se passe-t-il si le thread des calculs supprime quelque chose en cours d'affichage?


---------------
deluser --remove-home ptitchep
n°1555605
MagicBuzz
Posté le 05-05-2007 à 01:02:09  profilanswer
 

évidement, qui dit thread, dit toute la panoplie des instructions qui vont bien pour que le code soit safe.
 
si le thread de calcul supprime un élément en cours d'affichage, évidement, ça se passe très mal...

n°1555652
ptitchep
Posté le 05-05-2007 à 12:03:07  profilanswer
 

Dans ce cas, est-ce bien utile?
Puisque les calculs se résument le plus souvent à faire avancer les acteurs et les objets (balles, bonus) en vérifiant qu'ils existent toujours, le thread d'affichage ne risque pas d'être bloqué pendant toute la durée des calculs ou presque?
Inversement, les calculs ne risquent pas d'être obligés de s'endormir à chaque suppression d'un élément du jeu le temps que l'affichage se termine? Que les calculs attendent la fin de l'affichage pourrait être catastrophique niveau gameplay et fps non?
Comment faut-il organiser tout cela?


Message édité par ptitchep le 05-05-2007 à 12:05:14

---------------
deluser --remove-home ptitchep
n°1555703
tbp
Posté le 05-05-2007 à 14:31:24  profilanswer
 

La solution la plus simple est de tamponner. Disons qu'on se cantonne au trivial double-buffer, avec 2 états alternés { s0, s1 }, | dénote une execution en //:
1) affichage de s0 | calcul de s1 à partir de s0
2) affichage de s1 | calcul de s0 à partir de s1
3) goto 1
 
Vu que l'état précédent est utilisé en lecture seule, nul besoin de synchroniser; celà se paie par un retard entre l'état le plus récent et celui affiché (retard qui augmente avec le nombre de buffers).
Par une généralisation de cette technique il est facile de permettre un découplage total entre calcul des états (physique etc) et affichage par interpolation.

n°1555739
red factio​n
Posté le 05-05-2007 à 16:46:13  profilanswer
 

ptitchep a écrit :

Faire des threads...
Faut jouer avec les sémaphores alors?
Que se passe-t-il si le thread des calculs supprime quelque chose en cours d'affichage?


j'ai eu exactement le meme probleme dans un jeu... enfait le thread "calcul" supprimait des particules en fin de vie , alors que lautre thread les envoyait a la cg....
 
et j'ai jamais trouver de solutions adequate....

mood
Publicité
Posté le 05-05-2007 à 16:46:13  profilanswer
 

n°1555766
tbp
Posté le 05-05-2007 à 17:37:55  profilanswer
 

Encore une fois n'avoir qu'un seul état et tenter de garantir sa cohérence tout du long est futile. Non seulement l'approche avec un historique/tamponage des états est plus simple, mais dans le cas courant ou l'affichage se fait à une fréquence bien plus élevée que la mise à jour cela permet naturellement d'interpoler.

n°1555785
ptitchep
Posté le 05-05-2007 à 18:25:23  profilanswer
 

tbp a écrit :

La solution la plus simple est de tamponner. Disons qu'on se cantonne au trivial double-buffer, avec 2 états alternés { s0, s1 }


effectivement ça m'a l'air d'être une bonne solution.
Par contre en pratique ça donne quoi?
Par exemple si chaque objet possède une méthode afficher(), qui est appelée par le thread d'affichage, il faut alors copier chaque objet pour tamponner?
 
 

tbp a écrit :

dans le cas courant ou l'affichage se fait à une fréquence bien plus élevée que la mise à jour cela permet naturellement d'interpoler.


Chez moi les calculs sont nettement plus rapides que l'affichage (3D OpenGL)...


---------------
deluser --remove-home ptitchep
n°1555858
bjone
Insert booze to continue
Posté le 05-05-2007 à 20:59:45  profilanswer
 

absolument pas besoin de threader pour un jeu.
 
a chaque frame tu mesures le temps écoulé et actualise l'état de tes objets en fonction de ce temps écoulé.
 
si tu veux être multi-tâche friendly (dans le sens pas 100% du cpu utilisé par un shoot'em up 2D), tu mets un timer par message à 40hz, et tu fais ta passe entrée utilisateur>actualisation monde>rendu a chaque évenement de timer.  
 
toujours en ayant mesuré le temps entre chaque frame, car un timer orienté message est toujours instable dû à l'ensemble de la charge de la machine (quelque soit l'os les messages peuvent arriver de manière irrégulière, en paquets de 4000, etc...).  
 
il n'a que sur les amiga/atari st/etc, ou tu as un framerate stable et reproductible, qui permet de mettre des "pas temporels" par frame.


Message édité par bjone le 05-05-2007 à 21:08:10
n°1555914
tbp
Posté le 06-05-2007 à 04:24:34  profilanswer
 

ptitchep a écrit :

effectivement ça m'a l'air d'être une bonne solution.
Par contre en pratique ça donne quoi?
Par exemple si chaque objet possède une méthode afficher(), qui est appelée par le thread d'affichage, il faut alors copier chaque objet pour tamponner?


Effectivement qque part il y a le fait qu'une forme de copie permet de s'abstenir de synchroniser. Mais si on reprend mon exemple, il n'y a à aucun moment de copie explicite juste une bascule entre 2 (ou n) états.
 
Dans votre cas (affichage plus lent que les calculs), il vaut mieux limiter le retard au maximum et donc se contenter d'un double-bufffer.
 
Ce genre de construction est d'autant plus facile à mettre en place que les propriétés de vos entités sont clairement distinctes (physique, rendu, audio etc...).

n°1556258
ptitchep
Posté le 07-05-2007 à 00:13:23  profilanswer
 

J'ai trouvé une solution sans thread qui a l'air de bien fonctionner chez moi:
Je fais toujours un minimum fixé de calcul par seconde et j'affiche chaque fois que j'ai le temps.
Si les temps sont faibles, il y en aura plus, sinon, l'affichage est sacrifié.
La variable nbIterations est globale (la seule du programme) car tout le jeu est fait en fonction d'elle. Par exemple quand un objet avance, il avance de  
vitesse/nbIterations
et donc en une seconde, il a avancé de vitesse (qui est exprimée en quelquechose/sec).
 
 

Code :
  1. Uint32  fps=SDL_GetTicks();
  2.   Uint32 fin(fps);
  3.   Uint32 MAJmili;
  4.   Uint32 compteur(0);
  5.   Uint32 decompte(fps);
  6.  
  7.   unsigned int It=60; //nombre d'itérations minimum recherché
  8.   unsigned int nbEff=0; //nombre d'iterations effectuées
  9.   double tps=1000./It; //temps en ms maximum recherché pour une itération
  10.   unsigned int nbImages=0;
  11.   unsigned int nbImagesInc=0;
  12.   joueurs[0]->mettreMiniCarteAJour();
  13.   while(1)
  14.   {
  15.     //On vrifie les actions du joueur1:
  16.     joueurs[0]->verifierActions();
  17.    
  18.     //Chaque joueur fait un tour:
  19.     for_each(joueurs.begin(),joueurs.end(),mem_fun(&Joueur::unTour));
  20.    
  21.     //Si on a le temps, on affiche:
  22.     MAJmili=SDL_GetTicks()-fps;
  23.     nbEff++;
  24.     if(MAJmili<nbEff*tps)   //le temps des calculs est inférieur au temps max?
  25.     {
  26.       joueurs[0]->afficher();
  27.       nbImagesInc++;
  28.     }
  29.    
  30.     if(nbEff>=It)
  31.     {
  32.       nbEff=0;
  33.       nbImages=nbImagesInc;
  34.       nbImagesInc=0;
  35.       fps=SDL_GetTicks();
  36.       joueurs[0]->mettreMiniCarteAJour(); //On met la mini carte a jour ttes les sec.
  37.     }
  38.     //On compte les itrations par seconde:
  39.     fin=SDL_GetTicks();
  40.     if(fin>=decompte+1000)
  41.     {
  42.       unsigned int unit=0;
  43.       for(unsigned int i=0;i<joueurs.size();++i)
  44. unit+=joueurs[i]->getNbUnites();
  45.      
  46.      
  47.       cout<<compteur<<" itrations /sec, "<<nbImages<<" images affiches, "<<unit<<" unites au total."<<endl;
  48.       nbIterations=compteur;
  49.       if(nbIterations==0)
  50. nbIterations=1;
  51.       compteur=0;
  52.       decompte=fin;
  53.     }
  54.     else
  55.       ++compteur;


---------------
deluser --remove-home ptitchep
n°1556273
Fred051
Posté le 07-05-2007 à 02:20:13  profilanswer
 

J'ai trouvé moi aussi une solution, sans thread comme l'a dit bjone. La solution était toute bête : il fallait mesurer comme il l'a dit le temps écoulé entre le render courant et le précédent, et ensuite de multiplier cette valeur par la vitesse que l'on veut. Et cela nous donne la même vitesse sur une machine qui tourne à 500 fps et sur une autre qui tourne à 50 fps. :)

n°1556274
ptitchep
Posté le 07-05-2007 à 02:26:06  profilanswer
 

oui mais dans ce cas, si l'affichage commence a prendre plus de temps, l'affichage ET les calculs sont effectués moins souvent et les objets avancent par saccades. Cela peut provoquer des problèmes comme par exemple des balles qui traversent les ennemis parce qu'à cause des saccades, ils n'ont jamais été en contact (expérience vécue).


---------------
deluser --remove-home ptitchep
n°1556448
bjone
Insert booze to continue
Posté le 07-05-2007 à 12:31:58  profilanswer
 

c'est (à peu près) comme ça dans tous les jeux de la création.
 
c'est très récent que c'est (assez) résolu et y'a pas besoin de mise en thread, il faut juste lors de la passe de calculs physique & actualisation monde itérer avec un pas de temps fin et pas le temps passé pour la dernière frame (bon il est vrai qu'un petit thread pour les entrées peut aider, vu que directinput fait ça en buffered je crois)
 
au lieu de faire tes 26.32ms d'un coup pour un framerate instantané de 38fps, dans la passe physique/actu du monde tu fais 26 itérations de 1ms et une de 0.32ms).
 
ensuite pour les tests balistiques / objets, si tes balles n'entrent pas en contact avec un objet, c'est que tu les considèrent comme un point dans l'espace, et non une ligne/courbe qui part de la dernière position à la nouvelle position actualisée. (en fait théoriquement c'est plus ça qui fait que tu ne vas pas louper de collision plus que d'itérer finement, mais rapidement si t'essayes de modéliser la colision de deux objets 3D complexe avec cette approche ça va devenir imbitable, il faudra discrétiser finement le temps quand même)
 
mais bon ça c'est plus facile en 3D, en 2D avec des sprites c'est effectivement moins trivial "d'extruder" temporellement un sprite 2D pour tester toute sa trajectoire avec les sprites des objets du jeu. (donc je pense que ton problème est dans ce contexte :/)
 
on peut imaginer faire un bresenham (ou une interpolation classique en X ou Y) entre la dernière position et la nouvelle position du sprite d'une balle, et tester la collision sprite balle/objets. avec un petit tests des enveloppes entre les deux positions des bounding box pour dégrossir.
 
mais pour être cohérent il faudrait aussi faire la même chose pour les objets. (pour ne pas louper une balle qui passe entre deux positions d'un objet qui se déplace vite :/) et là faut faire évoluer tout le monde par rapport au temps, et retester tout le monde à chaque fois que y'en a un qui bouge d'un pixel :D
 
bref je pense que pour un jeu 2D c'est moins "stable et trivial" vis àvis d'un temps variable.
 
ndlr, les threads c'est bien, mais dans le contexte d'un jeu c'est plus pour des contraintes précises (rarement découpler le rendu de l'actualisation du monde j'aurai tendance à dire, bien qu'une archi client/serveur c'est ce qui se passe :D), mais par exemple décoder un MP3 de manière régulée sans couacs... etc..., profiter d'un deuxième core pour streamer des portions de terrain et construire la géométrire qui en résulte (genre oblivion/lomac/fs & autre), bon c'est vrai que pour la simulation physique on peut chercher a profiter d'un deuxième core, etc...
 
mais basiquement des jeux qu'ils soient 2D ou 3D ont tournés de manière parfaitement fonctionnelle sans OS multi-tâche (ou micro-noyau maison multi-tâche). (bon après ils pouvaient avoir de l'accès bas-niveau qui nécessitent des threads pour obtenir un comportement similaire sur nos OS sécurisés actuels)
 
enfin je dis c'est pas pour dire les threads c'est mal, mais c'est justifié au cas par cas.


Message édité par bjone le 07-05-2007 à 13:22:40
n°1557210
MagicBuzz
Posté le 09-05-2007 à 10:35:05  profilanswer
 

Le problème de gérer le projectile comme une courbe, c'est que si un élément touchable vient se positionner sur la trajectoire du projectile après son passage, mais avant la fin de la gestion du projectile, tu va gérer un impact qui n'en est pas un. De plus, pour peu que la trajectoire soir une parabole, tu vas rapidement te retouver avec des calculs complexes. Idem si les "cibles" ont des formes complexes : pour améliorer la rapidité, tu sera tenté de gérer des bounding box, ce qui va résulter dans le fait qu'une balle tirer entre les jambes d'un personnage va le toucher, alors qu'elle n'est pas censée le toucher.
 
Ceci dit, on retrouve ce genre de problèmes, que ce soit avec ou sans gestion de threads.
 
Par contre, un point important... Aujourd'hui, tous les CPU sont dual core, vour quad core pour les plus récents. Ne pas utiliser les threads, c'est se tirer une balle dans le pied, dans la mesure ou on ne va absolument pas tirer partie de l'architecture évoluée des nouveaux matériels : 4 threads en // sur un quad core tournent à la même vitesse qu'un seul thread sur un même processeur, ce qui résulte à un vitesse réduire de 75%.
Si tu as le jeu qui tourne, pendant que TS tourne, TS va bouffer 50% du temps processeur inutilement, alors que dans le cas d'un jeu basé sur des threads, chaque thread va utiliser la même puissance de calcul, et ainsi, dans le cas de 4 threads pour le jeu, on gagne 30% de puissance CPU pour le jeu (4x20% pour le jeu, + 1x20% pour TS).
 
Au contraire, tous les jeux de simulation / stratégie temps réel sont massivement multi-threadé. Et la plupart des jeux de type FPS le sont aussi du moment qu'ils utilisent une IA, même si elle est très basique. Le moindre calcul de path AI va prendre plusieurs dizièmes de secondes, ce qui représente un lag inacceptable sur un jeu si on sérialise les traîtements.
 
Ensuite, même sous MS-DOS on pouvait travailler en multi-thread hein. C'est le multi-process qui n'était pas vraiment supporté (et encore, il était supporté, sinon explique moi comment on pouvait charger des résidents - emm386.exe, himem.sys, etc.)
 
Actuellement, je ne fais que répéter ce qu'on trouve dans le framework XNA (donc massivement orienté développement de jeux performants pour console de jeu). Les processes de la couche DirectX sont eux-même multi-threadés, ce qui montre que l'utilisation intensive de threads séparés est vitale pour un jeu. Je ne parle pas du doublebuffer ou même du triplebuffer, qui sont désormais supportés en natif par la couche DX, et ne demande pas même la moindre ligne de code supplémentaire (enfin, si, juste une, celle qui permet de l'activer)


Message édité par MagicBuzz le 09-05-2007 à 10:49:35
n°1557223
MagicBuzz
Posté le 09-05-2007 à 10:49:10  profilanswer
 

(ceci dit, pour un shot'em up, je suis d'accord qu'une architecture multi-threadée peut être le marteau pilon pour ouvrir une cacahuète... m'enfin moi je dis que c'est pas plus mal de partir sur de bonnes bases)

n°1557675
bjone
Insert booze to continue
Posté le 09-05-2007 à 22:56:16  profilanswer
 

faut pas tout mélanger; j'ai pas dit de s'arrêter a une bbox, j'ai dit que tu peux te servir d'une bbox comme test hiéarchique pour dégrossir (après tu as toujours les tests au niveau pixels pour de la 2D/poly pour de la 3D).
 
ensuite pour les threads, non les jeux dos n'étaient pas threadés, l'os n'exposait pas de capacités de threads, et ma conaissance aucun jeu évolué (donc généralement avec un dos-extender) n'a implémenté son propre scheduler. (ou alors on a pas la même définition d'un thread)

n°1557691
red factio​n
Posté le 09-05-2007 à 23:55:46  profilanswer
 

non les jeux netait pas threadés sauf que:
 
avant de faire le rendu on reprogrammait l'interruption du timer , ce qui fait qu'une meme procedure est tjs appelee toute les 18.2 x par seconde (ou autre valeur , cest a configurer). Du coup peut importe le cpu , cette procedure sera apellee a intervales reguliers (bon c pas tout a fait un thread puisque le cpu arrete ce quil est entrain de faire pour s'occuper de la procedure ...,sauf que si on est sur une machine mono cpu ca sera aussi comme ca... )  
 
c le cas de duke3d:  
une partie s'occupe du rendu,
un autre (appelee avec le timer) gere les entrees clavier et mes a jour la position du personnage... (chose relativement aisee que nimporte quelle cpu peut faire tres rapidement), ca permet egalement de deplacer tout le monde a la meme vitesse et de faciliter le mode reseau (meme si celui de duke etait bien merdique...)


Message édité par red faction le 09-05-2007 à 23:57:26
n°1557694
bjone
Insert booze to continue
Posté le 10-05-2007 à 00:05:54  profilanswer
 

j'ai pas été voir le source de dn3d.
 
on est d'accord que les jeux dos mettaient leur propres routines timer et kb. (je sais j'ai encore mon code asm de routine timer 2000hz avec le call-back de l'ancienne int pour à 18.2hz, d'ailleurs j'ai eu des bugs drôle lors du codage à base de déclenchement de time-out et d'horloge en 2024 en sortie de l'exe :D)
 
mais ç'est plus le comportement d'un signal que d'un thread.
 
la routine timer mesurait le temps de la frame, et la routine kb gérait les entrées par interruption, mais l'intégration de l'entrée et du temps se faisait dans une boucle générale, sinon bonjour les soucis de cohérence.  
 
la caméra était certainement pas déplaçé dans la routine d'interruption, alors que l'interruption a peut-être interrompu une routine d'actualisation de la géométrie du monde.

n°1557698
bjone
Insert booze to continue
Posté le 10-05-2007 à 00:22:23  profilanswer
 

je viens de zieuter: effectivement, la vitesse linéaire et angulaire de la caméra sont vilainement actualisés à l'interruption timer (les vilains).
 
mais bon, comme je dis, c'est intégré et mis en cohérence dans une boucle générale (ndlr le monde est actualisé par le totalclock, donc temps entre deux frames).
(ndlr, y'a aucunes relation au réseau là par-contre)
 

Code :
  1. void __interrupt __far timerhandler()
  2. {
  3. totalclock++;
  4. keytimerstuff();
  5. outp(0x20,0x20);
  6. }
  7. void __interrupt __far keyhandler()
  8. {
  9. oldreadch = readch; readch = kinp(0x60);
  10. keytemp = kinp(0x61); koutp(0x61,keytemp|128); koutp(0x61,keytemp&127);
  11. koutp(0x20,0x20);
  12. if ((readch|1) == 0xe1) { extended = 128; return; }
  13. if (oldreadch != readch)
  14. {
  15.  if ((readch&128) == 0)
  16.  {
  17.   keytemp = readch+extended;
  18.   if (keystatus[keytemp] == 0)
  19.   {
  20.    keystatus[keytemp] = 1;
  21.    keyfifo[keyfifoend] = keytemp;
  22.    keyfifo[(keyfifoend+1)&(KEYFIFOSIZ-1)] = 1;
  23.    keyfifoend = ((keyfifoend+2)&(KEYFIFOSIZ-1));
  24.   }
  25.  }
  26.  else
  27.  {
  28.   keytemp = (readch&127)+extended;
  29.   keystatus[keytemp] = 0;
  30.   keyfifo[keyfifoend] = keytemp;
  31.   keyfifo[(keyfifoend+1)&(KEYFIFOSIZ-1)] = 0;
  32.   keyfifoend = ((keyfifoend+2)&(KEYFIFOSIZ-1));
  33.  }
  34. }
  35. extended = 0;
  36. }
  37. keytimerstuff()
  38. {
  39. if (keystatus[buildkeys[5]] == 0)
  40. {
  41.  if (keystatus[buildkeys[2]] > 0) angvel = max(angvel-16,-128);
  42.  if (keystatus[buildkeys[3]] > 0) angvel = min(angvel+16,127);
  43. }
  44. else
  45. {
  46.  if (keystatus[buildkeys[2]] > 0) svel = min(svel+8,127);
  47.  if (keystatus[buildkeys[3]] > 0) svel = max(svel-8,-128);
  48. }
  49. if (keystatus[buildkeys[0]] > 0) vel = min(vel+8,127);
  50. if (keystatus[buildkeys[1]] > 0) vel = max(vel-8,-128);
  51. if (keystatus[buildkeys[12]] > 0) svel = min(svel+8,127);
  52. if (keystatus[buildkeys[13]] > 0) svel = max(svel-8,-128);
  53. if (angvel < 0) angvel = min(angvel+12,0);
  54. if (angvel > 0) angvel = max(angvel-12,0);
  55. if (svel < 0) svel = min(svel+2,0);
  56. if (svel > 0) svel = max(svel-2,0);
  57. if (vel < 0) vel = min(vel+2,0);
  58. if (vel > 0) vel = max(vel-2,0);
  59. }


 
j'ai pas mis les inits.
d'ailleurs l'init du timer n'est pas la méthode que j'employais, il va falloir que je ressortes ma bible et que je la dépoussière (sans paumer des pages qui tombent :D)


Message édité par bjone le 10-05-2007 à 00:56:30
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [C++] Reglage du fps pour un jeu 2D

 

Sujets relatifs
[C#] [Résolu] Comment communiquer avec une dll c++[C] Des accolades "just pour le fun" ?
la function mail dans PHP - réglage SMTP[VB?] réglage de la balance audio "wave"?
Mauvais réglage de l'heure lors de posts de news !Reglage terminal sous windows 2000
[delphi]Forcer la taille de sa police(reglage "Grande taille" chiant!)reglage date heure systeme en c++ sous dos
reglage date heure en c++ sous dosreglage date heure en c++ dos
Plus de sujets relatifs à : [C++] Reglage du fps pour un jeu 2D


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR