Salut tout le monde !
Alors voila, je suis actuellement en train de développer le jeu de la vie en C/SDL. Pour ceux qui ne connaissent pas, il s'agit d'une génération cellulaire : Dans un tableau à deux dimensions(grille), en fonction de l'état d'une cellule (vide ou pleine (0/1)) on regarde le nombres de cases pleines autour de celle-ci et on la fait vivre(1), mourir(0) ou rester dans le même état. Exemple, si une cellule morte se retrouve entourée de plus de 3 cellules vivantes, elle vie aussi.
Voila pour l'explication, maintenant passons au problème:
Une fois que l'utilisateur à lancé la séquence de génération (évènement clavier) une boucle fait en sorte de générer toutes les X ms la séquence des fonctions combinées règles + affichage.
Le problème est que même quand on génère on doit quand même gérer les évènements, ex : l'utilisateur clic droit avec la souris et cela génère des cellules aux différents endroits ou la souris passe quand le clic est maintenu.
Mon problème est donc de trouver une solution pour d'une part exécuter les fonctions règles + affichage toutes les X ms et d'autre part permettre à l'utilisateur dans le même temps de de faire des actions de manière fluide.
J'ai déjà tenté deux ébauches de solution avec leurs points faible et fort qui ne m'ont pas satisfaites. Elles sont complètement fonctionnelles, la partie intéressante ici se situe uniquement au niveau de la gestion du temps.
Voici grossièrement comment se présente l'algo pour une première solution, le SDL_Delay(X):
Point fort : Permet de mettre le programme en pause, économie de CPU, et génère au bon moment.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 int X; bool continuer=true; bool continuerbis=false; while(continuer) //boucle principale { //je passe le passage initialisation SDL... et les traitements annexes //L'utilisateur presse G, la touche pour générer continuerbis=true; while(continuerbis) //boucle principale pendant la génération, c'est celle qui nous intéresse { while(SDL_PollEvent(&event)) { //traitement du clic de la souris //et des divers appuis clavier } SDL_delay(X); if(continuerbis) //permet de ne pas générer pour rien si l'user a cliqué sur quitter par exemple { regles(param1,param2,paramN); affichage(param1,param2,paramN); } } }
Point faible : Empêche la fluidité du traitement des évènements qui sont désormais dépendant de ce temps X.
Point très faible : Bloque complètement le programme pendant ces X ms empêchant l'utilisateur de quitter par exemple. Quand c'est 25ms ça gène pas, mais si l'utilisateur peut par exemple faire varier X (ms de pause) alors il se peut que le programme soit totalement indisponible pendant un temps pouvant dépasser les 1sec, ce qui rend la gestion des évènements inutile.
Solution n°2 :
Combinaison de la gestion du temps avec le SDL_PollEvent et SDL_GetTicks
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 int X,passedtime; bool continuer=true; bool continuerbis=false; while(continuer) //boucle principale { //je passe le passage initialisation SDL... et les traitements annexes //L'utilisateur presse G, la touche pour générer continuerbis=true; while(continuerbis) //boucle principale pendant la génération, c'est celle qui nous intéresse { passedtime=SDL_GetTicks; while(SDL_PollEvent(&event)||(SDL_GetTicks-passedtime<X) ) { //traitement du clic de la souris //et des divers appuis clavier } if(continuerbis) //permet de ne pas générer pour rien si l'user a cliqué sur quitter par exemple { regles(param1,param2,paramN); affichage(param1,param2,paramN); } } }
Point fort : Gestion ultra fluide des événements et génération en temps voulu.
Point faible : Consommation énorme en processeur car celui-ci va tourner dans la boucle while(SDL_PollEvent...) tant qu'on atteint pas les X ms. Alors c'est sure que dans ce cas, dès qu'il y a un évènement il peut pas le rater !!!
Je cherche donc un compromis afin de réaliser la règle que je vais exprimer si dessous :
Si il y a un évènement on le traite, mais si il n'y a rien on attend les X ms et on génère. Ces X ms ne doivent pas compromettre la gestion fluide des évènements.
Une autre solution qui m'a traversée l'esprit serait de mettre un SDL_WaitEvent et de déclencher un évènement toutes les X ms qui serait l'exécution des fonctions règle + affichage. Mais je ne sais pas si c'est possible:
Avantage : Faible utilisation du CPU, génération en temps voulu, suppression de la condition if ce qui allégerait le programme encore plus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 int X,passedtime; bool continuer=true; bool continuerbis=false; while(continuer) //boucle principale { //je passe le passage initialisation SDL... et les traitements annexes //L'utilisateur presse G, la touche pour générer continuerbis=true; while(continuerbis) //boucle principale pendant la génération, c'est celle qui nous intéresse { passedtime=SDL_GetTicks; SDL_WaitEvent(&event) { //traitement du clic de la souris //et des divers appuis clavier //Toutes les X ms créer son propre évènement chargé d'exécuter les fonctions suivantes. Du genre : if(SDL_GetTicks-passedtime>X) { //création de l'évènement SDL_PushEvent() ; //on le place dans la file directement regles(param1,param2,paramN); //fonctions à affichage(param1,param2,paramN); //executer } } } }
Inconvénient : C'est possible ça?
Voila, j'ai essayé d'être le plus clair possible ! Bien sûre ma dernière proposition n'est qu'une suggestion et je suis ouvert à toute autre proposition permettant de régler le problème !
Merci pour l'attention que vous m'avez porté en lisant ce message, à bientôt !
Partager