SFML community forums

Help => Window => Topic started by: dabo on September 15, 2008, 10:20:36 pm

Title: A time question
Post by: dabo on September 15, 2008, 10:20:36 pm
Hi, using the GetFrameTime() method correctly the hero in my game should move and jump the same no matter the FPS right? Right now he jumps higher in release mode than in debug mode. I'm suppose to use GetFrameTime() for every new calculation of the x- and y-positions of my hero right?

Haven't used time before as you can see :)
Title: Re: A time question
Post by: quasius on September 15, 2008, 11:51:45 pm
Quote from: "dabo"
Hi, using the GetFrameTime() method correctly the hero in my game should move and jump the same no matter the FPS right? Right now he jumps higher in release mode than in debug mode. I'm suppose to use GetFrameTime() for every new calculation of the x- and y-positions of my hero right?

Haven't used time before as you can see :)


If you're getting different action speeds based on FPS, you're doing something wrong.
Basically, every game action should have a "speed" in some reasonable units.  In the case of your hero, it might be in pixels per second.
Then each frame you'd simply multiply his speed times the number of seconds for that frame.  Make sense?
Title: A time question
Post by: Wizzard on September 16, 2008, 06:22:59 am
It works by moving the object by the frame time multiplied by how many pixels you want the object to move each second, or the speed.
The frame time being the measure of how long it took for a call to sf::Window::Display to occur since the last call of it.

Code: [Select]
float Offset  = App.GetFrameTime() * 128.f;
float OffsetX = 0.f;
float OffsetY = 0.f;

if (Input.IsKeyDown(sf::Key::Up))    OffsetY = -Offset;
if (Input.IsKeyDown(sf::Key::Left))  OffsetX = -Offset;
if (Input.IsKeyDown(sf::Key::Down))  OffsetY += Offset;
if (Input.IsKeyDown(sf::Key::Right)) OffsetX += Offset;

View.Move(OffsetX, OffsetY);


This way, if a frame is rendered in one second (1 FPS), the object will move exactly one times the speed of your object every loop.
However, if a frame is rendered every 1/4 of a second (4 FPS), the object will move 1/4 the pixels every loop.
Title: A time question
Post by: dabo on September 16, 2008, 06:37:43 pm
Ok, thanks. I'm gonna try to figure out what I'm doing wrong.

Another thing, right now I'm not limiting the FPS (I get ~800 in release mode), what is a reasonably limit? I tried 30 and 60 but the movements don't seem that smooth.
Title: A time question
Post by: Wizzard on September 16, 2008, 07:57:01 pm
Try using...
Code: [Select]
App.UseVerticalSync(true);

... instead of a direct FPS limit.
Title: A time question
Post by: dabo on September 16, 2008, 08:29:04 pm
I still get ~800fps in release mode. I remember Laurent saying you have to set so that you let the application choose if v-sync should be used or not (some graphic card setting I suppose). Too bad I don't know where.
Title: A time question
Post by: Dig on September 16, 2008, 11:22:54 pm
If you have an ATI card and have that annoying Catalyst Control Center in the system tray that has options for controlling vertical sync for DirectX and OpenGL applications.

Assuming you're on windows right clicking on the desktop a bringing up properties->settings->advanced sometimes includes additional tab specific to your video card which should have those options.

No doubt nVidia has something similar.  For other graphics cards I'm not sure.
Title: A time question
Post by: dabo on September 17, 2008, 06:37:54 pm
http://www.intel.com/support/graphics/sb/CS-004692.htm
(Mobile IntelĀ® 945GM Express Chipset Family)

Here it says how to turn v-sync off, doing the opposite doesn't make a difference. I see no setting to let the application choose.
Title: A time question
Post by: Wizzard on September 17, 2008, 07:08:19 pm
I doubt he is running at ~800 Hz. :?
Title: A time question
Post by: dabo on September 18, 2008, 05:45:37 pm
What?

I'm gonna show you my code after I've done some more testing. Still got the time problem.
Title: A time question
Post by: quasius on September 19, 2008, 12:25:47 am
Quote from: "Wizzard"
I doubt he is running at ~800 Hz. :?


I can easily get 1500+ FPS on my machine in  my engine if not much is going on.
Title: A time question
Post by: dabo on September 26, 2008, 08:05:03 pm
Ok, here is most of my code (left out the unnecessary code, collision checking etc.), why isen't this fps-independent?

Code: [Select]
#define MAX_FORCE 2.05
#define BLOCK_SIZE 32

int main()
{
sf::RenderWindow Game(sf::VideoMode(640, 480), "Platform");

sf::Event Event;

sf::Image imgPlr;
if(!imgPlr.LoadFromFile("./data/block.png"))
return EXIT_FAILURE;

imgPlr.SetSmooth(false);

sf::Sprite sprPlr(imgPlr, sf::Vector2f(128.f, 64.f));

bool jumping = false;
bool standing = false;
float x = 128.f;
float y = 64.f;
float force = 0.f;
float frameRate;
float gravity = 3.14f;
float offset = 0.f;

while(Game.IsOpened())
{
Game.Clear();

while(Game.GetEvent(Event))
{
switch(Event.Type)
{
case sf::Event::KeyPressed:
if(Event.Key.Code == sf::Key::Escape)
Game.Close();
}
}

frameRate = Game.GetFrameTime();

const sf::Input& Input = Game.GetInput();

if(Input.IsKeyDown(sf::Key::Left))
x -= 60 * frameRate;

if(Input.IsKeyDown(sf::Key::Right))
x += 60 * frameRate;

if(Input.IsKeyDown(sf::Key::X) && !jumping && standing)
{
jumping = true;
standing = false;
force = -2.f;
}
else
{
if(!standing)
force += gravity * frameRate;

if(force > MAX_FORCE)
force = MAX_FORCE;
      }

      y += force - offset;

sprPlr.SetPosition(x, y);

Game.Draw(sprPlr);

Game.Display();
}

return EXIT_SUCCESS;
}
Title: A time question
Post by: quasius on September 26, 2008, 08:09:04 pm
Quote from: "dabo"
Ok, here is most of my code (left out the unnecessary code, collision checking etc.), why isen't this fps-independent?


From a quick look, probably because you're not multiplying all relevant variables by the frame time.  You have the right idea of calculating movement variables, but you missed one.  Look again...  :wink:
Title: A time question
Post by: dabo on September 26, 2008, 08:54:48 pm
I have always thought that you multiply with the frame time when you use the old value to get the new one, for example using operators:

Code: [Select]
+= -=
I don't think I need it here (called only once at the beginning of a jump):
Code: [Select]
force = -2.f;
...beacuse later:
Code: [Select]
y += force - offset;
...I move the player up 2 (offset = 0), and then it will be increased using the frame time:
Code: [Select]
force += gravity * frameRate;

I've tried a bunch of different stuff but can't figure it out.
Title: A time question
Post by: dabo on October 01, 2008, 01:02:13 pm
Anyone?
Title: A time question
Post by: zarka on October 01, 2008, 04:21:45 pm
have your tried to multiply this line by frametime as well ?
Code: [Select]
y += force - offset;

might solve it (not that i have look deeply into your code yet but if that doesn't work i will try to do that)
Title: A time question
Post by: dabo on October 01, 2008, 05:29:11 pm
Didn't work. the variable force has already been multiplied with the frame time when we get to that line of code.

Code: [Select]
if(!standing)
force += gravity * frameRate;
Title: A time question
Post by: zarka on October 01, 2008, 06:12:05 pm
Quote from: "dabo"
Didn't work. the variable force has already been multiplied with the frame time when we get to that line of code.

Code: [Select]
if(!standing)
force += gravity * frameRate;


strange... oh well i'm heading home from work now i will see if i can have a look at it when i get home ...
Title: A time question
Post by: dabo on October 01, 2008, 09:43:37 pm
ok, thanks.
Title: A time question
Post by: zarka on October 08, 2008, 08:12:38 pm
i don't know if you fixed this alredy but i finaly managed to remember to check this whan i was home and able to :)..
The problem is as others have pointed out this row:
Code: [Select]
y += force - offset;

The reason is that your MAX_FORCE constant is not time based .. meaning that when your force reaches MAX_FORCE it will be frame rate depandant and not frame time depandant as you whant it to be :)

so heres a solution:
Code: [Select]

//change it to a static const to keep c++ typesafety
static const float MAX_FORCE = 205.f;
...
//gravity should realy be a constant :)
const float gravity = 31.4f;
...
//and here we make sure it is kept time based
y += (force - offset) * frameRate;


now this should work fine :)