SDL : Geschiwindigkeitsverlust
-
Hallo, ich hab mir ein kleines Snake-Grundgerüst gebaut.
Dabei besteht die Schlange aus einzelnen Pixeln, deren Position in einem Array gespeichert ist.Bei 200 Pixeln läuft das ganze normal. Wenn ich die Länge der Schlange auf 1000 erhöhe, dann spielt sich das ganze Programm in einem Zeitlupentempo ab.
Komisch ist aber, dass das Spiel auch mit 1000 Pixeln flüssig läuft, wenn das Spielfenster Inaktiv ist. Sobald das Fenster wieder aktiv ist, spielt sich das ganze wieder in einem langsamen Tempo ab.Weiß jemand , an was es liegen könnte ?
Wer sich den Code anschauen will , hier :
#include <SDL.h> void DrawPixel(SDL_Surface *screen, int x, int y,Uint8 R, Uint8 G,Uint8 B); //Zeichnet ein Pixel SDL_Surface *screen; SDL_Event event; int i; const int SnakeLen = 1000; int snakeX=300,snakeY=300; //Die Position des erste Pixels der Schlange int xPlus=1,yPlus=0; //Die Richtung int snakex[SnakeLen+1]={0},snakey[SnakeLen+1]={0}; //Die restlichen Positionen der Pixel Uint8 *keys; //Speichert die gedrückte Taste bool done = false; //prüft, ob die hauptschleife weiterläuft int main(int argc, char *argv[]) { atexit(SDL_Quit); screen = SDL_SetVideoMode(800,600,32,SDL_HWSURFACE | SDL_DOUBLEBUF); while(!done) { while(SDL_PollEvent(&event)) //Prüfen, ob das Programm verlassen wird { switch(event.type) { case SDL_QUIT: done = true; break; } } SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,255,255,255)); //Bildschirm löschen snakeX+=xPlus; //Die Schlange bewegt sich in die aktuelle Richtung weiter snakeY+=yPlus; for (i=0;i<=SnakeLen;i++) { DrawPixel(screen,snakex[i],snakey[i],0,0,0); //Jedes Pixel zeichnen } for(i=SnakeLen;i>=0;i--) { snakex[i]=snakex[i-1]; //Jedes Pixel erhält die Position des Pixels vor ihm snakey[i]=snakey[i-1]; } snakex[0] = snakeX; //Die Hauptkoordinaten snakey[0] = snakeY; keys = SDL_GetKeyState(NULL); //Tasten Prüfen if(keys[SDLK_UP]) { xPlus = 0; yPlus = -1; } if(keys[SDLK_DOWN]) { xPlus= 0; yPlus= 1; } if(keys[SDLK_RIGHT]) { xPlus= 1; yPlus= 0; } if(keys[SDLK_LEFT]) { xPlus=-1; yPlus =0; } SDL_Flip(screen); } return 0; } void DrawPixel(SDL_Surface *screen, int x, int y,Uint8 R, Uint8 G,Uint8 B) { Uint32 color = SDL_MapRGB(screen->format, R, G, B); if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) { return; } } switch (screen->format->BytesPerPixel) { case 1: { /* vermutlich 8 Bit */ Uint8 *bufp; bufp = (Uint8 *)screen->pixels + y*screen->pitch + x; *bufp = color; } break; case 2: { /* vermutlich 15 Bit oder 16 Bit */ Uint16 *bufp; bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x; *bufp = color; } break; case 3: { /* langsamer 24-Bit-Modus, selten verwendet */ Uint8 *bufp; bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3; if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { bufp[0] = color; bufp[1] = color >> 8; bufp[2] = color >> 16; } else { bufp[2] = color; bufp[1] = color >> 8; bufp[0] = color >> 16; } } break; case 4: { /* vermutlich 32 Bit */ Uint32 *bufp; bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x; *bufp = color; } break; } if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } SDL_UpdateRect(screen, x, y, 1, 1); }
-
Heutzutage ist Videospeicher nicht dafür gemacht, um darin einzelne Pixel zu setzen.
Bye, TGGC (NP Intelligenz)
-
Ist es dann besser wenn ich ein 1*1 großes Bild lade und es zeichne ?
-
In deinem Programm werden für jeden einzelnen Pixel dir Lock/Unlock Methoden in der DrawPixel-Funktion aufgerufen.
Wie wärs, wenn du die SDL_Lock(...) und SDL_Unlock(...)- Aufrufe aus der Funktion DrawPixel(...) nimmst und um die for-Schleife mit dem DrawPixel-Aufruf setzt:
if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) return; } for (i=0;i<=SnakeLen;i++) DrawPixel(screen,snakex[i],snakey[i],0,0,0); //Jedes Pixel zeichnen if ( SDL_MUSTLOCK(screen) ) SDL_UnlockSurface(screen);
Und wozu brauchst du
SDL_UpdateRect(screen, x, y, 1, 1);
, wenn du doch Doublebuffering verwendest?
Mal hoffen, dass nun dein Programm schneller läuft.
-
Na dann
Danke
Die funktion habe ich aus einem Beispiel kopiert, ohne sie näher anzuschauen.
-
Falls du HW Support hast wäre eine dritte Idee nur die Eckpunkte zu speichern und dann mit einem Linestrip zu zeichnen.
Bye, TGGC (Denken, und gut ist.)
-
Diese PutPixel-Funktion aus der SDL-Doku war vermutlich auch eher nur als Beispiel gedacht... Da du dich bei SDL_SetVideoMode eh auf 32Bit festlegst, ist der case-Block recht überflüssig.
(achso, mehr Performance würde die fehlende Abfrage aber auch nicht wirklich bringen)