Problem with the logic of a small C++ program

Hello. I’m trying to write a little one-off program. I use C++ and SDL library. Those details don’t matter as I am having problems with writing the logic.

It should do this:

  1. Start playing the first song & begin iterating through an array of image files, displaying each one and waiting n-milliseconds before displaying the next one
  2. Is the first song done? Play the second one
  3. Quit, when the user presses X or ALT-F4 on keyboard.

So, the target is to do this: plays 2 songs, iterates over pictures while the songs are playing (sort of a slideshow), quits only when the user closes it.
I am having a problem with organizing the logic.

The main loop iterates, only after the n-milliseconds that I give to the function SDL_Delay(n) has passed. This causes the problem that, when the user wants to quit the program, it does not quit until the next iteration of the loop. It “freezes” there until the next iteration, doesn’t quit immediately.

I tried to create a function that takes a song filename argument and plays it then returns. This works alright.
My problem is with the delay after displaying each image: I can’t figure a way to do both: Quit immediately when the user closes the window && delay n-milliseconds between each picture. Even if I wrote a function that takes image filename argument and displays it and delays n-milliseconds, main() is still stuck waiting for that function to return, and dealing with a quit event is still stuck along with that delay.

I wonder, if it is possible to have two loops run along parallely? Or if the logic could be organized better?
Please help.

This is the main file. The other defintions are in other files and work as I intend them to do.

Code:
int main(int argc, char* argv[])
{
vector<SDL_Surface*> surfaces(26, NULL);
SDL_Event e;
bool quit = false;
bool first = false; // Set to true when the first song has been played
bool second = false; // Set to true when the second song has been played
vector<Mix_Music*> m(2, NULL);

// Initialize SDL facilities
if (!init())
{
	cout << "Initialization failed" << endl;
	return 1;
}
else
{
	unsigned int i = 0;
	while (!quit)
	{
		// Start first song
		if ((!Mix_PlayingMusic() && !first) && !second)
		{
			first = true;
			m[0] = loadMusic(songs[0].c_str());
			Mix_PlayMusic(m[0], 1);
		}

		// Start second song
		if ((!Mix_PlayingMusic() && first) && !second)
		{
			second = true;
			m[1] = loadMusic(songs[1].c_str());
			Mix_PlayMusic(m[1], 1);
		}

		// Image display
		if (i < images.size());
		{
			if (!loadImage(images[i].c_str(), surfaces[i]))
			{
				cout << "Failed to load image\n";
			}
			else
			{
				SDL_Rect stretchRect;
				stretchRect.x = 0;
				stretchRect.y = 0;
				stretchRect.w = SCREEN_WIDTH;
				stretchRect.h = SCREEN_HEIGHT;
				SDL_BlitScaled(surfaces[i], NULL,
						gScreenSurface, &stretchRect);

				SDL_UpdateWindowSurface(gWindow);
				SDL_Delay(15000);
			}
			++i;
		}

		// Check if user wants to quit
		while (SDL_PollEvent(&e) != 0)
		{
			if (e.type == SDL_QUIT)
				quit = true;
		}
	}
}

// Cleanup
Mix_FreeMusic(m[1]);
Mix_FreeMusic(m[0]);
close(surfaces);

return 0;

}

[/code]

The problem lies in using SDL_Delay(). This function basically ‘pause’ the main thread, everything freezes in the given amount of time. That’s why the user have to wait for n-ms before the application closes.

You have to change the approach to display an image in n-milliseconds. Instead of using SDL_Delay, uses SDL_GetTicks() to get the duration of time since SDL is initialized. It could be something like this (warning: I didn’t compile the code, it might not compile).

Code:

int imageShowsAt = SDL_GetTicks();
while(!quit)
{
int currentTime = SDL_GetTicks();
if(currentTime - imageShowsAt > 15000)
{
imageShowsAt = currentTime;
changeImage();
}
SDL_Delay(0);
}

I put the delay function at the end of the loop, because the main loop needs one for some reason (which I don’t remember, I’m sorry).

Hope this helps!

Now I remember why I’d put it there. I found that on some platform, if there’s put SDL_Delay() in the main loopat all, the application might become unresponsive (even though it works just fine). But if you found the code works, it might not need that function call.

Glad you get it working!

Here I do most things 60 times a second. For it to be the best it can be
there should also be code to drop the frequency of updated frames if there
starts to be a lag. If the logic does not run then all is lost. You could
even have reducer functions that simplify what the game does to speed it up
if it gets too slow. I’d rather play a really simple but fun game running
fine than have a fancy game that lags really bad or speeds up and slows
down all the time.

p.s. the example is no even a beta version but most of it is noob gold.
It’s main focus is to help people learning to get things done in simple
ways. It’s pretty small. Should I link it in the future?On Thu, Feb 6, 2014 at 11:47 AM, mr_tawan <mr_tawan at hotmail.com> wrote:

The problem lies in using SDL_Delay(). This function basically 'pause’
the main thread, everything freezes in the given amount of time. That’s why
the user have to wait for n-ms before the application closes.

You have to change the approach to display an image in n-milliseconds.
Instead of using SDL_Delay, uses SDL_GetTicks() to get the duration of time
since SDL is initialized. It could be something like this (warning: I
didn’t compile the code, it might not compile).

Code:

int imageShowsAt = SDL_GetTicks();
while(!quit)
{
int currentTime = SDL_GetTicks();
if(currentTime - imageShowsAt > 15000)
{
imageShowsAt = currentTime;
changeImage();
}
SDL_Delay(0);
}

I put the delay function at the end of the loop, because the main loop
needs one for some reason (which I don’t remember, I’m sorry).

Hope this helps!


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

-------------- next part --------------
A non-text attachment was scrubbed…
Name: TWINDRAGON_SDL2_GAME_EXAMPLE.zip
Type: application/zip
Size: 9264 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20140207/83cec2e0/attachment-0001.zip

Thank you, tawan. Your suggestion solves my problem.

Only two notes:

  1. I had to change the condition for displaying an image to test whether i is 0, so that it displays an image immediately at the program’s start, like so:

Code:
if (currentTime - imageShowsAt > 15000 || i == 0)

  1. It works just fine with no mentions of SDL_Delay(0) at all, unlike you said it would require, on both Windows and Linux and different IDE’s (GCC, Visual Studio and Code::Blocks).