SFML community forums

Help => Graphics => Topic started by: wh1t3crayon on November 20, 2014, 06:47:01 pm

Title: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 20, 2014, 06:47:01 pm
I'm trying to use relative mouse movement to move a sprite around the screen, but I'm having trouble. The sprite doesn't move until I move the mouse completely off the screen, but only because this movement breaks the loop of Event::MouseMoved. Here is the event code:
while(window.pollEvent(event)){
                if(event.type == sf::Event::Closed){
                        window.close();
                }
                if(event.type == sf::Event::MouseMoved){
                        sf::Vector2f mouseOffsetOrigin = static_cast<sf::Vector2f>(sf::Mouse::getPosition(window));
                        float mouseOffsetX, mouseOffsetY;
                        mouseOffsetX = sf::Mouse::getPosition(window).x - mouseOffsetOrigin.x;
                        mouseOffsetY = sf::Mouse::getPosition(window).y - mouseOffsetOrigin.y;
//flashlight is a sprite
                        board.GetFlashlight().move(mouseOffsetX, mouseOffsetY);
//keep the mouse in the center of the screen
                        sf::Mouse::setPosition(sf::Vector2i(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2), window);
                }
                if(event.key.code == sf::Keyboard::Escape){
                        window.close();
                }

The code is pretty simple I think, but it's not working properly because the event loop never breaks out.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 20, 2014, 06:55:20 pm
The simple solution is to do it outside the event loop. Since your code doesn't use the event data at all, this shouldn't be hard. Just move this block of code outside the event loop.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 20, 2014, 07:10:52 pm
Changing the if statement to
if(sf::Event::MouseMoved)
and putting the statement just outside my while loop still causes a weird bug. The sprite only moves at random times, not smoothly with the mouse movements, and the movements look rather jolty. I've searched but can't find a post that tells how to deal with and use relative mouse movement.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Gambit on November 20, 2014, 07:12:54 pm
Why would you change the if statement to that? sf::Event::MouseMoved is valid, therefore the condition is always true and the statement will always execute. Do you mean
Code: [Select]
if (event.type == sf::Event::MouseMoved)?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 20, 2014, 07:18:52 pm
Yes that's what I meant, but it doesn't make a difference. The sprite still only moves randomly. Is there a problem with how I'm calculating the mouse delta?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Gambit on November 20, 2014, 07:21:50 pm
Why dont you use sf::Mouse instead? That way you have the mouse position in real time.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 20, 2014, 07:36:54 pm
If you put this code outside the event loop, obviously you musn't test the event (it's not valid outside the event loop). Just do it every frame, even when the mouse doesn't move.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Hapax on November 20, 2014, 07:57:29 pm
One other thing that should be done here is to confirm that the event type is a keypress event before testing its keycode; when the event is not a keyboard event, event.key.code should not be accessed.

Mini-question: why, since you made mouseOffsetOrigin an sf::Vector2f, did you not make mouseOffset one, instead opting for two separate floats that create more code (in this case)?  :P
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 20, 2014, 08:12:40 pm
If you put this code outside the event loop, obviously you musn't test the event (it's not valid outside the event loop). Just do it every frame, even when the mouse doesn't move.
Even when running the above code every frame, without the if statement, the bug is still there. I'm sure it has more to do with logic and less to do with sfml, but I'm still confused.

Hapax, I'll include your ideas so thanks for that, but I'm more concerned about getting this sprite to move first :P
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 20, 2014, 08:25:48 pm
Can you show the new code?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 20, 2014, 08:29:05 pm
void Engine::Process(){
        while(window.pollEvent(event)){
                if(event.type == sf::Event::Closed){
                        window.close();
                }
                if(event.key.code == sf::Keyboard::Escape){
                        window.close();
                }
        }

        //create a .01 by .01 position of mouse used for checking for float rect collisions
        sf::FloatRect mousefr(sf::Mouse::getPosition(window).x, sf::Mouse::getPosition(window).y, .01f, .01f);
        if(screen.intersects(mousefr)){
                if(board.GetMouseIn() == false){
                        sf::FloatRect mouseTestfr(WALL_SIZE, WALL_SIZE, SCREEN_WIDTH - WALL_SIZE * 2, SCREEN_HEIGHT - WALL_SIZE * 2);
                        if(mouseTestfr.intersects(mousefr)){
                                board.SetMouseIn(true);
                        }
                }
                if(board.GetMouseIn() == true){
                       
                        //get mouse coords, calculate offset of mouse movement, move flashlight by that much
                        sf::Vector2f mouseOffsetOrigin = static_cast<sf::Vector2f>(sf::Mouse::getPosition(window));
                        sf::Vector2f mouseOffset(sf::Mouse::getPosition(window).x - mouseOffsetOrigin.x, sf::Mouse::getPosition(window).y - mouseOffsetOrigin.y);
                        board.GetFlashlight().move(mouseOffset.x, mouseOffset.y);
                        sf::Mouse::setPosition(sf::Vector2i(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2), window);
That's everything possibly relevant in my process input function
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 20, 2014, 08:39:03 pm
And what's the problem with this code? Obviously it can't be the initial problem (stuck in event loop) ;)
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 21, 2014, 02:26:57 pm
I'll try and explain my goal first and then explain what is happening. A video may be needed :-\ So, in theory, I will move the mouse, which will be centered in the screen, and the sprite moves based on how much the mouse moves from the center. After this calculation, I place the mouse at the center for the next loop. But instead the sprite only moves at random intervals whenever I move the mouse, but mostly the sprite doesn't even move, regardless of how fast or slow I move the mouse.

Update: It became even more confusing. I set the mouse to only recenter itself after every 100 ticks, which gives the mouse a solid two seconds to calculate its offset and have the flashlight move. But the issue still remains, which shows that it's not being caused by the function for retrieving mouse coordinates being too slow, which was my first guess.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 21, 2014, 05:52:53 pm
You should write from scratch a very simple code that only does this (moves a sprite depending on mouse delta), there's too much unrelated stuff in your original code for you (or us) to spot the error.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 21, 2014, 10:15:01 pm
sf::RenderWindow window;
                        window.create(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32), "Test");
                        sf::Vector2i mouseOffsetOrigin = sf::Vector2i(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
                        sf::Vector2f mouseOffset(std::ceil(sf::Mouse::getPosition(window).x - mouseOffsetOrigin.x), std::ceil(sf::Mouse::getPosition(window).y -                                                                        mouseOffsetOrigin.y));
                        sf::Texture texture;
                        texture.loadFromFile("example.png");
                        sf::Sprite sprite(texture);
                        while(true){
                                sprite.move(mouseOffset.x, mouseOffset.y);
                                sf::Mouse::setPosition(mouseOffsetOrigin, window);
                window.clear();
                                window.draw(sprite);
                        }
I didn't test, but that should? compile in a main() function. Anyways, to reiterate, the sprite seems rather unresponsive. The sprite moves now at least (line 3 of my code was setting the origin to the mouse's current position, I fixed that to the screen's center), but the sprite seems to drift and is oversensitive. I know the problem has now gone from "bug with sf::Event" to "help me move my sprite smoothly" but it's still annoying to me. How can I move the sprite smoothly with the mouse opposed to its current jerkiness?

Edit: I just thought of a great metaphor to explain this "jerkiness." When I move my cursor onscreen outside my application, it stays in a pretty straight, coherent line. When I move my sprite in the program's window, the sprite looks like a really drunk version of the cursor that can't even walk a straight line :P
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 21, 2014, 10:54:20 pm
Your code has no event loop, which makes the window unresponsive and makes it very hard to close it, since the cursor is stuck in the center. I had to open the task manager to close it.

Then I have no idea what it's supposed to do, since mouseOffset is not never updated in the game loop.

So I wrote a version that works as expected (and can be closed more easily):

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");
    window.setMouseCursorVisible(false);

    sf::Vector2i center(window.getSize().x / 2, window.getSize().y / 2);

    sf::Texture texture;
    texture.loadFromFile("example.png");
    sf::Sprite sprite(texture);
    sprite.setPosition(sf::Vector2f(center));

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
                window.close();
        }

        sf::Vector2i offset = sf::Mouse::getPosition(window) - center;
        sprite.move(sf::Vector2f(offset));
        sf::Mouse::setPosition(center, window);

        window.clear();
        window.draw(sprite);
        window.display();
    }

    return EXIT_SUCCESS;
}
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Gambit on November 21, 2014, 11:56:40 pm
Thats not really a metaphor but instead an analogy. Furthermore, if you did not test the code, you did not read what Laurent said, or what the rules (which Laurent wrote) say: Complete and minimal code. If you did not test the code, its probablt not an extract from your current code, so it probably doesnt contain the problem. However, you are never updating the mouse position in the code your posted, so the sprite position will never change. Also, why are you setting the mouse position yourself? Thats probably the reason why your thing doesnt work.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 24, 2014, 04:09:00 am
Well my code did contain the problem, I made sure of that much. I was just trying to post quickly before I got off. Also, sorry about the no escape functionality, I forgot to include that in the post.

Anyways, I hate to say this but your posted code doesn't seem to work either. The sprite sort of jumps around the screen in the general direction the mouse is moving, at a very fast rate as well, then after a time it zooms off screen in the last direction the mouse was moving, never to be seen again. It's just weird at this point. When you ran the code you posted, was the sprite even a little bit oversensitive to the mouse movements, or is this just me?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 24, 2014, 07:54:07 am
My code worked exactly as expected on my computer.

Do other SFML apps (like the SDK examples) work fine on your PC?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 24, 2014, 02:37:29 pm
Yes, the opengl example (with the box that follows the cursor) works just fine. Of course, that is simply following the cursor around while my code moves the sprite based on deltas, so perhaps the issue is how I'm calculating the deltas. I would have the code simply follow the cursor except I'm creating a maze for the user, and the mouse can easily bypass the maze walls when checking for collision due to its speed, so that's why I constantly set it to the center.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 24, 2014, 02:46:07 pm
Quote
so perhaps the issue is how I'm calculating the deltas
This is very unlikely, since my code doesn't work for you either.

Could you test my code with a framerate limit of 60?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 24, 2014, 02:51:40 pm
Yeah, setting the framerate helped some. I can say that I have control over the sprite, but getting it to move in a straight line if I move the mouse in a straight line is almost impossible.
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: Laurent on November 24, 2014, 02:55:14 pm
What do you mean? The movement is not smooth, or the direction is sometimes wrong?
Title: Re: Stuck in event loop when using Event::MouseMoved
Post by: wh1t3crayon on November 24, 2014, 06:22:50 pm
Sorry, I mean that the movement isn't smooth. A movement that would move my cursor maybe 5 pixels moves the sprite 9 or 10 pixels plus a little left or a little right, so slight movements left or right give the sprite a shaky appearence when moving.


Edit:
sf::Vector2i mouseOffset(std::floor(sf::Mouse::getPosition(window).x - mouseOffsetOrigin.x), std::floor(sf::Mouse::getPosition(window).y -                                                                      mouseOffsetOrigin.y));
using std::floor to calculate the offset seems to be a decent workaround. I still wonder what caused the issue though