SDL: Custon gui crash, debugger no output

Started by
5 comments, last by skwee 16 years, 12 months ago
Hello, Yea its me again :) Ok i made a custom gui: 5 buttons; 2 increase/decrease angle, 2 increase/decrease power attack and one Shot/Fire. If i press them in random order, and pretty fast/ a lot of times(i mean like i pressed button A 10 time in 2 sec the switched to D pressed it X secs the switched to B and etc), after 30-40 maybe 60 seconds my program crashes. GDB gave no results, just said something like "the program return 0" don't remember, but no errors not backtrace, looks like the program exited normally. Here parts of the code: This part is the part that draws pressed and released buttons and changes values of angle and power (actually the one that cause the crash as i think :\)

 //Main Game Loop
 while(gameRunning)
 {
  
  /*-------Start Event Handle-------*/
  while(SDL_PollEvent(&event))
  {
   //Pressed X
   if(event.type == SDL_QUIT)
    gameRunning = false;
   
   //Pressed Escape 
   if(event.key.keysym.sym == SDLK_ESCAPE)
    gameRunning = false;
   
   //Or user pressed mouse button
   if(event.type == SDL_MOUSEBUTTONDOWN)
   {
    //if left button
    if(event.button.button == SDL_BUTTON_LEFT)
    {
     mX = event.button.x;
     mY = event.button.y;
     switch(menu_GetButtonPressed(mX, mY))
     {
      //Button decrease angle pressed
      case 1:
       menuState = 1;
       angle -= 1;
       if(angle <= 0)
        angle = 360;
       menu_DrawMenu(angle, power, menuPic, 1);
       redraw = 1;
       break;
       
      //Button increase angel pressed
      case 2:
       menuState = 2;
       angle += 1;
       if(angle > 360)
        angle = 1;
       menu_DrawMenu(angle, power, menuPic, 2);
       redraw = 1;
       break;
       
      //Button Fire pressed
      case 3:
       menuState = 3;
       menu_DrawMenu(angle, power, menuPic, 3);
       redraw = 1;
       break;
       
      //Button increase power pressed
      case 4:
       menuState = 4;
       power -= 1;
       if(power < 1)
        power = 1;
       menu_DrawMenu(angle, power, menuPic, 4);
       redraw = 1;
       break;
      
      //Button decrease power pressed 
      case 5:
       menuState = 5;
       power += 1;
       if(power > 100)
        power = 100;
       menu_DrawMenu(angle, power, menuPic, 5);
       redraw = 1;
       break;
     }
    }
   }

   //Or user released mouse button
   if(event.type == SDL_MOUSEBUTTONUP)
   {
    //if left button
    if(event.button.button == SDL_BUTTON_LEFT)
    {
     switch(menuState)
     {
      //Button decrease angle pressed
      case 1:
       menu_DrawMenu(angle, power, menuPic, -1);
       menuState = 0;
       redraw = 1;
       break;
       
      //Button increase angel pressed
      case 2:
       menu_DrawMenu(angle, power, menuPic, -2);
       menuState = 0;
       redraw = 1;
       break;
       
      //Button Fire pressed
      case 3:
       //Do Fire()
       menu_DrawMenu(angle, power, menuPic, -3);
       menuState = 0;
       redraw = 1;
       break;
       
      //Button decrease power pressed
      case 4:
       menu_DrawMenu(angle, power, menuPic, -4);
       menuState = 0;
       redraw = 1;
       break;
      
      //Button increase power pressed 
      case 5:
       menu_DrawMenu(angle, power, menuPic, -5);
       menuState = 0;
       redraw = 1;
       break;
     }
    }
   }
  }
  /*-------End Event Handle-------*/
  
  if((SDL_GetTicks() - timer) >= FRAME_RATE)
  {
   if(redraw == 1)
   {
    SDL_Flip(g_Screen);
    redraw = 0;
   }
   timer = SDL_GetTicks();
  }
  
  SDL_Delay(1);
 }

menu_GetButtonPressed(mX, mY) - return button that pressed Here is the function menu_DrawMenu(int, int, SDL_Surface, int);

/**
* menu_DrawMenu
*/
void menu_DrawMenu(int angle, int power, SDL_Surface *menuPic,
                   int buttonToUpdate)
{
 //text color
 SDL_Color textColor = {200, 0, 0};
 
 //text nad menu bg image
 SDL_Surface *text = NULL;
 
 //Button to update
 bool update1 = false;
 bool update2 = false;
 bool update3 = false;
 bool update4 = false;
 bool update5 = false;
 
 switch(buttonToUpdate)
 {
  case 1:
   update1 = true;
   break;
   
  case 2:
   update2 = true;
   break;
   
  case 3:
   update3 = true;
   break;
   
  case 4:
   update4 = true;
   break;
   
  case 5:
   update5 = true;
   break;
   
  case -1:
   update1 = false;
   break;
   
  case -2:
   update2 = false;
   break;
   
  case -3:
   update3 = false;
   break;
   
  case -4:
   update4 = false;
   break;
   
  case -5:
   update5 = false;
   break;
 }
 
 //font
 TTF_Font *font = NULL;
 
 char textToRender[24];
 
 rec_ClearScreen(g_Screen, SDL_MapRGB(g_Screen->format, 0, 0, 0), 0, 500,
                 WSCREEN, HSCREEN);
 
 rec_Blit(menuPic, g_Screen, 0, 500);
 
 font = TTF_OpenFont("data/fonts/lycida.ttf", 25);
 if(font == NULL)
 {
  fprintf(stderr, "Error: Unable to load data file: data/fonts/lycida.ttf\n");
  exit(1);
 }
 
 //Set bold font style
 //TTF_SetFontstyle(font, TTF_style_BOLD);
 
 //create text
 sprintf(textToRender, "Angle: %d", angle);
 text = TTF_RenderText_Blended(font, textToRender, textColor);
 
 //Draw Text
 rec_Blit(text, g_Screen, angleTextPosX, angleTextPosY);
 
 //unload
 SDL_FreeSurface(text);
 
 //create text
 sprintf(textToRender, "Power: %d", power);
 text = TTF_RenderText_Blended(font, textToRender, textColor);
 
 //Draw Text
 rec_Blit(text, g_Screen, powerTextPosX, powerTextPosY);
 
 //unload
 SDL_FreeSurface(text);
 
 //Draw Left/decreaser angle button
 gui_DrawButton(angleButtonPosX, angleButtonPosY, angleButtonH, angleButtonW,
                update1, "-", font);
 
 //Draw Right/Increaser power button
 gui_DrawButton(angleButtonPosX + angleButtonStep, angleButtonPosY, 
                angleButtonH, angleButtonW, update2, "+", font);
 
 //Draw 'Fire' button
 gui_DrawButton(fireButtonPosX, fireButtonPosY, fireButtonH, fireButtonW,
                update3, "Fire!", font);
                
 //Draw Left/decreaser angle button
 gui_DrawButton(powerButtonPosX, powerButtonPosY, powerButtonH, powerButtonW,
                update4, "-", font);
 
 //Draw Right/Increaser power button
 gui_DrawButton(powerButtonPosX + powerButtonStep, powerButtonPosY, 
                powerButtonH, powerButtonW, update5, "+", font);
                
 TTF_CloseFont(font);
 font = NULL; //to be sure :)
}

rec_Blit() - blit one surface(image) into another one(screen) at positino x, y nothing special gui_DrawButton()

void gui_DrawButton(int x, int y, int h, int w, bool pressed, char *caption,
                    TTF_Font *fontFile)
{
 Uint32 upColor, downColor;
 
 SDL_Color textColor = {200, 0, 0};
 SDL_Surface *text;
 
 //define colors for pressed button
 if(pressed == true)
 {
  upColor = SDL_MapRGB(g_Screen->format, 72, 72, 72);
  downColor = SDL_MapRGB(g_Screen->format, 211, 211, 211);
 }
 
 //define colors for unpressed buttons
 if(pressed == false)
 {
  upColor = SDL_MapRGB(g_Screen->format, 211, 211, 211);
  downColor = SDL_MapRGB(g_Screen->format, 72, 72, 72);
 }
 
 //draw button
 Draw_Line(g_Screen, x, y, x + w, y, upColor);
 Draw_Line(g_Screen, x, y, x , y + h, upColor);
 Draw_Line(g_Screen, x + w, y, x + w, y + h, downColor);
 Draw_Line(g_Screen, x, y + h, x + w, y + h, downColor);
 
 //Bold style
 //TTF_SetFontstyle(fontFile, TTF_style_BOLD);
 
 //Get Text
 text = TTF_RenderText_Blended(fontFile, caption ,textColor);

 //Draw Text
 rec_Blit(text, g_Screen, (x + 12), (((y + h) + y) / 2) - 15);
 
 //unload
 SDL_FreeSurface(text);
}

rec_ClearScreen() - fill the screen with given color Thats all i think, i know its a LOOOT of code but i spent almost all day looking for the problem, maybe i tired and missed something, so please i need your help.

I would love to change the world, but they won’t give me the source code.

Advertisement
Returned 0, program looks like it exited normally?

I'd ask you, (only because I have done it myself before [smile]), is gameRunning initially set to false?

Also, this is dangerous:
if(event.key.keysym.sym == SDLK_ESCAPE)    gameRunning = false;


Due to the way unions are implemented, it is possibly you'd get an event that had a value in the same memory offset equalling SDLK_ESCAPE, but not of type KEYUP/DOWN.

Prefer:
if( event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)    gameRunning = false;


Also, you should really consider caching the font loading, and the ttf_rendering surfaces. Running in a loop like that you're doing a lot more work than you need to.
This snippet here contains a problem:

while(SDL_PollEvent(&event))  {   //Pressed X   if(event.type == SDL_QUIT)    gameRunning = false;      //Pressed Escape    if(event.key.keysym.sym == SDLK_ESCAPE)    gameRunning = false;


You use the event.key struct without checking if event.type==SDL_KEYDOWN. Since the event structure is implemented with a union, this value could be anything at all when you check it. It could even be the code for SDLK_ESCAPE without an escape having been pressed - though that seems pretty unlikely!

You need to wrap the check for escape in an if(event.type == SDL_KEYDOWN).

<edit>Beaten by rip-off
i find that whenever an application behaves randomly, or appears to behave randomly, im reading a dodgy bit of memory.
Don't thank me, thank the moon's gravitation pull! Post in My Journal and help me to not procrastinate!
Guys you are awesome!!
Thanks for the fast answers! I'll try it today after school.

rip-off
Hmm yes cause actually main (return 0) so it should be normal exit...

Quote:I'd ask you, (only because I have done it myself before ), is gameRunning initially set to false?

Nop gameRunning looks like:
bool gameRunning = true;

I'll fix this block today and i'll try to catch font loading and ttf_renedering.

speciesUnknown
What do you mean?

By the way can you recommend me a debugger? Except GDB.
Thanks a lot again!!

EDIT:
Ok seems like it wont happen any more, any way it haven't happened yet maybe later but we'll see.
Now i got another problem how i can optimize
void menu_DrawMenu(int angle, int power, SDL_Surface *menuPic,
int buttonToUpdate)
Function? Any ideas?

[Edited by - Minios on April 20, 2007 7:12:07 AM]

I would love to change the world, but they won’t give me the source code.

Quote:Original post by Minios
Now i got another problem how i can optimize
void menu_DrawMenu(int angle, int power, SDL_Surface *menuPic,
int buttonToUpdate)
Function? Any ideas?


Yes, you should not be loading the font every time you call the function. Load it once at the beginning of the program and use it each time, then destroy it at the end. So you should not be calling TTF_OpenFont or TTF_CloseFont in that function.

Loading data from a file is orders of magnitude slower than anything else you're doing, so this should make a huge difference for this function.
Quote:Original post by Simian Man
Quote:Original post by Minios
Now i got another problem how i can optimize
void menu_DrawMenu(int angle, int power, SDL_Surface *menuPic,
int buttonToUpdate)
Function? Any ideas?


Yes, you should not be loading the font every time you call the function. Load it once at the beginning of the program and use it each time, then destroy it at the end. So you should not be calling TTF_OpenFont or TTF_CloseFont in that function.

Loading data from a file is orders of magnitude slower than anything else you're doing, so this should make a huge difference for this function.


After messages like this i hate my self even more the before :)
Simple thing but it lowered the cpu usage from 8-10 max to 5 max.
Thanks a lot!! :)

I would love to change the world, but they won’t give me the source code.

This topic is closed to new replies.

Advertisement