Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

878848 Posts in 32941 Topics- by 24349 Members - Latest Member: Ozymandias

May 22, 2013, 07:27:26 PM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)Post your game loop
Pages: 1 [2] 3 4
Print
Author Topic: Post your game loop  (Read 2272 times)
agersant
Level 3
***



View Profile WWW Email
« Reply #15 on: June 12, 2012, 12:21:49 PM »

Code:
//Main loop
static function update (e : Event) : Void {
if (crashed) return;
frameTick = clock.clock();
for (s in scenes) s.update();
for (s in screens) s.draw();
Bank.cleanXmlMaps();
}
Logged

Pishtaco
Level 9
****



View Profile WWW
« Reply #16 on: June 12, 2012, 12:46:58 PM »

Kind of rambling:

Code:
    while (!game.quit_now)
    {
        game.updateState(dt); //use dt from last frame

        //TODO - fix input dt - maybe have continuous and discrete input as separate functions?
        handleInput(game, dt); //use dt from last frame

        current_time = stopwatch.microsec();
        float actual_dt = cast(float)(current_time - last_time)/1000000; //microseconds to seconds
        last_time = current_time;
        float bounded_dt = min(actual_dt, 0.1);

        game.updateGui(bounded_dt);

        if (!game.paused) dt = game.updateModel(bounded_dt);
        else dt = game.updateModel(0);

        game.updateView(dt);
        game.render();

        Screen.setupPointSprites();

        screen.setupOrthogonalProjection();
        if (game.console_open) Console.drawFully(screen);
        if (game.show_framerate) Console.displayFPS(game.current_FPS, screen);
        game.current_FPS = FPSCounter.update(actual_dt);

        //SDL_Delay(1);
        SDL_GL_SwapBuffers();
        game.frame_counter += 1;
        Screen.switchTextureUnit(0);
    }
I think the "setupPointSprites" thing is there to work around some bug.
Logged

Evan Balster
Level 10
*****


dreaming close to metal


View Profile WWW Email
« Reply #17 on: June 12, 2012, 03:29:30 PM »

My engine of three years' main loop:

Code: (Main Loop)
int Program::run()
{
    //Main game loop
    graphics.gui.focusMode(GUI::FocEngine);
    while (go)
    {
        //Random number generator may need to update early for some reason
        random.update();

        //Drop tasks
        if (keyboard.f8.pressed())
            for (Tasks::iterator i = tasks.begin(); i != tasks.end(); ++i)
                dropTask(*i);

        //---Game state update begins---
        graphics.gui.focusMode(GUI::FocTask);

        if (!pause || slow)
        {
            //Run tasks
            clock.benchStart();
            for (Tasks::iterator i = tasks.begin(); i != tasks.end(); ++i)
            {
                (*i)->update();
            }
            console.monitor() << L"Tasks: "
                << std::ceil(clock.benchStop() * 100.0f/.025f)
                << L"%\n";
            slow = false;
        }

        //Process added and dropped tasks
        for (Tasks::iterator i = dropTasks.begin(); i != dropTasks.end();
            ++i)
        {
            bool found = false;
            for (Tasks::iterator j = tasks.begin(); j != tasks.end(); ++j)
                if (*i == *j)
            {
                delete *j;
                tasks.erase(j);
                found = true;
                break;
            }
            if (!found) reportWarning("Tried to drop non-existent task...");
        }
        dropTasks.clear();
        for (Tasks::iterator i = addTasks.begin(); i != addTasks.end(); ++i)
        {
            tasks.push_back(*i);
        }
        addTasks.clear();


        //---Game state update is done---
        graphics.gui.focusMode(GUI::FocEngine);

        //Universe processes include cleaning up deleted entities.
        //  If we do it between tasks and output, deleted objects disappear
        // more responsively and created ones appear immediately.
        universe.update();

        //Audio processing (needs to follow the action closely)
        audio.update();

        //Network processing (send information soon after frame)
        network.handleOutbound();

        //Console comes after program elements, before graphics update
        if (pause) console.monitor() <<
            (clock.interval(.9f, .1f) ? L"[PAUSED]\n" : L"\n");
        if (!tasks.size() && !console.active()) console.introduce();
        console.update();

        //Likewise with GUI
        gui.update();

        //Graphics processing
        graphics.update();

        //Process program messages (may be a shut-down signal)
        update();

        //Clock processes last (it regulates framerate)
        clock.update();

        //Network processing (send information soon before frame)
        network.handleInbound();

        //Player input close before tasks, for responsiveness
        player.update();
    }

    return 0;
}

The ordering of input, logic and output can have surprising results on gameplay latency, for the unaware.


Here's my Clock module's update, since we're talking about framerate regulation too:

Code: (Clock Module)
void Clock::update()
{
    //No benchmarking should occur during clock's operation.
    if (!bench.empty()) reportError("Benchmark stack not empty!");

    //Console output of performance estimate
    float timeTaken = imp->currentTime() - frameStart;
    perf = .97f * perf + 3.0f*(timeTaken / frameLength);
    console.monitor() << std::ceil(perf) << L"% Time\n(";
    if (fpsLast < 10) console.monitor() << L"0";
    console.monitor() << fpsLast << L" FPS)\n";
    long secA = long(frameStart), secB;


    // (snipped some bizarro iOS testing code from this post)


    //Seed randomizer with time consumption
    random.cryptoSeed((Uint8*) &timeTaken, sizeof(float),
        3, Randomizer::SRC_PLAYER);

    //Advance time by one frame
    frameCount++;
    contextTime += timeStep;
    goalTime += timeStep;

    //Regulate framerate.
    imp->waitUntil(goalTime);

    //Note time after delay for next frame, and bound goal time.
    frameStart = imp->currentTime();
    goalTime = min(max(goalTime,
        frameStart - frameLength), frameStart + frameLength);

    //Framerate counting
    secB = long(frameStart);
    if (secA != secB)
    {
        fpsLast = fpsCount;
        fpsCount = 0;
    }
    ++fpsCount;
}

It's vsync-friendly due to the accumulator.
Logged

Infinite Blank, SoundSelf, Cave Story+, Wreath
voice, accordion, mandolin, (oboe, soon)
Game audio programming consultant.
<plaid/audio>: opensource audio framework
FuzzYspo0N
Level 0
***



View Profile WWW Email
« Reply #18 on: June 12, 2012, 03:37:43 PM »

Evan linked me into this cool thread, I guess ill post !

Code:
void cCore::process() {

     ptimer.start();
     shuttingDown = false;

while(!shuttingDown) {

boost::this_thread::sleep( boost::posix_time::milliseconds( 1 ) );

deltaTime = dte - dts;
dts = ptimer.getTime();

   time->process();
   events->process();
   net->process();
     Core::Script::process();
   phoenix->process();

dte = ptimer.getTime();

} //end while

} //end process()
Logged

ThemsAllTook
Moderator
Level 8
******


Alex Diener


View Profile WWW
« Reply #19 on: June 12, 2012, 03:55:22 PM »

A lot of what's been posted has some form of conditional that allows you to exit the run loop. Any reason you guys don't just call exit()? The OS will clean up everything for you, and probably do it quicker than if you tear things down yourself.

All of these have made sense to me until I got to Evan's. What's this Task mechanism you have in here? Some sort of cooperative multithreading? I can't figure out the purpose of graphics.gui.focusMode(), either.
Logged
zacaj
Level 3
***


void main()


View Profile WWW Email
« Reply #20 on: June 12, 2012, 03:58:08 PM »

A lot of what's been posted has some form of conditional that allows you to exit the run loop. Any reason you guys don't just call exit()? The OS will clean up everything for you, and probably do it quicker than if you tear things down yourself.

I have read in multiple place people claiming that the OS will/won't do this, always seemingly expert/trustable people, so I thought I might as well play it safe and close everything.  Plus, remembering to free everything when you exit the program will help you remember other in game places you've forgotten to free stuff
Logged

My twitter: @zacaj_

Quote from: mcc
Well let's just take a look at this "getting started" page and see--
Quote
Download and install cmake
Noooooooo
eigenbom
Level 10
*****



View Profile WWW
« Reply #21 on: June 12, 2012, 04:00:13 PM »

@kamac Yes I like pointers, how else do you get direct access to things? Smiley This..
Code:
Root::Instance()->physicsSystem->doSomething();
.. is fairly clear to me. As long as you have a well-defined way of using them, they aren't too dangerous.

@themsall Yeh my usual mode of operation is to code things directly in and then refactor them out, if I can't see clearly from the outset hows its going to be modularised. So all the loading screen code, for example, will eventually be smooshed into some sort of LoadingScreen class or something. Smiley The ISystemBase is a necessary abstraction, as an entity stores a list of systems it belongs to, which are all of that type.

Haha, the .Reset() .restart() is due to SFML changing APIs midway through my development. Tongue And thanks for the note, but they are all low resolution timers, so their exact values don't matter. Smiley



Logged

eigenbom
Level 10
*****



View Profile WWW
« Reply #22 on: June 12, 2012, 04:05:30 PM »

A lot of what's been posted has some form of conditional that allows you to exit the run loop. Any reason you guys don't just call exit()? The OS will clean up everything for you, and probably do it quicker than if you tear things down yourself.

Maybe:
- You might want to save or flush data, or log statistics
- It's good defensive programming to free all memory you've allocated
- It provides a clear flow, you know that when your program exits it will run the last bit of code under the while loop, rather than exiting from deep within your program
Logged

pekuja
Level 0
*



View Profile WWW Email
« Reply #23 on: June 12, 2012, 04:32:04 PM »

This is actually my first post here on TIGForums. Seemed like a fun thread to join.
Code:
int ret=0;
while (!s3eDeviceCheckQuitRequest() && !Game::quit)
{
Game::update(ret);
Gfx::render(ret);
Gfx::flip_buffers();

Input::update();
s3eDeviceYield(0);
}
Hmm, I think that ret variable isn't even used anywhere. Leftovers from a previous state of the code.
Logged
BlueSweatshirt
Level 10
*****


the void


View Profile WWW
« Reply #24 on: June 12, 2012, 04:43:35 PM »

Code:
    void GameContext::gameLoop() {

        m_window = new sf::RenderWindow(sf::VideoMode(m_win_width, m_win_height), m_win_title);

        while(m_window->isOpen()) {
            sf::Event event;
            while(m_window->pollEvent(event)) {
                if (event.type == sf::Event::Closed)
                    m_window->close();
                if (event.type == sf::Event::Resized)
                    setWindowSize(event.size.width, event.size.height);
            }

            m_elapsed = m_clock.getElapsedTime();
            m_clock.restart();

            update();

            m_window->clear(m_clearCol);
            render();
            m_window->display();

        }

        m_running = false;
        delete m_window;
        if (m_thread) m_thread->terminate();
    }

For the GameContext class in my framework/engine.
Logged

eigenbom
Level 10
*****



View Profile WWW
« Reply #25 on: June 12, 2012, 04:45:37 PM »

hey pekuja, welcome, and nice loop you've got there. is that for tiny hawk? Smiley
Logged

Dovuro
Level 0
*


View Profile
« Reply #26 on: June 12, 2012, 04:46:51 PM »

A lot of what's been posted has some form of conditional that allows you to exit the run loop. Any reason you guys don't just call exit()? The OS will clean up everything for you, and probably do it quicker than if you tear things down yourself.

I have a loop exit condition in my game loop for iOS. When the user hits the home button, sending the app to the background, I exit out of the game loop. When the user resumes the app I start the game loop up again. I do this because iOS will sometimes opt to simply kill an app instead of suspend it if it doesn't stop doing work correctly while in the background. iOS will, for example, kill an app that attempts to make OpenGL calls while in the background. I also exit the game loop when they put their device into sleep mode, and start the loop again when they wake their phone back up. iOS won't kill an app for processing while the device is asleep, but it'll drain the battery unnecessarily, so stopping the loop is just a nice thing to do there.
Logged
pekuja
Level 0
*



View Profile WWW Email
« Reply #27 on: June 12, 2012, 05:05:45 PM »

hey pekuja, welcome, and nice loop you've got there. is that for tiny hawk? Smiley

Yeah, that's the Tiny Hawk loop for iOS and Android, using Marmalade SDK. It's a bit different in the PSP version, but I don't know if it'd be ok to post that. Maybe if I took out the few PSP API calls I have in there.
Logged
Evan Balster
Level 10
*****


dreaming close to metal


View Profile WWW Email
« Reply #28 on: June 12, 2012, 05:11:41 PM »

A lot of what's been posted has some form of conditional that allows you to exit the run loop. Any reason you guys don't just call exit()? The OS will clean up everything for you, and probably do it quicker than if you tear things down yourself.

A more philosophical answer:  In C or Java, the destruction of an object is not typically a significant event.  In C++, by contrast, everything has a very well-defined endpoint to its lifespan and a sequence of carefully-ordered events that happens there.  This allows for constructs such as an object representing the period of time a mutex is locked, frames of a stack elsewhere in the program, or objects which perform and undo a modification to the filesystem at the beginning and end of their lifetime.  (I do this in one program to automatically reload an autosave file if I've detected the last session ended abnormally)  To simply exit() dispenses with this entire paradigm and all the strengths it can offer.

The short answer, though, is "saving on exit".


All of these have made sense to me until I got to Evan's. What's this Task mechanism you have in here? Some sort of cooperative multithreading? I can't figure out the purpose of graphics.gui.focusMode(), either.

A game or program running on the engine would be a Task.  These can coexist, though I don't often do so.  I manage their addition and removal from the system with careful timing for reasons I don't need to explain.  Smiley

As for focusMode(), that's a bit obscure.  The debug terminal (an overlay accessed with the ~ key) blocks keyboard and mouse button input to GUI objects and Tasks.  GUI objects can block this focus to Tasks, as well.  I put a bizarro masking system in place so that the press/release states would be properly triggered when the focus mode transitioned.  (In case, say, the player was holding the "shoot" button when the console popped up, or lord knows what else)
Logged

Infinite Blank, SoundSelf, Cave Story+, Wreath
voice, accordion, mandolin, (oboe, soon)
Game audio programming consultant.
<plaid/audio>: opensource audio framework
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #29 on: June 12, 2012, 06:06:03 PM »

Not a lot to say really, it does what it does.

What's the language? I don't recognize it.

Ada.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Pages: 1 [2] 3 4
Print
Jump to:  

Theme orange-lt created by panic