   SDL app staggering, tearing and choppy
  [edit: updated source to current implementation + sorted out layout issue]I've created a VERY simple SDL app which seems to be staggering, choppy and occasionally shows tearing. Why is this? I've created 2 games in SDL now, and they seem to have this problem. I was aiming with this simple app to solve my real game issues.Below is the sourcecode (excluding the timer class). You can find the full project folder (including release exe) at http://gravityapple.com/games/TestPerformance.rarI've used a fixed timestep which updates 60 FPS. Rendering is done outside this loop (as fast as possible).It still seems choppy, and the simple animation doesnt move as smooth as i'd like.Other things ive tried:Using png instead of bmpSWSURFACE instead of HWSURFACEIs there an obvious flaw in my design? Is this behaviour expected of SDL?Thanks for any design tips/helpAaron#include "SDL/SDL.h"#include "SDL_image.h"#include "Timer.h"#include <string>#include <iostream>#include <vector>static const int FPS = 60;static const int SKIP_TICKS = 1000 / FPS;static const int MAX_FRAMESKIP = 5;SDL_Surface* loadImage(const std::string& a_Filename);void applySurface(int x, int y, SDL_Surface* const a_Source, SDL_Surface* const a_Destination);int main(int argc, char *argv[]){SDL_Init(SDL_INIT_EVERYTHING);SDL_Surface* screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);bool running = true;SDL_Event event;std::vector<SDL_Surface*> stars;stars.push_back(loadImage("ball.bmp"));int x = 0;int y = 50;Timer FPSTimer;FPSTimer.start();double nextGameTick = FPSTimer.getTicks();int loops = 0;while(running){loops = 0;   while(SDL_PollEvent(&event))   {if(event.type == SDL_QUIT){running = false;}}    while(FPSTimer.getTicks() > nextGameTick && loops < MAX_FRAMESKIP) {x += 10;   if(x > 800){x = 0;}nextGameTick += SKIP_TICKS;  loops++;}SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0, 0, 0));for(std::vector<SDL_Surface*>::iterator it = stars.begin(); it != stars.end(); ++it){applySurface(x, y, *it, screen);} SDL_Flip(screen);}return 0;}SDL_Surface* loadImage(const std::string& a_Filename){SDL_Surface* loadedImage = NULL;SDL_Surface* optimizedImage = NULL;std::cout << a_Filename.c_str() << std::endl;loadedImage = IMG_Load(a_Filename.c_str());    if(loadedImage != NULL)    {   optimizedImage = SDL_DisplayFormat(loadedImage);   SDL_FreeSurface(loadedImage);    }    return optimizedImage;}void applySurface(int x, int y, SDL_Surface* const a_Source, SDL_Surface* const a_Destination){    SDL_Rect offset;    offset.x = x;    offset.y = y;SDL_BlitSurface(a_Source, NULL, a_Destination, &offset);} [Edited by - aaronjbaptiste on June 7, 2010 7:20:13 AM]
  Ah wrong category, I was meant to put this in Alternative Game Libraries   ;  Moved [smile]   ;  I'm no expert, but I think it has something to do with the fact that your logic and blitting code is in a nested while loop.Also, your white spacing does not follow convention, which makes your code somewhat difficult to read.   ;  Hi Aethix,Sorry about the formatting, I copied and pasted the code from VS and it must of not formatted correctly. I've made changes to the source now.Also about the nested while loop, I have tried putting the blitting both inside and outside. Ive updated the source to show the blitting outside (I usually do it like this anyway) but I still dont think performance is good enough.I have been trying to interpolate the position during rendering based on how far into the next frame the loop is but cant seem to get it to work. The ball just moves slower as the interpolation value is always very small.On another note, I have implemented the exact same code using SFML. It is much faster and has no tearing. However there are still some places where the ball seems to slow down a little as it fizzes past the screen, even though update FPS is 60-62 and rendering is over 200 FPS.;  Well, Aaron, I can't guarantee that I'll know what I'm talking about, but since nobody else has stepped in, I'll try.I think that 200 FPS can be problematic, as I don't think that most monitors can handle that high of a framerate. I'm still convinced that having an inner while loop for the game logic is a bad thing, but then again you may just be using a technique that's over my head. Try using this code instead, and see if it fixes the problem:#include "SDL/SDL.h"#include "SDL_image.h"#include "Timer.h"#include <string>#include <iostream>#include <vector>static const int FPS = 60;static const int SKIP_TICKS = 1000 / FPS;static const int MAX_FRAMESKIP = 5;SDL_Surface* loadImage(const std::string& a_Filename);void applySurface(int x, int y, SDL_Surface* const a_Source, SDL_Surface* const a_Destination);int main(int argc, char *argv[]){SDL_Init(SDL_INIT_EVERYTHING);SDL_Surface* screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);bool running = true;SDL_Event event;std::vector<SDL_Surface*> stars;stars.push_back(loadImage("ball.bmp"));int x = 0;int y = 50;Timer FPSTimer;FPSTimer.start();double nextGameTick = FPSTimer.getTicks();int loops = 0;while(running){   while(SDL_PollEvent(&event))   {if(event.type == SDL_QUIT){running = false;}}x += 10;   if(x > 800){x = 0;}SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0, 0, 0));for(std::vector<SDL_Surface*>::iterator it = stars.begin(); it != stars.end(); ++it){applySurface(x, y, *it, screen);} SDL_Flip(screen);  if(FPSTimer.getTicks() < SKIP_TICKS) {    SDL_Delay(SKIP_TICKS - FPSTimer.getTicks()); }}return 0;}SDL_Surface* loadImage(const std::string& a_Filename){SDL_Surface* loadedImage = NULL;SDL_Surface* optimizedImage = NULL;std::cout << a_Filename.c_str() << std::endl;loadedImage = IMG_Load(a_Filename.c_str());    if(loadedImage != NULL)    {   optimizedImage = SDL_DisplayFormat(loadedImage);   SDL_FreeSurface(loadedImage);    }    return optimizedImage;}void applySurface(int x, int y, SDL_Surface* const a_Source, SDL_Surface* const a_Destination){    SDL_Rect offset;    offset.x = x;    offset.y = y;SDL_BlitSurface(a_Source, NULL, a_Destination, &offset);}I haven't actually tested this code, so I hope I didn't introduce any syntax errors. The changes were so simple though, so it should work.   ;  I tried your code, however it never delayed (FPSTimer.getTicks() < SKIP_TICKS was always false), I had to add FPSTimer.start(); to the beginning. Its strange though, even though it was going very fast, it was quite smooth...while(running){FPSTimer.start();...}This indeed slowed it down to 60FPS. However it was quite similar to my game loop, a little jumpy.The technique I was originally using is from http://dev.koonsolo.com/7/dewitters-gameloop/. The inner while loop is simply there to catch up on skipped frames if its running behind (up to a maximum of MAX_FRAMESKIP frames).I decided to have another go at interpolating, as this was the final part of the article I hadn't managed to get working. After reading through it again I realised I was multiplying the interpolated value with the position, not the speed. After making the modifications and running again, all works fine. It runs/animates VERY smooth. There is some tearing in windowed mode, which I believe is due to SDL not being able to do vsync in windowed mode. Fullscreen there is no tearing.The "missing" part:...while(FPSTimer.getTicks() > nextGameTick && loops < MAX_FRAMESKIP) {x += 10;   if(x > 800){x = 0;} nextGameTick += SKIP_TICKS;  loops++;   }float interpolation = float(FPSTimer.getTicks() + SKIP_TICKS - nextGameTick) / float(SKIP_TICKS);for(std::vector<SDL_Surface*>::iterator it = stars.begin(); it != stars.end(); ++it){//position of current frame + (speed * how far into rendering next frame)applySurface(x+(10 * interpolation), y, *it, screen);}SDL_Flip(screen);...Thanks for your help, much appreciated.Aaron   