Voilà, je voulais savoir si (et comment) on peut intégrer le rafraichissement vertical avec la gestion des timers...
Je m'explique, voici un exemple avec un algorithme:
// installation du timer //
// temps de jeu = variable qui mesure où en est le timer du jeu //
temps de jeu = 0 (on commence le jeu au temps zéro! 0 secondes 0 centièmes, etc...)
Tant que (pas de touche Esc) faire
{
si (temps de jeu) > 0 faire // je teste si le timer est positif
{
saisie des entrées (clavier, manette, etc...)
gestion des calculs variables/entrées
décrémenter temps de jeu de 1.
}
sinon afficher l'écran en fonction des variables. // le timer est négatif ou égal à 0.
}
Le soucis est à "sinon afficher l'écran en fonction des variables." ...
Le problème c'est que si je mets une fonction d'attente de synchronisation verticale dans les fonctions d'affichage il va me temporiser l'affichage et ne rien m'afficher pendant que le timer continue d'avancer!
Sauf que je vais avoir beaucoup de retard quand je vais ré-attaquer la première boucle et il va mettre longtemps avant de me ré-afficher une autre image! vous comprenez?
Je l'ai testé et c'est ce qui se passe!
Sans timer c'est beaucoup plus fluide...
Une solution
ps: en fait je programme sous c++ avec allegro (librairie graphique 2d)
Edit: Il fallait lire à la fin... "Sans Synchro Verticale c'est beaucoup plus fluide..." ![]()
je
au cas où quelqu'un saurait m'aider...
Je ne suis pas sur que ca soit tres utile en 2011 d'attendre la synchro verticale. On a plus d'ecran CRT, donc je ne suis pas sur que ca ait encore du sens. (Quelqu'un de plus experimente que moi en techno graphique?)
Les écrans LCD ont aussi un taux de rafraichissement et donc aussi un phénomène de tearing. La Vsync est donc bien utile.
Par contre je n'ai pas bien saisi le problème :s
moi j'ai un écran CRT!
(en j'en suis bien heureux)
pour l'explication du problème je ne peux pas être plus précis que ce que j'explique précédemment...
En gros, il y a une boucle qui attend que le timer arrive à zéro puis il affiche les données.
et il recommence l'opération...
si je mets une Vsync quand j'affiche les données je vais avoir du lag du fait de la boucle et du timer!
Une solution serait d'ecrire apres la synchro verticale et pas avant. Mais pourca il fau pouvoir prober la synchro verticale. Ca peut certainement se faire avec un thread separer ou peut etre que ta lib graphique sait faire ca.
prober c'est quoi?
ma librairie c'est allegro et pour l'attente de synchro verticale je crois qu'il n'y a que Vsync() comme instruction... (très simple)
Ce que j'entendais ar prober est:
"est ce que la vsync est passe depuis la derniere fois que j'ai demande?"
Personnellement j'utilise une librairie qui gère un peu ça pour moi, donc je ne sais pas tellement comment ça fonctionne sans, mais je ne vois toujours pas le soucis?
Tu prépares tes données et tu lances l'affichage, et l'affichage se fait lorsque le bon temps est atteint pour le Vsync, ensuite tu lances l'image suivante?
Ou alors ce qui t'embête est que ton programme est "bloqué" jusqu'au temps de Vsync? Dans ce cas multithread.
godrik
oui, avec une instruction comme ça je pourrai résoudre mon problème sûrement mais je suis pas sûr que cette instruction est présente avec allegro... ![]()
Mjonir
ben j'ai fais un essai avec et sans Vsync et avec franchement j'ai clairement le programme qui m'affiche rien pendant longtemps (genre 1 seconde ou 2 des fois puis l'image apparaît. par contre, il garde les déplacement en mémoire. c'est-à-dire si mon entrée clavier (par exemple) va à droite et reste appuyée alors même si il m'affiche l'image plus tard elle se sera déplacée pendant que l'on voyait rien!
tu vois ce que je veux dire?
infestor, et pourquoi pas afficher tout les 1/60 secondes et se foutre de la vsync ?
bordel mais c'est pas bête ce que tu dis puisque j'utilise un timer! ^^
par contre, si quelqu'un a un affichage 75 Hz et que je fais du 60 img/s ça va bien rendre ![]()
godrick -> Ben déjà ça ne prend pas en compte les taux de rafraichissement supérieurs, ce qui est bien dommage. Ensuite, d'expérience, c'est pas terrible... soit il faut faire du busy-waiting, soit il faut accepter un certain aléa sur le rafraichissement ce qui mène à une mauvaise impression de fluidité (les intervalles entre les rafraichissements sont différents à chaque coup, donc le mouvement n'est pas bien uniforme).
Une solution sympa à ce problème est de threader l'affichage par rapport à la simulation, simuler avec une frame d'avance et lors de l'affichage interpoler la position.
M'enfin au final, ça reste quand même bien plus moche que de tout simplement gérer les déplacements à la seconde je trouve, après avoir utilisé tout ce qui est mentionné au dessus, j'y suis retourné.
Infestor -> Si tu utilises cette technique, outre les problèmes que j'ai mentionné au dessus, ça n'aura pas trop de soucis par rapport à un taux de rafraichissement supérieur... ce sera juste dommage de ne pas en profiter pour gagner en fluidité.
Pour le soucis, je saisis toujours pas, mais c'est surtout que je ne comprends pas comment tu gères la vsync avec allegro que je ne connais pas. Ce serait plus clair je crois si tu postais un bout de code et éventuellement un exécutable qui montre ce que ça donne :x
bah je programme sous linux (plus simple) donc pour l’exécutable... ça va être compliqué! ^^
l'instruction vsync() attend juste que l'écran est passé la bande verticale pour continuer à exécuter des instructions d'affichage qui suivent. par contre, elle n'empêche pas le timer d'être exécuté.
Voici mon code:
volatile int game_time;
void game_timer(void) {
game_time++;
}
END_OF_FUNCTION(game_timer);
int main() {
BITMAP* sprite1, *buffer, *fond;
PALETTE ma_palette ;
double xx,yy;
allegro_init() ;
install_keyboard() ;
set_color_depth(16) ;
if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0) != 0) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Impossible d’initialiser le mode vidéo !\n%s\n", allegro_error);
return 1;
}
//set_color_depth(8) ;
install_int(game_timer, 1);
game_time = 0;
LOCK_FUNCTION(game_timer);
LOCK_VARIABLE(game_time);
fond = load_bitmap("bleu-vert.bmp", NULL) ;
sprite1 = load_bitmap("mario.bmp", NULL) ;
if(!sprite1) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Erreur ! Impossible de lire le fichier image !");
return 1;
}
buffer = create_bitmap(SCREEN_W, SCREEN_H) ;
set_palette(ma_palette);
xx = SCREEN_W/3;
yy = SCREEN_H/3;
while(!(key[KEY_ESC])) {
if(game_time>0) {
if(key[KEY_LEFT]) xx-=INCREMENT_X;
if(key[KEY_RIGHT]) xx+=INCREMENT_X;
if(key[KEY_UP]) yy-=INCREMENT_Y;
if(key[KEY_DOWN]) yy+=INCREMENT_Y;
if(xx > SCREEN_W) xx = 0;
if(xx < 0) xx = SCREEN_W;
if(yy > SCREEN_H) yy = 0;
if(yy < 0) yy = SCREEN_H;
--game_time; }
else {
vsync();
clear_bitmap(buffer) ;
blit(fond, buffer, 0, 0, -(int)(xx/2), 0, SCREEN_W, SCREEN_H) ;
draw_sprite(buffer, sprite1, (int)xx, (int)yy);
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H) ; }
}
destroy_bitmap(sprite1) ;
destroy_bitmap(buffer) ;
destroy_bitmap(fond) ;
return 0;
}
END_OF_MAIN();
Je ne pense pas que thread l'affichage soit une bonne solution: C'est relativement complique et le gain ne me parait pas clair.
Mais on peut utiliser un thread pour rendre l'appel a vsync asynchrone. Ce qui est probablement beaucoup plus simple et certainement suffisant pour les besoins d'OP.
http://www.allegro.cc/manual/4/api/graphics-modes/vsync
D'après la doc il ne faut pas utiliser vsync, c'est fait automatiquement. Ton problème de freeze vient peut être d'autre part ?
J'ai parcouru la doc de allegr et je n'ai pas trouve de fonction pour lui dire:
-je commence a dessinner
-j'ai fini de dessinner
C'est pas un peu bizarre ?