SFML community forums
Help => Window => Topic started by: tntexplosivesltd on December 27, 2010, 06:10:17 am
-
I have a bit of a problem, stemming from this code:
while (App->IsOpened())
{
sf::Sleep(0.001);
// Process all "application" events
sf::Event Event;
while (App->GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App->Close();
// Escape key : exit
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
App->Close();
// Resize event : adjust viewport
if (Event.Type == sf::Event::Resized)
glViewport(0, 0, Event.Size.Width, Event.Size.Height);
/*
if (Event.Key.Code == sf::Key::F1)
{
sf::Image Screen = App->Capture();
Screen.SaveToFile("screenshot.jpg");
}
*/
}
cout << "" << 1/App->GetFrameTime() << endl;
moving = false;
// adjust x- y- and z- step amounts based on current direction/view rotation
xStep = playerSpeed * sin((PI * zRotation) / 180);
yStep = playerSpeed * cos((PI * zRotation) / 180);
zStep = -playerSpeed * sin((PI * rotation) / 180);
//cout << "zRot: " << zRotation << " rot: " << rotation << endl;
// process real-time input
if (Input.IsKeyDown(sf::Key::W)) // W = forwards
{
moving = true;
playerX -= (xStep * cos((PI * rotation) / 180));
playerY -= (yStep * cos((PI * rotation) / 180));
playerZ -= zStep;
}
if (Input.IsKeyDown(sf::Key::S)) // S = backwards
{
moving = true;
playerX += (xStep * cos((PI * rotation) / 180));
playerY += (yStep * cos((PI * rotation) / 180));
playerZ += zStep;
}
if (Input.IsKeyDown(sf::Key::A)) //A = strafe left
{
if ((moving = true))
{
xStep *= 0.707106;
yStep *= 0.707106;
}
playerX += yStep;
playerY -= xStep;
}
if (Input.IsKeyDown(sf::Key::D)) //D = strafe right
{
if ((moving = true))
{
xStep *= 0.707106;
yStep *= 0.707106;
}
playerX -= yStep;
playerY += xStep;
}
// Rotate view based on mouse movement
mouseDeltaX = Input.GetMouseX() - centreX;
mouseDeltaY = Input.GetMouseY() - centreY;
zRotation += (mouseDeltaX / 10);
rotation += (mouseDeltaY / 10);
//cout << "DeltaX: " << mouseDeltaX << " DeltaY: " << mouseDeltaY << endl;
// Z rotation normalisation - between 0 and 360
if (zRotation >= 360)
{
zRotation -= 360;
}
if (zRotation < 0)
{
zRotation += 360;
}
// X/Y rotation limits
if (rotation < -90)
{
rotation = -90;
}
if (rotation >= 90)
{
rotation = 90;
}
// Set the active window before using OpenGL commands
// It's useless here because active window is always the same,
// but don't forget it if you use multiple windows or controls
App->SetActive();
// color and depth buffer
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Rotate the view first
glRotatef(-90 + rotation, 1.f, 0.f, 0.f);
glRotatef(zRotation, 0.f, 0.f, 1.f);
// Then translate it
glTranslatef(playerX, playerY, playerZ);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCallList(ALL_CUBES);
glFlush();
App->Display();
App->SetCursorPosition(centreX, centreY);
}
return EXIT_SUCCESS;
}
What is happening is when I have the sf::Sleep(0.001) in there, the framerate drops to ~60FPS. When I comment it out, it shoots up to ~300-400FPS. Even if it's drawing only one block, the FPS is ~60FPS with sf::Sleep(0.001). This is weird.
Additionally, I still have the same problem listed in this thread (http://www.sfml-dev.org/forum/viewtopic.php?t=3753), with the mouse input.
So I have a few questions:
1) What is happening with the framerate varying so much?
2) What is the difference between Input.GetMouseX() and Event.MouseMoved.X?
-
1) What is happening with the framerate varying so much?
What's your OS?
2) What is the difference between Input.GetMouseX() and Event.MouseMoved.X?
There's none. The first one is always available, the second one is given when you receive a MouseMoved event.
-
I'm using Windows 7 32-bit, and Arch Linux X86_64, and getting the same problem on both operating systems :(
-
Thread schedulers in common OSes usually have a time quantum of approx. 16 ms (ie. once a thread goes to bed, it can only wake up after a minimum of 16 ms). And 16ms = 1/0.016 Hz = approx. 60Hz. That could be an explanation.
-
Okay, thanks.
I changed from Input.GetMouseX() to Event.MouseMove.X, and it hasn't changed how the mouse behaves under Windows 7, as outlined in my other thread. I put the sf::Sleep(0.005) in there because it seemed to fix it, but it drags the FPS down to ~60FPS. How can I fix this? Will it improve if I put the rendering in a thread on its own, and everything else in a second thread?
-
How can I fix this?
Seriously, I don't understand why you get these problems with mouse input.
But is it such a bad workaround? I mean, 60 FPS should be enough.
Will it improve if I put the rendering in a thread on its own, and everything else in a second thread?
I don't know, it depends on the origin of your problem. But you can try.
-
2) What is the difference between Input.GetMouseX() and Event.MouseMoved.X?
There's none. The first one is always available, the second one is given when you receive a MouseMoved event.
This is not true in SFML 1.6, because Input and Event aren't synchronized. So there are situations where Input.GetMouseX() is not equal to Event.MouseMoved.X.
-
This is not true in SFML 1.6, because Input and Event aren't synchronized. So there are situations where Input.GetMouseX() is not equal to Event.MouseMoved.X.
Right. However this is a detail, at worst sf::Input will get delayed by one frame. So it can't explain the problems that we're talking about.
-
Has anyone ever had this problem before? It seems a bit odd.
-
If you create a test program in a single file, I will happily compile and run it on my computer. Well, if you are using 1.6, that is...
-
Finally fixed it. I looked back at one of my previous snapshots and found that if I moved App->SetCursorPosition(centreX, centreY); from after App->Display(); to just before I take mouse input:
App->SetCursorPosition(centreX, centreY);
mouseDeltaX = Input.GetMouseX() - centreX;
mouseDeltaY = Input.GetMouseY() - centreY;
zRotation += (mouseDeltaX / 10);
rotation += (mouseDeltaY / 10);
it works fine. Yay!
On a side note, why does this change it?
-
I don't have an answer to your question, but I would suggest that you make the following changes to your program:
Move the cursor position/rotation stuff to the event loop, and only do the calculations if the cursor has moved.
Also, make the rotation speed independent of the application speed, by dividing the rotation amount by the frame delta time, instead of some constant.
Pseudo code:if( Event.Type == MouseMove )
{
if( centreX != Event.MouseMoved.X )
zRotation += (Event.MouseMoved.X - centreX) / frameTime;
if( centreY != Event.MouseMoved.Y )
rotation += (Event.MouseMoved.Y - centreY) / frameTime;
App->SetCursorPosition(centreX, centreY);
}
If you haven't already, I still think you should take a gander at that game loop article I linked to in the other thread.
Here is the link again for good measure: http://www.koonsolo.com/news/dewitters-gameloop/
You might enjoy it - I did!
Wonderful bedtime reading. :)
-
Okay thanks for that.
I tried scaling the mouse movement by the frame time, but the view moves less when the frame rate is lower. Not sure if this is expected?
-
Um, no. Ignore the frame time thing, that was just me not thinking clearly. Sorry :oops: