Jump to content

  • Log In with Google      Sign In   
  • Create Account


MrFraggs

Member Since 02 Jan 2012
Offline Last Active Nov 25 2013 08:12 PM
-----

#5076811 Advice With Game Loop

Posted by MrFraggs on 10 July 2013 - 10:58 PM

Alright i'll have to try both options out and see how they work, preferably across multiple pieces of hardware. Thanks for all the help, especially Ectara! It's hard to believe some random guy across the interwebs appreciating much, but believe me, I do :)




#5076802 Advice With Game Loop

Posted by MrFraggs on 10 July 2013 - 09:28 PM

You might want to consider a game that sleeps or waits for vsync instead of rendering as many times as possible. It's also a little better, I believe, to track performance in time, not FPS. Knowing your update is right at 60 UPS is nice - at least you know you have corrected your game loop now. Knowing it takes 12 ms on average, maybe with 18 ms spikes, is nicer. (I understand your update is nearly empty as of now, this is just an example.)

 

You won't get to be one of the guys here who talks about his awesome 4000 FPS game, but you might keep your CPU's fan from getting too loud.

 

Running at 4000+ FPS is definitely not a goal, just something it's doing. I'm not limiting it for now, just because I don't really have a need to aside from less cycles. Once I start adding things to the game, i'll see how they effect the FPS, and if it's capped, I won't know how it effects it unless it drops below my target. Then, when i'm confident that I won't be adding anything else that may significantly lower my FPS, I can work on capping it. My logic isn't currently based on FPS, but the amount of Update() passes per second, which I have set to 60 right now.

 

Also, I believe using any kind of Sleep() function when not explicitly programming multiple cores is bad. That's just what i've picked up over the years of learning, so until I get into that area if need be, I want to stay away from anything that puts the thread to sleep for now. I appreciate the suggestions though, definitely gives me things to think about!

 

Now, Ectara, I haven't really implemented any kind of time based logic, and I think that using a semi-fixed time step loop like this one, I read that it isn't necessary all the time. I could be way off, as I've only really spent the last few days deeply researching this. I came from XNA, which basically handled all this stuff for me. I did use ElapsedGameTime in XNA, which I think I can easily use here. That time function I used should keep track of the total time the game has been running, and if not, I can always use the less-precise SDL_GetTicks(). But say I was moving a sprite, and had something like this. This obviously wouldn't be all the logic, but I think it gets my point across:

 

SpritePositionX = 0

SpriteSpeed = 5

 

So, since I tried to get the updates to go the same amount of time (hence semi-fixed step, which is how http://gafferongames.com/game-physics/fix-your-timestep/ described it), each update if I were to move, I would do:

 

SpritePositionX = SpritePositionX + SpriteSpeed.

 

I know with game time based updating (which i'm not saying i WON'T use), since i'm trying to get Update() to run so many times per second, wouldn't it move 5 pixels each pass, which would be 60 x 5 pixels per second? I tried passing both dt and t to my Update method, and when playing around with variables increasing by 1 * some game time, I couldn't find a difference in increasing it by a static amount, like I used with SpriteSpeed, and increasing it by say, SpriteSpeed * gameTime. I understand the concept, but I can't really figure out if implementing it in my current design is necessary.

 

I could definitely be wrong on all of this, down to the entire game loop itself. Definitely not saying i'm right at all on anything, which is why i'm coming to you guys for help! Should I go by game time, which I think would look something like this:

 

Update(gameTime)

{

   GetLastGameTime;

   GetCurrentGameTime;

  Find the difference;

   Calculate logic based on difference;

}

 

I'm assuming based on your comments above that the game loop I have now will work well, (I hope!), so I think any changes I make come down to whether to update my logic based on time or Update() passes. 




#5076774 Advice With Game Loop

Posted by MrFraggs on 10 July 2013 - 08:13 PM

Ectara, I see what you meant now, sorry if it sounded like I came off as arrogant on that one! I didn't mean to at all, I just thought that what I did wasn't really clear, since you don't have all my code in front of you, just snippets.

 

Thanks for the replies, I went ahead and spent a day working through the link you guys posted trying to understand it better than I did before. I found a silly mistake that caused those updates and render cycle numbers to be off. The timer's he uses is based on seconds, even though they aren't real timers. They clearly say, "hi_res_timers_in_seconds", and no matter how many times I read it, nothing clicked. I finally saw it about two or three hours ago and got it fixed. Now my Update() runs properly at about 60 times per second, or whatever I set it to! 

 

I only have two more questions, and i'll post my current loop below. First, will this loop run the update function on most computers the same amount of times? I know if a computer can't handle it, the frame rate will drop, which is expected. But will the game logic run at the same speed even when the frames drop? I probably sound like a broken record, and for a 2D game it probably won't even be a huge problem, but if i'm going to learn something, I want to learn it right :P

 

Second, i'm not sure if this is based on my UPS calculations, or the game logic itself, but my UPS runs between 59.99xxx and 60.00xxx, where the xxx are any numbers, usually the same each time it switches. Is this really a huge problem, or can I ignore that?  It switches between the two constantly, and i'm not sure if that is going to effect my game logic. I set up a test where each update loop i have an x variable that increases by 1 each pass, so I could see how many times per second it updates. In theory, it should update by 60 each time if i'm running the update loop 60 times per second. It does a pretty good job of that, but every few seconds it will increase by 61 or so, meaning sometimes Update() will run an extra time. Will this end up being a huge problem, or is it normal and I should just ignore it? 

 

Thanks for all the help, I really appreciate the time and effort you guys are putting in to assist! :)

 

Here's my code, I grabbed the timer function online somewhere, as I was having some trouble grasping the QueryPerformanceCounter() function.

 

Main Loop:

const float dt = 1.0f / 60.0f;  //60 Would be desired updates per second

float currentTime = game->Time();  //Get the current time.
float accumulator = 0.0f;

while(game->IsRunning())
{
while(SDL_PollEvent(&e)) 
{
//Exit the game if the user hits the 'X' button on the window.
if(e.type == SDL_QUIT)
game->SetIsRunning(false);
} 

//Game update, render loop 

float newTime = game->Time();
float frameTime = (newTime - currentTime); //Convert to seconds
if(frameTime > 0.25f)
frameTime = 0.25f;
currentTime = newTime;

accumulator += frameTime;

while(accumulator >= dt)
{
game->Update();
accumulator -= dt;
}

game->Render();

} // End main loop

Timer Function:

//hi res timer in seconds
float Game::Time()
{
    static __int64 start = 0;
    static __int64 frequency = 0;

    if (start==0)
    {
        QueryPerformanceCounter((LARGE_INTEGER*)&start);
        QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
        return 0.0f;
    }

    __int64 counter = 0;
    QueryPerformanceCounter((LARGE_INTEGER*)&counter);

return (float) ((counter - start) / float(frequency));
}

UPS/FPS Tracking:

updateCount++;
	time = Time();
	UPS = updateCount / (time - timeBase); 
	FPS = frameCount / (time - timeBase);

	//Set the title each second
	if(time - timeBase >= 1) {
		timeBase = time;
		updateCount = 0.0f;
		frameCount = 0.0f;

		std::stringstream strs;
		strs << "FPS: "<< FPS << " UPS: " <<  UPS;
		std::string temp = strs.str();
		char* theTitle = (char*)temp.c_str();
		//Set window title to fps
		SDL_SetWindowTitle(mWindow, theTitle); 
	}



PARTNERS