I am making an Sdl game, it's 2d shooter. I am using SDL to import surfaces and OpenGL to draw them on the screen (doing so because it works way faster than just SDL). I've got two threads running, one for processing stuff and rendering, and another one for input. Basically, the processing one is taking 1-2% of my CPU, while the input loop takes 25% (on quad-core, so it's 1 full core). I tried doing SDL_Delay(1) before each while (SDL_PollEvent(&keyevent))
and it works! Reduces CPU load to 3% for whole process. However, there's a nasty side effect. The whole program input is handicapped: it doesn't detect all of the key pressed, and for example, to make the character move, it sometimes takes up to 3 seconds of bashing keyboard for it to react.
I've also tried solving it by using SDL_PeepEvent()
and SDL_WaitEvent()
, however, it's causing the same (very long!) delay.
Event loop code:
void GameWorld::Movement()
{
SDL_Event keyevent;
bool x1, x2, y1, y2, z1, z2, z3, m; // Booleans to determine the
x1 = x2 = y1 = y2 = z1 = z2 = z3 = m = 0; // movement direction
SDL_EnableKeyRepeat(0, 0);
while (1)
{
while (SDL_PollEvent(&keyevent))
{
switch(keyevent.type)
{
case SDL_KEYDOWN:
switch(keyevent.key.keysym.sym)
{
case SDLK_LEFT:
x1 = 1;
x2 = 0;
break;
case SDLK_RIGHT:
x1 = 0;
x2 = 1;
break;
case SDLK_UP:
y1 = 1;
y2 = 0;
break;
case SDLK_DOWN:
y1 = 0;
y2 = 1;
break;
default:
break;
}
break;
case SDL_KEYUP:
switch(keyevent.key.keysym.sym)
{
case SDLK_LEFT:
x1 = x2 = 0;
break;
case SDLK_RIGHT:
x1 = x2 = 0;
break;
case SDLK_UP:
y1 = y2 = 0;
break;
case SDLK_DOWN:
y1 = y2 = 0;
break;
default:
break;
}
break;
case SDL_QUIT:
PrintToFile("The game was closed manually.\n");
CleanUp();
return;
break;
default:
break;
}
}
m = x1 || x2 || y1 || y2;
if (m) // if any button is pushed down, calculate the movement
{ // direction and assign it to the player
z1 = (x1 || x2) && (y1 || y2);
z2 = !x1 && (x2 || y2);
z3 = (!y1 && x1) || (!y2 && x2);
MainSurvivor->SetMovementDirection(4 * z1 + 2 * z2 + z3);
}
else // if no button is pushed down, reset the direction
MainSurvivor->SetMovementDirection(-1);
}
}
Code for calculation/render loop:
void GameWorld::GenerateCycles()
{
int Iterator = 0;
time_t start;
SDL_Event event;
Render();
_beginthread(MovementThread, 0, this);
while (1)
{
// I know I check this in input loop, but if I comment
SDL_PollEvent(&event); // out it from here, that loop cannot
if (event.type == SDL_QUIT) // see any of the events (???)!
{
PrintToFile("The game was closed manually.\n");
CleanUp();
} // It never closes through here though
start = clock();
Iterator++;
if (Iterator >= 232792560)
Iterator %= 232792560;
MainSurvivor->MyTurn(Iterator);
for (unsigned int i = 0; i < Survivors.size(); i++)
{
Survivors[i]->MyTurn(Iterator);
if (Survivors[i]->GetDiedAt() != 0 && Survivors[i]->GetDiedAt() + 25 < clock())
{
delete Survivors[i];
Survivors.erase(Survivors.begin() + 5);
}
}
if (Survivors.size() == 0)
SpawnSurvivors();
for (int i = 0; i < int(Zombies.size()); i++)
{
Zombies[i]->MyTurn(Iterator);
if (Zombies[i]->GetType() == 3 && Zombies[i]->GetDiedAt() + 25 < Iterator)
{
delete Zombies[i];
Zombies.erase(Zombies.begin() + i);
i--;
}
}
if (Zombies.size() < 3)
SpawnZombies();
// No need to render every cycle, gameplay is slow
if (Iterator % 2 == 0)
Render();
if (Interval - clock() + start > 0)
SDL_Delay(Interval - clock() + int(start));
}
}
Does anyone have any ideas?