SDL Phantom Blitting

Started by
4 comments, last by Zanthos 20 years, 3 months ago
I''ve never had much luck with API''s, and SDL is my new venture.. And I''ve hit some problem I don''t seem to think I can solve. Basically, I have a program which works in either windowed or fullscreen mode, and displays a bitmap at the position of the cursor. I''ve disabled the cursor using SDL_ShowCursor(0), and am using: SDL_HWSURFACE|SDL_DOUBLEBUFFER as my primary surface flags. The problem.. Whilst the program is running, I get strange "phantom blits" which flick around on the screen in a seemingly random fashion whilst I move the mouse cursor. These "phantom blits" are also seemingly random chunks of the screen, both in size and position. I''ve completely ruled out any tearing due to buffer flipping, and anything due to the mouse cursor(whether visible or not). Additionally, this problem is apparent whether in fullscreen or windowed mode. I did, however, find a bodge to the problem, and that is to use SDL_Delay(10) after the SDL_Flip(screen) call, but I can''t live with myself to use that as a fix Any help would be much appreciated. Additionally.. My system configuration: Windows 2000 Professional SP 4 DirectX 9.0b SDL 1.2.6 P4 Non-HT @ 2.4Ghz Creative nVidia GeForce3 Ti200 64MB via Detonator XP 40.72 512MB DDR333 RAM
Advertisement
Your application is probably just flipping too fast, hence the SDL_Delay fix. As soon as you add a little more code to the application I firmly believe the flicking will dissapear.
-----------------------------Final Frontier Trader
I''ve read in several places that SDL locks to the refresh rate of my video adaptor, which is currently @ 75Hz(unless you can override it somehow). Unfortunately, I''ve just tried my test app again, which has the 10ms delay, and my kludgy fix has broken..
If you could post some of your code it would be easier to see what is going on. I have been using SDL for a while and haven''t had that problem yet. Oh, and is it happening in both full screen and windowed?

"If you are not willing to try, you will never succeed! If you never succeed, are you really trying?"

Grellin

"If you are not willing to try, you will never succeed!"GrellinC++ Game Programming
Here it is...

/*  lesson5.cpp  Cone3D GFX with SDL lesson 5.  Made by Marius Andra 2002  http://cone3d.gamedev.net  You can use the code for anything you like.  Even in a commercial project.  But please let me know where it ends up.  I''m just curious. That''s all.*/#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <time.h>#include "SDL.h"#include "font.h"// These two variables contain the dimensions of the playfieldint rows;int cols;SDL_Surface *screen;   // The screen surfaceSDL_Surface *balls[10];// The ball imagesSDLFont *font1;        // 2 fontsSDLFont *font2;char *playf;           // The playfield itself// The default width and height of the screenint scrwidth=640, scrheight=480;int centx=0,centy=0;   // Used to center the grid nicely onto the screenint bls=4;             // Number of differently colored ballsint bla=0;             // Used with the mouse...int score=0;           // The current score// This function draws a surface onto the screenvoid DrawIMG(SDL_Surface *img, int x, int y){  SDL_Rect dest;  dest.x = x;  dest.y = y;  SDL_BlitSurface(img, NULL, screen, &dest);}// This swaps two type char variablesvoid swap(char &r1, char &r2){  char temp=r1;  r1=r2;  r2=temp;}// Returns the color of a ball in the playfield.inline char &grid(int a, int b){  return playf[a*cols+b];}// This function makes balls fall down and rows move left.void collapse(){  // Make balls fall down  int to=-1;  for(int j=0;j<cols;j++)  {    to=-1;    for(int i=rows-1;i>=0;i--)    {      if(to==-1 && grid(i,j)==-1) {to=i;}      else if(to!=-1 && grid(i,j)!=-1) {swap(grid(i,j),grid(to,j)); to--;}    }  }    // Move rows to the left  to=-1;  {    for(int j=0;j<cols;j++)    {  	  if(to==-1 && grid(rows-1,j)==-1)      {        to=j;      } else if(to!=-1 && grid(rows-1,j)!=-1) {        for(int i=0;i<rows;i++)        {          grid(i,to) = grid(i,j);        }  	    to++;      }    }	    {      if(to!=-1)      {        for(int j=to;j<cols;j++)        {          for(int i=0;i<rows;i++)          {            grid(i,j)=-1;          }   	    }      }    }  }}// This is a recursive function that clears a bunch of balls.// It uses the flood fill algorithmint pick(int i, int j, int a){  int sum=1;  grid(i,j)=-1;  if(i != 0 && grid(i-1,j)==a) sum+=pick(i-1,j,a);  if(j != 0 && grid(i,j-1)==a) sum+=pick(i,j-1,a);  if(i<rows-1 && grid(i+1,j) == a) sum+=pick(i+1,j,a);  if(j<cols-1 && grid(i,j+1) == a) sum+=pick(i,j+1,a);  return sum;}// This function checks whether one ball is connected to an otherint bunch(int i,int j){  int a = grid(i,j);  if(i!=0 && grid(i-1,j) == a) return 1;  if(j!=0 && grid(i,j-1) == a) return 1;  if(i<rows-1 && grid(i+1,j) == a) return 1;  if(j<cols-1 && grid(i,j+1) == a) return 1;  return 0;}// Draw the screenvoid DrawScene(){  //SDL_ShowCursor(0);                    // Hide the mouse cursor  SDL_FillRect(screen,NULL,0x000000);   // Clear the entire screen with black  // Draw the balls  for(int i=0;i<rows;i++)  {    for(int j=0;j<cols;j++)    {      if(grid(i,j)!=-1) DrawIMG(balls[grid(i,j)],j*45+centx,i*45+centy);    }  }  // Draw some info and the score  drawString(screen,font1,1,scrheight-16,"SPACE restarts, gray + and - change the nr of balls (%d). Score: %d",bls,score);  // Draw the webspace url to the bottom-right of the screen  drawString(screen,font2,scrwidth-stringWidth(font2,"http://cone3d.gamedev.net"),                                        scrheight-16,"http://cone3d.gamedev.net");  SDL_Flip(screen);        // Flip the buffers  //SDL_ShowCursor(1);       // Show the cursor again}// This function resets the entire grid by adding random balls to itvoid newgame(){  // Reset the score  score=0;  // Fill the grid with random balls  for(int i=0;i<rows;i++)  {    for(int j=0;j<cols;j++)    {      grid(i,j) = rand()%bls;    }  }  // Redraw the screen  DrawScene();}// This is our main functionint main(int argc, char *argv[]){  srand(time(NULL));    // We initalize the random number generator  // Depending on the command line arguments given to this program,  // we change the screen resolution.  if(argc>1 && strcmp(argv[1],"640")==0) {scrwidth=640;scrheight=480;}  if(argc>1 && strcmp(argv[1],"800")==0) {scrwidth=800;scrheight=600;}  if(argc>1 && strcmp(argv[1],"1024")==0) {scrwidth=1024;scrheight=768;}  if(argc>1 && strcmp(argv[1],"1152")==0) {scrwidth=1152;scrheight=864;}  if(argc>1 && strcmp(argv[1],"1280")==0) {scrwidth=1280;scrheight=960;}  if(argc>1 && strcmp(argv[1],"1600")==0) {scrwidth=1600;scrheight=1200;}  // Initalize SDL  if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 )  {    printf("Unable to init SDL: %s\n", SDL_GetError());    exit(1);  }  atexit(SDL_Quit);  // We load in a random ball image as the icon for this program  char tempstring[100];  sprintf(tempstring,"data/balls/%d.bmp",rand()%9+1);  SDL_WM_SetIcon(SDL_LoadBMP(tempstring),NULL);  // Initalize the video mode  screen=SDL_SetVideoMode(scrwidth,scrheight,32,SDL_HWSURFACE|SDL_HWPALETTE);  if ( screen == NULL )  {    printf("Unable to set %dx%d video: %s\n", scrwidth, scrheight, SDL_GetError());    exit(1);  }  // Load in the fonts  font1 = initFont("data/font1");  font2 = initFont("data/font2",1,1,0);  // Load in all the balls  for(int a=1;a<10;a++)  {    char temp[100];    sprintf(temp,"data/balls/%d.bmp",a);    balls[a-1]=SDL_LoadBMP(temp);  }  // Calculate how much balls fit on the screen with the current  // screen resolution  rows=(scrheight-16)/45;  cols=(scrwidth)/45;  // Calculate how much must the balls be movedso that they would be centered.  centx = (scrwidth-cols*45)/2;  centy = (scrheight-16-rows*45)/2;  // Allocate space for the playfield  playf = new char[rows*cols];  // Reset the score and generate the playfield  newgame();  // Loop a bit  int done=0;  while(done == 0)  {    DrawScene();    SDL_Delay(30);    SDL_Event event;    while ( SDL_PollEvent(&event) )    {      // If someone closes the prorgam, then quit      if ( event.type == SDL_QUIT )  {  done = 1;  }      if ( event.type == SDL_KEYDOWN )      {        // If someone presses ESC, then quit        if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }        // Space restarts the game        if ( event.key.keysym.sym == SDLK_SPACE ) { newgame(); }        // The gray keypad + increases the nr. of different balls        if ( event.key.keysym.sym == SDLK_KP_PLUS ) { if(bls<9) {bls++;newgame();} }        // The gray keypad - decreases the nr. of different balls        if ( event.key.keysym.sym == SDLK_KP_MINUS ) { if(bls>3) {bls--;newgame(); } }      }    }    int x,y;     // Used to hold the mouse coordinates    int x2,y2;   // Used to hold the ball coordinates    float x3,y3; // Used to temporarily hold the ball coordinates    SDL_GetMouseState(&x, &y);    // Get the mouse coords    x3=(((float)(x-centx))/45);   // Get the ball coords    y3=(((float)(y-centy))/45);    if(x3<0 || y3<0) continue;    // If they are negative, restart the loop    else {x2=(int)x3;y2=(int)y3;} // else store them as ints    // If the mouse button is released, make bla equal 1    if(!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))    {      bla=1;    }    // If the mouse button was released the previous frame and is now    // held down, then ...    if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1) && bla==1)    {      // Make bla equal zero so that we could get here only if we release      // the mouse button and then click it again.      bla=0;      // Investigate the clicked ball      if(x2>=0 && y2>=0 && x2<cols && y2<rows && grid(y2,x2) != -1 && bunch(y2,x2))      {        // If it really is clickable then get rid of the balls        int a=pick(y2,x2,grid(y2,x2));        // Increase the score by the (removed balls-2)^2        score+=(a-2)*(a-2);        // Make the balls fall down        collapse();        // And update the screen              }    }  }  // Let''s clean up...  freeFont(font1);  freeFont(font2);  return 0;}


Ok its nicked from cone3d, but I made a modification of updating on every iteration of the event loop instead of just when the display gets updated. I know the initial method is more efficient, but I wanted to test something a bit more substantial than my single-bitmap-following-the-mouse-cursor demo.
Just a glance at the code, haven''t loaded it yet, but it looks like you are making the cursor flicker on purpose. In your posted code you have the SDL_ShowCursor functions commented out so you shouldn''t have a problem with the flicker. If they were uncommented it would make it flicker becuase it would act like a strobe light.

DrawScene()
turn off
flip
turn on
...repeat.

again, not sure if that is where the problem is but you should turn your cursor back on when you are cleaning up at shut down. I''ll run the code and see what I come up with.

"If you are not willing to try, you will never succeed!"

Grellin
"If you are not willing to try, you will never succeed!"GrellinC++ Game Programming

This topic is closed to new replies.

Advertisement