SFML real time input issue

Does sf::Input work with a buffer internally? I'm asking because it looks like it's
supposed not to -> http://www.sfml-dev.org/documentation/1.6/classsf_1_1Input.php

When I repeatedly hit (press and release) a particular arrow
key fast, the circle keeps moving for a long while after I stop
touching the key. Is it only me or does this happen to you too?
I also put GetAsyncKeyState (which works fine) for comparison.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <SFML/Graphics.hpp>
#include <windows.h>

struct Direction { enum { UP = 0, LEFT = 1, DOWN = 2, RIGHT = 3 }; };

int main()
{
    const int window_width  = 400;
    const int window_height = 300;

    sf::RenderWindow window(sf::VideoMode(window_width, window_height, 32), "SFML test");
    window.UseVerticalSync(true);

    sf::Shape circle = sf::Shape::Circle(25, 25, 20, sf::Color::Yellow, 5, sf::Color::Blue);
    sf::Event Event;

    int xpos = 0;
    int ypos = 0;

    bool moved;
    int direction;

    while (window.IsOpened())
    {
        window.GetEvent(Event);

        if (Event.Type == sf::Event::Closed) window.Close();

        if (window.GetInput().IsKeyDown(sf::Key::Escape)) window.Close();

        moved = false;

        #if 1

        if (window.GetInput().IsKeyDown(sf::Key::Up   )) { moved = true; direction = Direction::UP;    }
        if (window.GetInput().IsKeyDown(sf::Key::Left )) { moved = true; direction = Direction::LEFT;  }
        if (window.GetInput().IsKeyDown(sf::Key::Down )) { moved = true; direction = Direction::DOWN;  }
        if (window.GetInput().IsKeyDown(sf::Key::Right)) { moved = true; direction = Direction::RIGHT; }

        #else

        if (GetAsyncKeyState(VK_UP   ) >> 15) { moved = true; direction = Direction::UP;    }
        if (GetAsyncKeyState(VK_LEFT ) >> 15) { moved = true; direction = Direction::LEFT;  }
        if (GetAsyncKeyState(VK_DOWN ) >> 15) { moved = true; direction = Direction::DOWN;  }
        if (GetAsyncKeyState(VK_RIGHT) >> 15) { moved = true; direction = Direction::RIGHT; }

        #endif

        if (moved)
        {
            int new_xpos = xpos;
            int new_ypos = ypos;

            switch (direction)
            {
                case Direction::UP:    --new_ypos; break;
                case Direction::LEFT:  --new_xpos; break;
                case Direction::DOWN:  ++new_ypos; break;
                case Direction::RIGHT: ++new_xpos; break;
            }

            const double animation_speed = 40;

            for (int i = 1; i < animation_speed; ++i)
            {
                circle.SetPosition
                (
                    (xpos + (new_xpos - xpos) * i / animation_speed) * 50,
                    (ypos + (new_ypos - ypos) * i / animation_speed) * 50
                );

                window.Clear(sf::Color::Black);
                window.Draw(circle);
                window.Display();
            }

            new_xpos += (window_width  / 50); new_xpos %= (window_width  / 50);
            new_ypos += (window_height / 50); new_ypos %= (window_height / 50);

            xpos = new_xpos;
            ypos = new_ypos;
        }

        circle.SetPosition(xpos * 50, ypos * 50);

        window.Clear(sf::Color::Black);
        window.Draw(circle);
        window.Display();
    }
}

EDIT: Erased some unnecessary code. Was there for reasons not needed here.
Last edited on
Ok, I got it working by removing the nested loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <SFML/Graphics.hpp>
#include <windows.h>

struct Direction { enum { UP = 0, LEFT = 1, DOWN = 2, RIGHT = 3 }; };

int main()
{
    const int window_width  = 400;
    const int window_height = 300;

    sf::RenderWindow window(sf::VideoMode(window_width, window_height, 32), "SFML test");
    window.UseVerticalSync(true);

    sf::Shape circle = sf::Shape::Circle(25, 25, 20, sf::Color::Yellow, 5, sf::Color::Blue);
    sf::Event Event;

    double  cur_xpos = 0,  cur_ypos = 0;
       int prev_xpos = 0, next_xpos = 0;
       int prev_ypos = 0, next_ypos = 0;

    const int max_animation_frame = 40;
          int cur_animation_frame;

    bool is_moving  = false;
    bool was_moving = false;

    int direction;

    while (window.IsOpened())
    {
        window.GetEvent(Event);

        if (Event.Type == sf::Event::Closed) window.Close();

        if (window.GetInput().IsKeyDown(sf::Key::Escape)) window.Close();

        was_moving = is_moving;

        if (!is_moving && window.GetInput().IsKeyDown(sf::Key::Up   )) { is_moving = true; direction = Direction::UP;    }
        if (!is_moving && window.GetInput().IsKeyDown(sf::Key::Left )) { is_moving = true; direction = Direction::LEFT;  }
        if (!is_moving && window.GetInput().IsKeyDown(sf::Key::Down )) { is_moving = true; direction = Direction::DOWN;  }
        if (!is_moving && window.GetInput().IsKeyDown(sf::Key::Right)) { is_moving = true; direction = Direction::RIGHT; }

        if (is_moving && !was_moving)
        {
            next_xpos = prev_xpos;
            next_ypos = prev_ypos;

            switch (direction)
            {
                case Direction::UP:    --next_ypos; break;
                case Direction::LEFT:  --next_xpos; break;
                case Direction::DOWN:  ++next_ypos; break;
                case Direction::RIGHT: ++next_xpos; break;
            }

            cur_animation_frame = 1;
        }

        if (is_moving)
        {
            cur_xpos = prev_xpos + (next_xpos - prev_xpos) * cur_animation_frame * 1. / max_animation_frame;
            cur_ypos = prev_ypos + (next_ypos - prev_ypos) * cur_animation_frame * 1. / max_animation_frame;

            if (++cur_animation_frame == max_animation_frame)
            {
                is_moving = false;

                prev_xpos = cur_xpos = (next_xpos + window_width  / 50) % (window_width  / 50);
                prev_ypos = cur_ypos = (next_ypos + window_height / 50) % (window_height / 50);
            }
        }

        circle.SetPosition(cur_xpos * 50, cur_ypos * 50);

        window.Clear(sf::Color::Black);
        window.Draw(circle);
        window.Display();
    }
}

Though, if anyone knows why the first approach doesn't work, I'd like to know. Peeking at SFML
source code wasn't really helpful... Input::IsKeyDown is implemented using GetAsyncKeyState.
Last edited on
Topic archived. No new replies allowed.