Hi,
I’m trying to write a clone of an old DOS game in C++, using SDL,
and I’ve been working on that for about a year now, having tried
many different methods of event handling and drawing.
I first tried a structure where there was only one game loop that
was drawing the objects, updating them and handling input events.
Using a double-buffered video mode, the loops/sec of the whole game
were limited to approximately the refresh rate of my monitor, because
SDL_Flip waits for the vertical retrace.
The game got more and more complex (and slow), because there were
hundreds of objects that had to be updated and blitted, so I tried to use
multiple threads to speed up the game. Unfortunately, SDL doesn’t
support blitting and event handling in any other thread than the main
thread, so any speed improvement is lost because event handling and
drawing are limited by SDL_Flip() again.
Is there any possibility to call each object’s draw() method (where a lot
of blitting is done) from a separate thread, so that only this particular
thread has to run at 60-80 loops/sec. and the other ones are only
limitated by the CPU speed?
My last try was the following one:
I created three threads where game objects can register themselves,
and the thread objects call their draw() / update() / event() method
asynchronously.
The drawing thread also calls SDL_Flip() and SDL_Delay(10) to synchronize
with the vertical refresh, so it is the only one that is slowed down, but the
SDL docs say that it is not safe to call any library function outside the main
thread.
Can anyone give advice please?
-Christian
(I included a piece of code from main.cpp to show the use of the different threads).-----------------------------------------------------------------------------------------------
int runEventThread(void *ptr)
{
EventThread *threadObject = (EventThread *)ptr;
// EventThread::update() just goes through the list of
// registered objects and calls their event() method when
// an event occurs.
while(!threadObject->quit())
threadObject->update();
}
int runDrawThread(void *ptr)
{
DrawThread *threadObject = (DrawThread *)ptr;
// DrawThread::update() goes through the list of
// registered objects and calls their draw() method.
while(!threadObject->quit())
threadObject->update();
}
int runUpdateThread(void *ptr)
{
UpdateThread *threadObject = (UpdateThread *)ptr;
// UpdateThread::update() goes through the list of
// registered objects and calls their update() method.
while(!threadObject->quit())
threadObject->update();
}
int main(int argc, char *argv[])
{
IO *io = new IO();
EventThread *eventThread = new EventThread(io);
DrawThread *drawThread = new DrawThread(io);
UpdateThread *updateThread = new UpdateThread(io);
// create threads for drawing and event handling
SDL_Thread *event = SDL_CreateThread(runEventThread, (void *)eventThread);
SDL_Thread *draw = SDL_CreateThread(runDrawThread, (void *)drawThread);
SDL_Thread *update = SDL_CreateThread(runUpdateThread, (void *)updateThread);
Dune *dune = new Dune(io, 0, 0, 0, 640, 480, drawThread, updateThread, eventThread);
// the event thread quits when it receives an EVENT_QUIT event
SDL_WaitThread(event, NULL);
updateThread->stop();
drawThread->stop();
eventThread->stop();
SDL_WaitThread(update, NULL);
SDL_WaitThread(draw, NULL);
delete(dune);
delete(updateThread);
delete(drawThread);
delete(eventThread);
delete(io);
}