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

Author Topic: Taking the time control approach - questions  (Read 7023 times)

0 Members and 1 Guest are viewing this topic.

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« on: April 11, 2010, 05:43:33 am »
Okay, I've been trying to do this new approach rather than depending on FPS...  Here's a snippet of my player code.

Code: [Select]

#define PLAYER_SPEED 160.f
float MoveY = 0.f;
float MoveX = 0.f;
if (GetEventsControls.bDownKey) //Vert.
MoveY += PLAYER_SPEED;
else if (GetEventsControls.bUpKey)
MoveY -= PLAYER_SPEED;
if (GetEventsControls.bLeftKey) //Horiz.
MoveX -= PLAYER_SPEED;
else if (GetEventsControls.bRightKey)
MoveX += PLAYER_SPEED;
//Focus mode
if (GetEventsControls.bLshift)
{ MoveX /= 2;
MoveY /= 2;
}
MoveX = MoveX * App.GetFrameTime();
MoveY = MoveY * App.GetFrameTime();
game.playerHitX += (int)MoveX;
game.playerHitY += (int)MoveY;


Basically, with it right now, it SEEMS to be precise...  I have to multiply by 160 to get a result that actually moves...

The HitX and HitY is the center point of the player and it is drawn relative to that point.  The main problem, though, is I want this number to be an int always.

Is there anything better I can be doing with this or does this look acceptable?  Thanks!

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Taking the time control approach - questions
« Reply #1 on: April 11, 2010, 12:16:49 pm »
I think it's fine.

Here's the way I do it for a deterministic approach:
Code: [Select]
// time variables
float count = 0.f;
sf::Clock clock;

// --- game loop ---
while (App.IsOpened()){

   // --- process events ---
   (...)

   // --- update frames ---
   // each update is made within a frame time
   count += clock.GetElapsedTime();
   while (count>=FRAME_RATE){
      count -=FRAME_RATE;
      updateState(...);
   }

   // --- draw the game state ---
   drawEverything(...);
   App.Display();

   // --- makes the game sleep, releasing CPU usage ---
   // use elapsed time to know how much time is left
   // if it's too late to sleep, count remains unchanged to compensate the lag on the next game loop
   count += clock.GetElapsedTime();
   if (count < FRAME_RATE){
      sf::Sleep(FRAME_RATE - count); // sleep the remaining time
      count = FRAME_RATE;            // update count to the new time (end of frame)
   }

   clock.Reset();
}


Every update uses fixed values (for example for velocity), and the expected effect is that there is an update every frame. If for any reason the game lags and a loop on the main cycle takes more than the FRAME_RATE time, it means there are updates missing, so they are made in a row on the next cycle without being drawn. After those updates, the game state is drawn on the screen. If there is still time left, it's passed on sleeping, if not, the lack of time is propagated to the next cycle, forcing it to do more updates to compensate.

This is assuming that drawing is a while more time consuming than updates (as it uses to be), and they can be skipped between updates. If the game lags much it means the updates are taking too long.

This approach is also good to avoid updates taking unexpected values. Like for velocity on your approach, if the game lags, the velocity can take a big value because of the elapsed time, and as result the character can overpass a wall for instance. On this approach, changes always takes the expected values.



Edit: For a framerate of 60fps:
Code: [Select]
static const float FRAME_RATE = 0.0166666;
Pluma - Plug-in Management Framework

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #2 on: April 11, 2010, 05:22:40 pm »
What you're doing looks kinda like what I was originally trying, though a bit more sophisticated.

What does FRAME_RATE = in your example?

One thing I'm noticing is that with my new approach, things don't move a fixed number of pixels.  Like, I want the player to always move at a rate of 4 pixels, player shots at a rate of 12, etc.  Right now, the player goes between 4-5, mostly towards the 4.  The animation can look jittery because of the inconsistent movement rate...  I've been studying other games and they seem to have the rate locked.

I'll give your proposal a go.  Thanks.

JollyRoger

  • Newbie
  • *
  • Posts: 17
    • View Profile
Taking the time control approach - questions
« Reply #3 on: April 11, 2010, 05:52:32 pm »
I also had this problem myself with the inconsistent step size.  Gsaurus' approach was the best I found, and it works well.

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #4 on: April 11, 2010, 05:56:05 pm »
Okay, I've gone and tried this.  This is similar to the problem I had before where trying to get a frame rate of 60 makes it so the game doesn't run fast unless a lot of things are being updated.

FRAMERATE was set to 1.f/60.f

JollyRoger

  • Newbie
  • *
  • Posts: 17
    • View Profile
Taking the time control approach - questions
« Reply #5 on: April 11, 2010, 06:00:55 pm »
The FRAMERATE variable shouldn't matter.  That's the nice thing about this, it locks the frame rate to whatever you desire.  Can we see your new code?

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #6 on: April 11, 2010, 06:06:54 pm »
Sure...

Code: [Select]

#define FPSRATE 1.f/65.f  //It has to be this, otherwise the game runs at half speed.  It hates 60.f

...

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP, LOOP!!!!!!!!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float countor = 0.f;
sf::Clock clocky;
while (bGameGoing && App.IsOpened())
{ GameInputClass& playerInput = GameInputClass::GetInput(); //Keyboard recognized...
playerInput.GetGameplayKeys();
//Escape goes to exit
//-------------------------------------------------------------------------------------
if (playerInput.bEscKey)
{ bGameGoing = false;
gameState = 1;
}

countor += clocky.GetElapsedTime();
while (countor >= FPSRATE)
{ countor -= FPSRATE;
GameLogic();
}
GameRender();
countor += clocky.GetElapsedTime();
if (countor < FPSRATE)
{ sf::Sleep(FPSRATE - countor);
countor = FPSRATE;
}
clocky.Reset();
frameRate = 1.f / frameClock.GetElapsedTime();
frameClock.Reset();

//Wait to get a proper time in-between frames...
//-------------------------------------------------------------------------------------
}

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #7 on: April 12, 2010, 06:55:31 pm »
Hey all.  This still doesn't work.  I'm wondering if there are other possibilities than code, because I look at this code and I get what it should be doing.

These are my "other possibilities" thoughts:
-Can VC++ 2008 EXPRESS be the problem?  I've considered trying to get it compiled on a regular version, but this just seems unlikely.
-I made an "Empty Project" for the project type and not a Win32 console app.  Does this matter?
-Was the original code using a different version of SFML?

It's just annoying, to say the least.  Thanks.

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Taking the time control approach - questions
« Reply #8 on: April 12, 2010, 07:06:14 pm »
I have used this in SFML 1.4, 1.5 and 2
SFML version is not the problem.
Pluma - Plug-in Management Framework

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #9 on: April 12, 2010, 07:22:40 pm »
Hm.  I'll try going back to 1.5 and see if that helps...  Any thoughts on the Win32 console app part though?

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Taking the time control approach - questions
« Reply #10 on: April 12, 2010, 08:16:36 pm »
Maybe you should also use sf::Window::GetFrameTime() to lock your variables to the current frame rate.

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #11 on: April 12, 2010, 08:50:30 pm »
I'm out here at the University and their computer has a similar result...  It randomly was at 60.1 or 60.2, but it ONLY did this once.

Basically it is still thinking 60 = 32...

I'll try the proposed alternative approach when I get back.

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Taking the time control approach - questions
« Reply #12 on: April 12, 2010, 09:48:37 pm »
Quote from: "Sivak"
It randomly was at 60.1 or 60.2, but it ONLY did this once.

Basically it is still thinking 60 = 32...


So, you mean that you ran the application several times, and one time it was stable at around 60fps, and all other times it was stuck on 32fps?
Pluma - Plug-in Management Framework

Sivak

  • Jr. Member
  • **
  • Posts: 51
    • View Profile
Taking the time control approach - questions
« Reply #13 on: April 12, 2010, 10:18:34 pm »
Quote from: "gsaurus"
Quote from: "Sivak"
It randomly was at 60.1 or 60.2, but it ONLY did this once.

Basically it is still thinking 60 = 32...


So, you mean that you ran the application several times, and one time it was stable at around 60fps, and all other times it was stuck on 32fps?


Well, it wasn't fully stable.  It showed 60.1 but went to 56 at times...  And yeah, this was ONLY once.  I'm determined to get this work correctly all the time.

If any of you care to test this:  http://sivak.nintendoage.com/Shmuppy.zip

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Taking the time control approach - questions
« Reply #14 on: April 12, 2010, 10:45:25 pm »
The demo sometimes speeds up from 50 to 66 fps.

I suggest you to use sf::Window::GetFrameTime() to make all the speeds constant.