salut,
j'ai fait un pong en c windows, et je voudrais que la vitesse de jeu soit la meme pour chaque pc.
comment dois je faire?
salut,
j'ai fait un pong en c windows, et je voudrais que la vitesse de jeu soit la meme pour chaque pc.
comment dois je faire?
Ca va pas être simple ! Mis à part si tyous tes PC sont identiques, chaque ordi dépend de la vitesse de son processeur et de la qualité de sa carte graphique ! Donc, je ne pense pas que tu obtiennes des FPS égaux sur tous les PC même si le code est optimisé.
@ ++
Il faut que la vitesse de ton jeu ne depende pas de la vitesse d'affichage.
Il faut utiliser des outils de synchronisation, de delais, de gestion de temps...
Utilise des timers ou autres...
dans le traitement des messages windows,
lorsque le message WM_PAINT est recu,
j'appelle ma fonction d'affichage, ca n'est donc pas dépendant de la vitesse du jeu.
pour la vitesse du jeu, j'utilise des Sleep.
Salut,
vu que tu n' as pas donné trop de précision je sais pas trop si la methode conviendra mais dans mes jeux pour corriger le probleme de vitesse suivant la puissance des pc je calcule le temps ecoulé entre chaque frame affiché pour obtenir un coefficiant pour le deplacement de mes perso et objets
genre au lien de faire
tu fais
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2Perso.x += 1.0f;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Perso.x += 1.0f * deltaTime; //
ou deltaTime est l' intervalle de temps entre chaque frame ,
calculé avec une fonction du genre :
va faire un tour sur www.gametutorials.com et regarde dans les tutoriaux openGL pour timebased mouvement pour un exemple d' implémentation
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 float Get_Interval();
merci pour le lien,
j'ai regardé mais je n'ai pas très bien compris,
je vous donne mon code, si vous pouviez mieux m'expliquer en vous servant de lui:
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 #include <windows.h> #include <gl/gl.h> #include <gl/glu.h> #include <gl/glaux.h> #include <string.h> #include <math.h> WNDCLASS wc; MSG msg; HWND hWnd; HDC DC; HGLRC RC; int mv_barre_gauche,mv_barre_droite; int score_gauche,score_droite,mode;//mode: 1 joueur ou 2 ou le menu float pos_barre_gauche,pos_barre_droite; float balle_x,balle_y,vitesse,angle; BOOL pause,fin=false; unsigned texture[12]; AUX_RGBImageRec *texture1[12]; //pour les textures de scores double sx,sy; void InitVariable(){ pause=true; angle=3.14/4; vitesse=0.005; balle_x=0;balle_y=0; pos_barre_gauche=0;pos_barre_droite=-3; mode=0; mv_barre_gauche=0;mv_barre_droite=0;score_droite=0;score_gauche=0; }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 DWORD WINAPI Ia(LPVOID){//thread pour le mode 1 joueur(ordi) while(!fin){ if(pause==false){ Sleep(0.6); if(balle_y>(pos_barre_droite+1) && (cos(angle)<0))mv_barre_droite=2; else if(balle_y<(pos_barre_droite+0.5) && (cos(angle)<0))mv_barre_droite=1; else mv_barre_droite=0; } } fin=false; return true; }
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 void Traitement(){ if(mode==0){ } else { if(pause==false){ Sleep(0.5); vitesse+=0.0000001; //mouvement des barres switch (mv_barre_gauche){ case 0:break; case 1:if(pos_barre_gauche>-3.85) pos_barre_gauche = pos_barre_gauche - 0.01; break; case 2:if(pos_barre_gauche<1.15) pos_barre_gauche = pos_barre_gauche + 0.01; break; } switch (mv_barre_droite){ case 0:break; case 1:if(pos_barre_droite>-3.85) pos_barre_droite = pos_barre_droite - 0.006; break; case 2:if(pos_barre_droite<1.15) pos_barre_droite = pos_barre_droite + 0.006; break; } //calcul de la position de la balle balle_x+= vitesse * cos(angle); balle_y+= vitesse * sin(angle); //test du rebond sur les murs if(balle_y>=2.65 || balle_y<=-3.85) angle=-angle; //test points joueur gauche if(balle_x<=-4.9){ if(balle_y<(pos_barre_droite-0.15) || balle_y>(pos_barre_droite+1.65)){ score_gauche++; pause=true; balle_x=0;balle_y=0; vitesse=0.005; } else{ angle=-(angle+3.14); } } //test points joueurs droite if(balle_x>=4.9){ if(balle_y<(pos_barre_gauche-0.15) || balle_y>(pos_barre_gauche+1.65)){ score_droite++; pause=true; balle_x=0;balle_y=0; vitesse=0.005; } else{ angle=-(angle+3.14); } } } } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 void LoadTexture(char *path,int at) { texture1[at] = auxDIBImageLoad(path); glGenTextures (1, &texture[at]); } void SelectTexture(int s){ glBindTexture (GL_TEXTURE_2D, texture[s]); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, texture1[s]->sizeX, texture1[s]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1[s]->data); }
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 void RePaint () { glClear (GL_COLOR_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); //gluLookAt (0,0,-10,0,0,0,0,1,0); glEnable (GL_TEXTURE_2D); if(mode) { gluLookAt (0,0,-10,0,0,0,-1,1,1); //affichage des scores SelectTexture(score_gauche); glBegin(GL_QUADS); glColor3d(1,1,1); glTexCoord2i(1,0);glVertex2f(0.2,3.6); glTexCoord2i(1,1);glVertex2f(0.2,4); glTexCoord2i(0,1);glVertex2f(0.5,4); glTexCoord2i(0,0);glVertex2f(0.5,3.6); glEnd(); SelectTexture(10); glBegin(GL_QUADS); glColor3d(1,1,1); glTexCoord2i(1,0);glVertex2f(-0.2,3.6); glTexCoord2i(1,1);glVertex2f(-0.2,4); glTexCoord2i(0,1);glVertex2f(0.2,4); glTexCoord2i(0,0);glVertex2f(0.2,3.6); glEnd(); SelectTexture(score_droite); glBegin(GL_QUADS); glColor3d(1,1,1); glTexCoord2i(1,0);glVertex2f(-0.5,3.6); glTexCoord2i(1,1);glVertex2f(-0.5,4); glTexCoord2i(0,1);glVertex2f(-0.2,4); glTexCoord2i(0,0);glVertex2f(-0.2,3.6); glEnd(); //affichage des murs glDisable( GL_TEXTURE_2D ); glBegin (GL_QUADS); glColor3d (0,0,1); glVertex2f (5.3,3); glVertex2f (5.3,2.7); glVertex2f (-5.3,2.7); glVertex2f (-5.3,3); glEnd (); glBegin (GL_QUADS); glColor3d (0,0,1); glVertex2f (5.3,-4); glVertex2f (5.3,-3.9); glVertex2f (-5.3,-3.9); glVertex2f (-5.3,-4); glEnd (); //affichage des joueurs glBegin (GL_QUADS); glColor3d (1,1,1); glVertex2f (5,pos_barre_gauche); glVertex2f (5,pos_barre_gauche+1.5); glVertex2f (5.3,pos_barre_gauche+1.5); glVertex2f (5.3,pos_barre_gauche); glEnd (); glBegin (GL_QUADS); glColor3d (1,1,1); glVertex2f (-5,pos_barre_droite); glVertex2f (-5,pos_barre_droite+1.5); glVertex2f (-5.3,pos_barre_droite+1.5); glVertex2f (-5.3,pos_barre_droite); glEnd (); //affichage de la balle glBegin (GL_QUADS); glColor3d (1,0,0); glVertex2f (balle_x+0.1,balle_y-0.1); glVertex2f (balle_x+0.1,balle_y+0.1); glVertex2f (balle_x-0.1,balle_y+0.1); glVertex2f (balle_x-0.1,balle_y-0.1); glEnd (); } else { gluLookAt (0,0,-10,0,0,0,0,1,0); //affichage du menu SelectTexture(11); glBegin(GL_QUADS); glColor3d(1,1,1); glTexCoord2i(1,0);glVertex2f(-5.5,-4); glTexCoord2i(1,1);glVertex2f(-5.5,4); glTexCoord2i(0,1);glVertex2f(5.5,4); glTexCoord2i(0,0);glVertex2f(5.5,-4); glEnd(); } SwapBuffers (DC); }
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 void InitPixelFormat (HDC hDC) { PIXELFORMATDESCRIPTOR pfd = { sizeof (PIXELFORMATDESCRIPTOR), 1, PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; SetPixelFormat (hDC, ChoosePixelFormat (hDC, &pfd), &pfd); }
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 LRESULT CALLBACK WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_LBUTTONDOWN: sx=LOWORD(lParam); sy=HIWORD(lParam); if(mode==0) { if((sx>74 && sx<534) && (sy>320 && sy<406)) PostMessage(hWnd,WM_CLOSE,0,0); else if((sx>63 && sx<551) && (sy>186 && sy<267)) mode=2; else if((sx>55 && sx<562) && (sy>80 && sy<182)){ mode=1; if(CreateThread(NULL,NULL,Ia,NULL,NULL,NULL)==NULL){ mode=0; } } } break; case WM_KEYDOWN: switch(wParam) { //demande de fermeture du programme case VK_ESCAPE: if(mode==0)PostMessage(hWnd,WM_CLOSE,0,0); else { InitVariable(); fin=true; mode=0; } break; case 0xd: if(pause==true){ pause=false; if(score_gauche==9 || score_droite==9){ InitVariable(); fin=true; mode=0; } } else pause=true; break; case VK_UP: if(mode==2)mv_barre_droite=2; else if(mode==1)mv_barre_gauche=2; break; case VK_DOWN: if(mode==2)mv_barre_droite=1; else if(mode==1)mv_barre_gauche=1; break; case 0x5a: if(mode==2)mv_barre_gauche=2; break; case 0x53: if(mode==2)mv_barre_gauche=1; break; } break; case WM_KEYUP: switch(wParam) { case VK_UP: if(mode==2)mv_barre_droite=0; else if(mode==1)mv_barre_gauche=0; break; case VK_DOWN: if(mode==2)mv_barre_droite=0; else if(mode==1)mv_barre_gauche=0; break; case 0x5a: if(mode==2)mv_barre_gauche=0; break; case 0x53: if(mode==2)mv_barre_gauche=0; break; } break; case WM_CREATE: int i;char par[14],tot[2]; InitVariable(); DC=GetDC (hwnd); InitPixelFormat (DC); RC = wglCreateContext (DC); wglMakeCurrent (DC, RC); for(i=0;i<=9;i++){ strcpy(par,"");strcpy(tot,"");strcpy(par,"score\\"); itoa(i,tot,10);strcat(par,tot); strcat(par,".bmp"); LoadTexture(par,i); } LoadTexture("score\\tiret.bmp",10); LoadTexture("score\\menu.bmp",11); break; case WM_CLOSE: wglMakeCurrent (NULL, NULL); wglDeleteContext (RC); ReleaseDC (hwnd,DC); PostQuitMessage (0); break; case WM_SIZE: glViewport (0,0,LOWORD (lParam),HIWORD (lParam)); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (45,(float)(LOWORD(lParam))/(float)(HIWORD(lParam)),1,100); break; case WM_PAINT: RePaint (); break; default: return DefWindowProc (hwnd,uMsg,wParam,lParam); break; } return 0; }
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 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow) { wc.style = CS_OWNDC; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "OGL"; RegisterClass(&wc); hWnd = CreateWindow ("OGL", "pong", WS_POPUPWINDOW | WS_VISIBLE, 20, 20, 600, 450, NULL, NULL, hInstance, NULL ); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); Traitement(); } return 0; }
ba j' ai pas tout matté en detail mais des que tu deplace un objet multiplie par un coef deltatime
pour calculer le deltatime , regarde du coté des fonctions QueryPerformanceCounter ou timeGetTime (winmm.lib)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 balle_x+= deltatime * vitesse * cos(angle); balle_y+= deltatime * vitesse * sin(angle);
je crois que j'ai compris,
je calcul mes frames par secondes, et je fais un truc du genre:
c'est ca?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Sleep(frame/100);
et sinon, y a t-il un moyen de limiter directement le nombre de frames à 130 par exemple?
Salut,
je comprends pas trop pourquoi tu veux mettre des sleep a tout prix ...
tiens deja un lien pour comment faire un timer avec QueryPerformanceCounter :
http://nehe.gamedev.net/data/lessons....asp?lesson=21
Sinon plutot que de faire un Sleep() , pour bloquer ton frame rate avec l' API multimedia Win32
tu peux faire un truc genre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 bool LockFrameRate(int frame_rate) { static float lastTime = 0.0f; float currentTime = GetTickCount() * 0.001f; if((currentTime - lastTime) > (1.0f / frame_rate)) { lastTime = currentTime; return true; } return false; }
et dans ta boucle Win32 principale tu fais
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 while(1) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else if(LockFrameRate(60)) // exemple pour 60 fps { Draw_Scene(); // la fonction qui dessine ta scene }
Si je veux faire absolument des Sleep(), c'est pour cadencer la vitesse du jeu, chez moi avec 1000 frames par secondes, je faisait un Sleep(0.5);
Sans le Sleep(), autant dire que l'on ne peut plus suivre la balle des yeux.
oui ok , ca j' ai bien saisi ,
par contre je crois pas que t a lu ou compris les deux derniers bouts de code que je t ai donné sinon tu me dirais pas ca
bon je vais tenter d' expliquer differemment alors :
imagine un vieux pc qui te sort 1 frame par sec :
en 1 sec ton code fait une boucle affichage + deplacement des objets ....
donc si tu fais
ta balle avance de 1.0f par sec , ok ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3balle.x = balle.x + 1.0f;
sur le super PC a 200 fps en une seconde tu fais deux cents boucles
donc ta balle avance de 200.0f en 1 sec ... toujours ok ? 8)
c bien pour cela que tu dois calculer avec une variable deltatime tel que
ton deltaTime ( == l espace entre les frames == temps a la frame courante - temps à la derniere frame) sera alors 200 fois plus petit sur le super pc que sur le pc pourri !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 balle.x = balle.x + ( 1.0f * deltaTime );
Voila
Bon je coup ci je crois pas que je peux te l' expliquer mieux que ca , regarde les codes que j' ai posté , essaye de les comprendre, de les implementer et rergarde les liens que j' ai posté
A+
je crois que j'ai compris, les FPS correspondent aux nombres de boucles Principale effectuées en une seconde?
désolé de t'embêter à nouveau,
j'ai fait comme tu as dit, mais les déplacements sont saccadés, c'est normal? (je suis à 600 FPS)
en fait les FPS ca veux dire frame par second (image par seconde) et pour chaque image calculée le programme fais une boucle principale.
Merci,
beaucoup, désolé d'avoir mis du temps à repondre, mais j'ai très peu de temps libre depuis un moments.
Partager