SFML community forums

Help => Window => Topic started by: tntexplosivesltd on December 15, 2010, 12:33:05 am

Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 15, 2010, 12:33:05 am
I have written some movement code for SFML 1.6 as follows:
Code: [Select]

while (App.IsOpened())
    {
        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);
        App.SetCursorPosition(centreX, centreY);


I then use OpenGL to rotate and translate blah, but that's not important.

Now, in Arch Linux x86_64 (with X11 and XFCE), this works fine. The view rotates fine.
In Windows (Windows 7 32-bit), it's a different story. The view hardly moves with the same mouse movements. It's so annoying! However, the keyboard movement is exactly the same.

What's going on?
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 15, 2010, 02:44:50 am
Fixed it somewhat. Added sf::Sleep(0.005) to the mail game loop, but this does expectedly lower the framerate. Is there a better way to give the inputs a chance to register, but keep a higher framerate?
Title: sf::Input.GetMouseX() and Y()
Post by: Laurent on December 15, 2010, 08:02:55 am
Where do you call GetEvent?
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 16, 2010, 08:06:56 am
I call it just after creating my sf::RenderWindow() object (outside the game loop). I tried moving it to the main loop, but it didn't help out.
Title: sf::Input.GetMouseX() and Y()
Post by: Laurent on December 16, 2010, 08:38:32 am
Can you show your complete code please?
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 17, 2010, 10:21:56 am
Complete code? Here we go...
(keep in mind it's not finished/optimised yet, and I'm relatively new to C++ and SFML)
Code: [Select]

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>

#define ALL_CUBES 1
using namespace std;

////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////

class Block
{
    public:
        int x, y, z, size;
        Block(int blockSize, int xCoord, int yCoord, int zCoord) {x = xCoord; y=yCoord; z=zCoord; size = blockSize; }
};

//DrawCube - creates 6 face polygons, with size and position arguments
void DrawCube(float size, float xOffset, float yOffset, float zOffset)
{
    size = size / 2;
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glBegin(GL_QUADS);
        glEdgeFlag(GL_TRUE);

        glColor3f(((xOffset/16+10)/20), ((yOffset/16+10)/20), ((zOffset/16+10)/20));

        glVertex3f(-size + xOffset, -size + yOffset, -size + zOffset);
        glVertex3f(-size + xOffset,  size + yOffset, -size + zOffset);
        glVertex3f( size + xOffset,  size + yOffset, -size + zOffset);
        glVertex3f( size + xOffset, -size + yOffset, -size + zOffset);

        glVertex3f(-size + xOffset, -size + yOffset, size + zOffset);
        glVertex3f(-size + xOffset,  size + yOffset, size + zOffset);
        glVertex3f( size + xOffset,  size + yOffset, size + zOffset);
        glVertex3f( size + xOffset, -size + yOffset, size + zOffset);

        glVertex3f(-size + xOffset, -size + yOffset, -size + zOffset);
        glVertex3f(-size + xOffset,  size + yOffset, -size + zOffset);
        glVertex3f(-size + xOffset,  size + yOffset,  size + zOffset);
        glVertex3f(-size + xOffset, -size + yOffset,  size + zOffset);

        glVertex3f(size + xOffset, -size + yOffset, -size + zOffset);
        glVertex3f(size + xOffset,  size + yOffset, -size + zOffset);
        glVertex3f(size + xOffset,  size + yOffset,  size + zOffset);
        glVertex3f(size + xOffset, -size + yOffset,  size + zOffset);

        glVertex3f(-size + xOffset, -size + yOffset,  size + zOffset);
        glVertex3f(-size + xOffset, -size + yOffset, -size + zOffset);
        glVertex3f( size + xOffset, -size + yOffset, -size + zOffset);
        glVertex3f( size + xOffset, -size + yOffset,  size + zOffset);

        glVertex3f(-size + xOffset, size + yOffset,  size + zOffset);
        glVertex3f(-size + xOffset, size + yOffset, -size + zOffset);
        glVertex3f( size + xOffset, size + yOffset, -size + zOffset);
        glVertex3f( size + xOffset, size + yOffset,  size + zOffset);
    glEnd();
}
int main()
{
    bool moving = false;
    //up/down rotation
    float rotation = 0;
    //horizintal rotation
    float zRotation = 0;

    //player movement variables - need to make into player class - maybe
    float playerSpeed = 1;
    float playerX = 0;
    float playerY = 0;
    float playerZ = 0;
    float xStep = 0;
    float yStep = 0;
    float zStep = 0;

    float mouseDeltaX = 0;
    float mouseDeltaY = 0;

    int mousePrevX;
    int mousePrevY;

    //PI
    const float PI = 3.14159265358979323846264338329750288419716939937510582;

    //settings for OpenGL rendering context
    sf::WindowSettings Settings;
    Settings.DepthBits         = 24; // Request a 24 bits depth buffer
    Settings.StencilBits       = 8;  // Request a 8 bits stencil buffer
    Settings.AntialiasingLevel = 8;  // Request 8 levels of antialiasing

    // Create the main window and appropriate variables
    sf::VideoMode bestMode = sf::VideoMode::GetMode(0);
    int bestWidth = bestMode.Width;
    int bestHeight = bestMode.Height;
    int centreX = bestWidth / 2;
    int centreY = bestHeight / 2;

    Block * allBlocks[8000];

    sf::RenderWindow * App = new sf::RenderWindow(sf::VideoMode(bestWidth, bestHeight, 32), "Rendering Test", sf::Style::Fullscreen, Settings); //, sf::Style::Fullscreen

    // Hide the cursor
    App->ShowMouseCursor(false);
    //App->SetFramerateLimit(200);

    // real-time input handler
    //const sf::Input& Input = App->GetInput();

    // Set color and depth clear value
    glShadeModel(GL_SMOOTH);
    // Colours and depths to clear to
    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.3f, 0.f);


    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.f, 1.f, -1.f, 1.f, 1.5f, 10000.f);
    glViewport (0, 0, bestWidth, bestHeight);

    // DisplayList for cubes
    int iterator = 0;
    for (int i = -10; i < 10;i++)
    {
        for (int j = -10; j < 10; j++)
        {
            for (int k = -10; k < 10; k++)
            {
                allBlocks[iterator] = new Block(16, i*60, j*60, k*60);
                iterator++;
            }
        }
    }

    glNewList(ALL_CUBES, GL_COMPILE);
    for (int i = 0; i < 8000; i++)
    {
        DrawCube(allBlocks[i]->size, allBlocks[i]->x, allBlocks[i]->y, allBlocks[i]->z);
        //cout << "" << allBlocks[i]->size << " " << allBlocks[i]->x << " " << allBlocks[i]->y << " " << allBlocks[i]->z << endl;
        delete allBlocks[i];
    }
    glEndList();


    //cout << "zRot: " << zRotation << " rot: " << rotation << endl;
    // Start game loop
    while (App->IsOpened())
    {
        const sf::Input& Input = App->GetInput();
        //sf::Sleep(0.005);
        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;
        }

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

        // 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;
}
Title: sf::Input.GetMouseX() and Y()
Post by: Laurent on December 17, 2010, 10:45:30 am
Try moving your event loop atthe beginning of your main loop.

Then, what does "The view hardly moves with the same mouse movements" mean exactly? What framerate do you have?
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 17, 2010, 10:50:42 am
Quote from: "Laurent"
Try moving your event loop at the beginning of your main loop.

Hasn't worked :(

Quote from: "Laurent"

Then, what does "The view hardly moves with the same mouse movements" mean exactly? What framerate do you have?

In Linux, if I move the mouse say 5cm, the view on screen moves as expected in the window.
However, in Windows, for the same 5cm mouse movement, the view moves a much smaller amount, and in jumps. The framerate stays relatively constant. (~300-400 FPS)
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 18, 2010, 09:50:57 am
Any ideas? I don't want to be limited to 200FPS. Also, if I set the framerate limit, the problem persists.
Title: sf::Input.GetMouseX() and Y()
Post by: Terrydil on December 18, 2010, 04:32:57 pm
This is slightly off-topic as it doesn't relate to fixing your problem, so feel free to ignore...

But am I missing something about framerates?  Why would you not want to be limited to 200fps?  I keep seeing stuff like "I need more than 400 fps".  Do you just hate having idle cpu time?   Visually you can't tell the difference right?  Just curious if there was some other reason.  :)
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 19, 2010, 07:44:12 am
Well, if someone has an older computer, I don't want them to have the 5ms pause because it will introduce more lag for the computer, i.e. I want the game to be able to run as fast as possible on any computer, without any built-in pauses.
Title: sf::Input.GetMouseX() and Y()
Post by: Hiura on December 19, 2010, 12:17:56 pm
Well, if you use sf::Window::SetFrameLimit(60), it won't "pause" your app unless it runs fast enough to have 60fps (ie. if your computer is slow and you only get 50fps you won't have any sleep function call). So there's no need of 400fps on one's computer to run at 60fps on another pc.

(Moreover it's illogical.)
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 19, 2010, 10:14:21 pm
That is true, but using sf::Window::SetFrameLimit(60) doesn't fix my problem :(
Title: sf::Input.GetMouseX() and Y()
Post by: tntexplosivesltd on December 20, 2010, 10:33:44 am
I'll just use sf::Sleep(0.005). It gives the CPU(s) some idle time, and basically fixes my problem.
Title: sf::Input.GetMouseX() and Y()
Post by: Terrydil on December 20, 2010, 02:38:36 pm
If it works it might not be worth messing with anymore, but do you get roughly the same values from GetMouseX/Y with similar movements on both Linux and Windows?
Title: sf::Input.GetMouseX() and Y()
Post by: model76 on December 21, 2010, 03:31:38 am
If it works, it works. Or does it?

I recommend you take a step back and examine the intricacies of the game loop. Here is a good article:
http://www.koonsolo.com/news/dewitters-gameloop/

 :)