Jump to content
  • Advertisement
Sign in to follow this  
sakatius

SDL animation problem (uses SDL_AddTimer)

This topic is 3894 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently using Dev-C++ and SDL to develop a game. In my main function I've made use of the SDL timer functionality: gameTimerId = SDL_AddTimer((33/10)*10, myCallbackFunc, NULL); In my function 'myCallbackFunc', I do most all the game handling, although I do have a while-loop running in the 'main' function as well that handles a minimal amount of input from the user: while(!done){ ... } In my 'myCallbackFunc', the last two segments of code are the same; however, if I comment out the last segment posted here before my comment /* testing */, everything works fine, it's when I include that segment that my screen gets rendered once (possibly twice) but immediately freezes and won't accept input handled in the 'myCallbackFunc' (which to me seems like it should work just fine since it is the same code segment as above and it worked fine). The only explanation I could think of is that the function isn't finishing before it's being called again? I doubled the amount of time when I called SDL_AddTimer, but that had no effect, and from what I can guess, that one pivotal code segment should not double the amount of time needed. I also tried passing (33/10)*100 as the first parameter in my SDL_AddTimer call, multiplying my previous parameter by 10, but that too had no effect. Any help will be so much appreciated; I suspect there may be factors concerning SDL, my compiler, or my computer that I'm simply not aware of. Here is the bulk of my 'myCallbackFunc' function, please tell me if you spot anything: Uint32 myCallbackFunc(Uint32 interval, void* param) { // Handle the user input if(gamePhase == GAME_PLAY){ HandleGamePlayInput(); // Handle the user's input list< list<Spacecraft> >::iterator currentWave = waves.begin(); while(currentWave != waves.end()){ list<Spacecraft>::iterator currentSpacecraft; for(currentSpacecraft = (*currentWave).begin(); currentSpacecraft != (*currentWave).end(); currentSpacecraft++){ if(currentSpacecraft->health <= 0) currentSpacecraft = (*currentWave).erase(currentSpacecraft); // Remove destroyed enemies from the current wave, and continue to the next sprite in the wave currentSpacecraft->setPosition(Coor(currentSpacecraft->getPosition().x, currentSpacecraft->getPosition().y + 2)); // Move the spacecraft in the wave 2 pixels down } if(currentWave->empty()){ // If all the sprites were destroyed and removed from the wave currentWave = waves.erase(currentWave); // Erase the wave and iterate to the next wave } else currentWave++; // Simply iterate to the next wave } // Iterate through and modify each missle's position. Remove all the missles that are no longer actively involved in game play. list<Sprite>::iterator currentMissle = missles.begin(); while(currentMissle != missles.end()){ currentMissle->setPosition(Coor(currentMissle->getPosition().x, currentMissle->getPosition().y - 10)); // Propel the missle forward 10 pixels up the screen if(currentMissle->getBottomRightCorner().y < 0){ currentMissle = missles.erase(currentMissle); // Removes the missle from the game and iterates to the next missle in the list } else currentMissle++; // Simply iterate to the next missle } /**/ // Check if the front wave has breached the bottom of the screen completely (the sprite can no longer be seen) if(!waves.empty()){ list<Spacecraft> frontWave = waves.front(); // The front wave of enemies Spacecraft tSpacecraft = frontWave.front(); // Since all sprites in a wave share the same y-coordinate, just check the first one if(tSpacecraft.getTopLeftCorner().y >= gameSpace.getBottomBoundary()){ // If the first sprite has breached the bottom of the screen completely score -= (100 * frontWave.size()); // Deduct 100 points from the score for each sprite located in the front wave (that breached the bottom of the screen completely) waves.pop_front(); // Remove the front wave from the list of waves } } /**/ // Iterate through and modify each missle's position. Remove all the missles that are no longer actively involved in game play. //bool missleDetonation = false; // Stores whether the current missle detonated or not (thus needing to be erased from the list of missles) currentMissle = missles.begin(); while(currentMissle != missles.end()){ currentWave = waves.begin(); // Iterator for the list of waves of enemies, defined earlier currentMissle->setPosition(Coor(currentMissle->getPosition().x, currentMissle->getPosition().y - 10)); // Propel the missle forward 10 pixels up the screen if(currentMissle->getBottomRightCorner().y < 0){ currentMissle = missles.erase(currentMissle); // Removes the missle from the game and iterates to the next missle in the list } else currentMissle++; // Simply iterate to the next missle } /* testing */ currentMissle = missles.begin(); while(currentMissle != missles.end()){ currentWave = waves.begin(); // Iterator for the list of waves of enemies, defined earlier currentMissle->setPosition(Coor(currentMissle->getPosition().x, currentMissle->getPosition().y - 10)); // Propel the missle forward 10 pixels up the screen if(currentMissle->getBottomRightCorner().y < 0){ currentMissle = missles.erase(currentMissle); // Removes the missle from the game and iterates to the next missle in the list } else currentMissle++; // Simply iterate to the next missle } } Render(); // Render the screen } ----------------------------------------------- Here are some global declarations too, if they help: #include <list> using std::list; #include <SDL/SDL.h> #include <time.h> DivContainer gameSpace(Coor(0,0), WINDOW_WIDTH, WINDOW_HEIGHT); // The space on the screen in which the action takes place SDL_TimerID gameTimerId; // = SDL_AddTimer((33/10)*10, myCallbackFunc, NULL); bool done = false; // Temporary global variable for main loop termination int spriteHealth = 100; // Percentage of health for the main character sprite Sprite goodGuy; SDL_Surface *g_Screen = NULL; // The window's screen list< list<Spacecraft> > waves; list<Sprite> missles; bool loadedMissle = false; // This global variable flags whether a missle is loaded or not for the user's spacecraft bool missleDetonation = false; // This doesn't need to be global but is used in my 'myCallbackFunc' function and created adverse effects if I declared this boolean inside the scope of the function, it's so puzzling.

Share this post


Link to post
Share on other sites
Advertisement
SDL timers are actually very tricky, because they can run in different threads. To quote from the SDL documentation:
Quote:

The timer callback function may run in a different thread than your main program, and so shouldn't call any functions from within itself. However, you may always call SDL_PushEvent.


Your main() code can simply call PollEvent (or better still WaitEvent if you aren't doing any other background processing):


enum CustomEvent {
// whatever timed events you want
TICK,
DRAW,
};

Uint32 tickCallback(Uint32 interval, void *param)
{
SDL_Event event;

event.type = SDL_USEREVENT;
event.user.code = TICK;
event.user.data1 = NULL;
event.user.data2 = NULL;

SDL_PushEvent(&event);
return(interval);
}

Uint32 drawCallback(Uint32 interval, void *param)
{
SDL_Event event;

event.type = SDL_USEREVENT;
event.user.code = DRAW;
event.user.data1 = NULL;
event.user.data2 = NULL;

SDL_PushEvent(&event);
return(interval);
}

int main(int, char**)
{
init();

// set the timers

SDL_Event event;
while(SDL_WaitEvent(&event))
{
if(event.type == SDL_QUIT)
{
break;
}
else if(event.type = SDL_USEREVENT)
{
if(event.user.code == TICK)
{
updateGameLogic();
}
else if(event.user.code == DRAW)
{
render();
}
}
else
{
// handle user input
}
}
cleanup();
}




All you would have to do then is decouple the user input from the ticking, or user SDL_GetMouseState and SDL_GetKeyboardState instead of calling PollEvent in your updateGameLogic() function.

Share this post


Link to post
Share on other sites
Excellent! That helped me out tremendously, thank you so much! I used the code you provided as a template to rebuild my main() function; the line "else if(event.type = SDL_USEREVENT)" gave me some grief, but I finally spotted it; thanks again!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!