5
\$\begingroup\$

I'm trying to make a loading screen. My idea is to have two threads working - one in the background loading the 'game' scene, one displaying 'load' scene. When building 'game' scene is finished, it's displayed instead of 'load' scene. Before threading I want to make it work the usual way: first display 'load' scene, then 'game' scene. Both GameScene and LoadScene inherit from a virtual function Scene. Here's how my main looks like:

LoadScene *load_scene;
GameScene *game_scene;
Scene *scene;

int main(int argc, char **argv)
{
// Init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_STENCIL);
glutInitWindowPosition(initWindowX, initWindowY);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("OpenGL");

// Register callback functions for change in size and rendering.
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);

// Register Input callback functions.
// 'Normal' keys processing
glutKeyboardFunc(processNormalKeys);
glutKeyboardUpFunc(processNormalKeysUp);
// Special keys processing
glutSpecialFunc(processSpecialKeys);
glutSpecialUpFunc(processSpecialKeysUp);

// Mouse callbacks
glutMotionFunc(processActiveMouseMove);
glutPassiveMotionFunc(processPassiveMouseMove);
// void glutMouseFunc(void(*func)(int button, int state, int x, int y))
glutMouseFunc(processMouseButtons);
glutMouseWheelFunc(processMouseWheel);
// Position mouse in centre of windows before main loop (window not resized 
yet)
glutWarpPointer(windowWidth / 2, windowHeight / 2);
// Hide mouse cursor
glutSetCursor(GLUT_CURSOR_NONE);
// warp

// Initialise input and scene objects.
input = new Input();
//scene = new LoadingScene(input);
load_scene = new LoadScene();
game_scene = new GameScene(input);

// load scene 
// Create GameScene();
// Create LoadingScene(GameScene *)
// delete LoadingScene();
// LoadingScene thread tells game to start loafing assetss

// Enter GLUT event processing cycle
glutMainLoop();

return 1;
}

The game scene reassignment must be called in changeSize function. I thought it should be in the renderScene function but it's the only way it works. Here's how it looks like:

void changeSize(int w, int h)
{
scene = load_scene;

scene->resize(w, h);
}

Any ideas how I could go on about it? So far if I assign to 'scene' pointer 'load_scene' object it's displaying 'load' scene. Same goes for 'game' scene. Is it even possible to achieve a transition between scenes without threading?

\$\endgroup\$
  • \$\begingroup\$ For your last question: you can't have a smooth loading scene without threading because the loading process usually takes up longer then one frame time and so will pause you're game, create a chunky animation and, in some cases make it unresponsive. The only way so is threading; you can manually divide the process into small subroutines but it would be time expensive and imprecise. So make the OS do this, it's easier. Usually is you're loading function which run in another thread, but when it has finished you switch back to your main thread to call update and render functions \$\endgroup\$ – Liuka May 4 '17 at 5:17
  • \$\begingroup\$ I posted a comment because I haven't fully understand your problem. Maybe just because it's 7 a.m. (and I don't know anything about glut) :) \$\endgroup\$ – Liuka May 4 '17 at 5:23
  • \$\begingroup\$ I think you're right. I need to use threading in order to have a loading screen and to load my scene in the baclground. No I just need to learn threading and somehow figure that out :D \$\endgroup\$ – carrotcake May 4 '17 at 12:43
  • \$\begingroup\$ I'll post it as an answer with few more details then \$\endgroup\$ – Liuka May 4 '17 at 13:53
1
\$\begingroup\$

This is an answer based on my previous comments.

In a game you usually have one loading function for each system/component (graphic, input, window, game logic, entities...) and you call it once when your program starts. You always have to load files from disk to RAM and to perform heavy task to setup the data needed by your game to run. This takes a lot of time (in AAA games sometimes even a minute or more). If you want to have a loading animation you need to update it x times per second and you can't if you're program is doing something completly different.

One simple approach is to have a fixed loading screen with a simple progress bar: you load your systems with different function and, between each one you call some kind of "update method" which updates the loading percentage and displays it. This method has its limits: maybe one system takes a lot to intialize itself and your program stucks and becomes unresponive, but, first of all you have to manually write the code to separate the different loading functions (and keep it updated).

And here comes multithreading: let the OS performs this division, switching automatically between loading and rendering thread. You usualy have you're main thread where you perform things like input handling, rendering and so on and one where, while you're game is running, you load the data needed for the next level for example.

So, in pseudo-code you have:

//Main thread
//Create game window, load graphic engine ann other basic stuff
function load()
{
f_loadWindow(width, height);
f_loadInput(m_Window);
f_loadGraphic(m_Window);

var isLoading = true;

//create the loading thread where GameLogic::loadingFunction will run
var loadingThread = new Thread(GameLogic::loadingFunction, isLoading);

//Display loading animation from the main thread while the other is loading
while(isLoading){
    f_updateLoadingAnimation();
    f_renderLoadingAnimation();
}

//Now that the data is loaded close the secondary thread
loadingThread.join();

//Now you can easily enter the game loop (frame() function)
return;
}

function frame()
{
f_updateGameLogic();
f_renderGameLogic();
}

function loadingFunction(bool& _isLoading)
{
//Load different objs
f_LoadTerrrain();
f_LoadEntities();
...
f_LoadMisc();

//now that you have load everything set isLoading to false
//to stop the main thread's animation while loop
isLoading = false;

return;
}

Everything rotates around "isLoading" which allow the two threads to communicate. I actually can't remember how threading is implemented in c++, but you can easiy find it on google.

(I used functions insetead of classes to be clearer, of course you can go your own way).

Ask for anything you need.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.