SFML community forums
Help => Window => Topic started 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 :)
-
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?
-
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.
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.
-
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.
-
Try using...
App.UseVerticalSync(true);
... instead of a direct FPS limit.
-
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.
-
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.
-
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.
-
I doubt he is running at ~800 Hz. :?
-
What?
I'm gonna show you my code after I've done some more testing. Still got the time problem.
-
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.
-
Ok, here is most of my code (left out the unnecessary code, collision checking etc.), why isen't this fps-independent?
#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;
}
-
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:
-
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:
+= -=
I don't think I need it here (called only once at the beginning of a jump):
force = -2.f;
...beacuse later:
y += force - offset;
...I move the player up 2 (offset = 0), and then it will be increased using the frame time:
force += gravity * frameRate;
I've tried a bunch of different stuff but can't figure it out.
-
Anyone?
-
have your tried to multiply this line by frametime as well ?
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)
-
Didn't work. the variable force has already been multiplied with the frame time when we get to that line of code.
if(!standing)
force += gravity * frameRate;
-
Didn't work. the variable force has already been multiplied with the frame time when we get to that line of code.
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 ...
-
ok, thanks.
-
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:
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:
//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 :)