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

Posts I've Made

In Topic: Advice With Game Loop

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 :)


In Topic: Advice With Game Loop

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. 


In Topic: Advice With Game Loop

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); 
	}

In Topic: Advice With Game Loop

10 July 2013 - 03:38 PM

So I reworked my loop, and this is what I have, but with an unexpected result:

double t = 0.0;
	const double dt = 0.01;

	double currentTime = SDL_GetTicks();
	double accumulator = 0.0;

	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	

		double newTime = SDL_GetTicks();
		double frameTime = newTime - currentTime;
		if(frameTime > 0.25)
			frameTime = 0.25;
		currentTime = newTime;

		accumulator += frameTime;

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

		game->Render();

	} // End main loop

Now, I know that SDL_GetTicks() only has a resolution of 1ms, so I may find a better one soon. Here is my code for calculating frames per second and updates per second:

	updateCount++;
	time = SDL_GetTicks();
	if(time - timeBase > 1000) {
		UPS = updateCount * 1000.0 / (time - timeBase); 
		FPS = frameCount * 1000.0 / (time - timeBase);
		timeBase = time;
		updateCount = 0;
		frameCount = 0;
	}

timeBase, frameCount and updateCount are all initialized to zero in the constructor, and frameCount++ is located in the render function, but I didn't find it necessary to include that entire function for one line of code, which is basically in Update() as well. 

 

Now, here is where I'm confused. the FPS is about 270, while the UPS is about 7000. This seems a little off, but I could be wrong. I haven't incorporated the time stuff into the Update() function yet, since there's nothing on the screen to worry about updating, but I will when I get this loop going correct. How does it look to you guys? Would you do anything different? Thanks!


In Topic: Advice With Game Loop

10 July 2013 - 12:02 PM

Like I said, that has nothing to do with the actual FPS/UPS calculations. The FPS/UPS variable it updates to is STRICTLY for display purposes. I added that code in after I had the rates updating at the same time as it had after I added that code. It has NOTHING to do with the actual fps/ups calculations, just the display of information that tells me how many times per second the game is updating. If I run the game, which is just a blue screen still, it updates the title of the window with that information, telling me that i'm getting about 4000-4500 FPS, and about 60-62 UPS right now. But instead of that number in the title bar changing 60 times per second, which is how many times Update() get's called per second (UPS), it checks to see if a second in time has passed, and if so, updates the title bar. Nothing more, nothing less. I can't stress that enough. It has absolutely NOTHING to do with the actual game loop. tongue.png

 

I used Pokemon as more of an example of the display I was going for, with a kind of top down approach with a full 2D world, and not a 2D side scroller. I have no intentions of emulating Pokemon gameplay at all, but at the time, that was the first game that popped into my head to use as an example of the type of display I was looking for. I should have said, not a 2D side scroller, but a 2D tile based world. 

 

GafferonGames' link is the only other link I used that I actually tried to implement the gameplay, but it almost seemed a little too complicated for a smaller indie title. Not only that, but I was having trouble trying to decipher the actual game loop in terms of FPS/UPS. Going for a time based Update() is my goal here, I guess i'm just implementing it wrong. I'll have to look over it again, for a third day in a row, and see if I can grasp it any better than I previously had. One question about this article though, is the integrate() function basically the Update() function i'm trying to use? Keep in mind, my game logic hasn't really been born yet, which is why I don't even pass a gameTime variable into Update(). It will eventually, but like I said, I need to get the main game loop running in a way I'm happy with and know it SHOULD run about the same on MOST systems first.


PARTNERS