InputQueue

Bases: deque

Provides additional functionality beyond pygame.key.get_pressed(). Contains a series of ChannelTuples which represent the state history of the input device that this queue is tracking. This input history allows us to track which keys have been pressed and released this tick.

Subclasses should implement get_new_values.

Source code in robingame/input/queue.py
 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
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
class InputQueue(deque):
    """
    Provides additional functionality beyond pygame.key.get_pressed().
    Contains a series of ChannelTuples which represent the state history of the input device
    that this queue is tracking.
    This input history allows us to track which keys have been pressed and released this tick.

    Subclasses should implement `get_new_values`.
    """

    def __init__(self, queue_length=5):
        super().__init__(maxlen=queue_length)

    def get_new_values(self) -> ChannelTuple:
        """
        Subclasses should implement this.
        It should be something like pygame.key.get_pressed().

        Returns:
            a tuple of integers representing the states of the input channels
        """
        raise NotImplementedError

    def read_new_inputs(self):
        self.append(self.get_new_values())

    def get_down(self) -> ChannelTuple:
        """
        Return the keys which are currently held down.

        Returns:
            a tuple of values for each input channel. 0 = not down. Nonzero = down.
        """
        return self[-1] if len(self) > 0 else Empty()

    def get_pressed(self) -> ChannelTuple:
        """
        Return the keys that have just been pressed
        i.e. those that are down this tick but not the previous tick

        Returns:
            a tuple of integers for each input channel. 1 = pressed, 0 = not pressed.
        """
        try:
            current = self[-1]
            previous = self[-2]
            # we HAVE to use the __getattr__ method of the ScancodeWrapper
            # here. Using for/in to iterate over it gives erroneous results!
            # That's why I'm using the index to get the values.
            return tuple(
                int(current[i] and not previous[i])
                for (i, c), p in zip(enumerate(current), previous)
            )
        except IndexError:
            return Empty()

    def get_released(self) -> ChannelTuple:
        """
        Return the keys that have just been released
        i.e. those that are not down this tick, but were down the previous tick.

        Returns:
            a tuple of integers for each input channel. 1 = released, 0 = not released.
        """
        try:
            current = self[-1]
            previous = self[-2]
            return tuple(
                int(previous[i] and not current[i])
                for (i, c), p in zip(enumerate(current), previous)
            )
        except IndexError:
            return Empty()

    def is_pressed(self, key) -> int:
        """
        Check if a key has been pressed this tick

        Returns:
            1 if pressed; 0 otherwise
        """
        keys = self.get_pressed()
        return keys[key]

    def is_down(self, key) -> int:
        """
        Check if a key is currently held down

        Returns:
            1 if down; 0 otherwise
        """
        keys = self.get_down()
        return keys[key]

    def is_released(self, key) -> int:
        """
        Check if a key has been released this tick

        Returns:
            1 if released; 0 otherwise
        """
        keys = self.get_released()
        return keys[key]

    def buffered_inputs(self, key: int, buffer_length: int) -> tuple[int, int]:
        """
        Count the rising and falling edges. Can be used to detect past inputs.

        Args:
            key: identifier of the input channel
            buffer_length: how many past iterations to consider

        Returns:
            number of times the input channel has been pressed and released over the `buffer_length`
        """
        buffer = list(self)[-buffer_length:]
        values = [layer[key] for layer in buffer]
        return count_edges(values)

    def buffered_presses(self, key, buffer_length):
        rising, falling = self.buffered_inputs(key, buffer_length)
        return rising

    def buffered_releases(self, key, buffer_length):
        rising, falling = self.buffered_inputs(key, buffer_length)
        return falling

buffered_inputs(key, buffer_length)

Count the rising and falling edges. Can be used to detect past inputs.

Parameters:
  • key (int) –

    identifier of the input channel

  • buffer_length (int) –

    how many past iterations to consider

Returns:
  • tuple[int, int]

    number of times the input channel has been pressed and released over the buffer_length

robingame/input/queue.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
def buffered_inputs(self, key: int, buffer_length: int) -> tuple[int, int]:
    """
    Count the rising and falling edges. Can be used to detect past inputs.

    Args:
        key: identifier of the input channel
        buffer_length: how many past iterations to consider

    Returns:
        number of times the input channel has been pressed and released over the `buffer_length`
    """
    buffer = list(self)[-buffer_length:]
    values = [layer[key] for layer in buffer]
    return count_edges(values)

get_down()

Return the keys which are currently held down.

Returns:
  • ChannelTuple

    a tuple of values for each input channel. 0 = not down. Nonzero = down.

robingame/input/queue.py
51
52
53
54
55
56
57
58
def get_down(self) -> ChannelTuple:
    """
    Return the keys which are currently held down.

    Returns:
        a tuple of values for each input channel. 0 = not down. Nonzero = down.
    """
    return self[-1] if len(self) > 0 else Empty()

get_new_values()

Subclasses should implement this. It should be something like pygame.key.get_pressed().

Returns:
  • ChannelTuple

    a tuple of integers representing the states of the input channels

robingame/input/queue.py
38
39
40
41
42
43
44
45
46
def get_new_values(self) -> ChannelTuple:
    """
    Subclasses should implement this.
    It should be something like pygame.key.get_pressed().

    Returns:
        a tuple of integers representing the states of the input channels
    """
    raise NotImplementedError

get_pressed()

Return the keys that have just been pressed i.e. those that are down this tick but not the previous tick

Returns:
  • ChannelTuple

    a tuple of integers for each input channel. 1 = pressed, 0 = not pressed.

robingame/input/queue.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def get_pressed(self) -> ChannelTuple:
    """
    Return the keys that have just been pressed
    i.e. those that are down this tick but not the previous tick

    Returns:
        a tuple of integers for each input channel. 1 = pressed, 0 = not pressed.
    """
    try:
        current = self[-1]
        previous = self[-2]
        # we HAVE to use the __getattr__ method of the ScancodeWrapper
        # here. Using for/in to iterate over it gives erroneous results!
        # That's why I'm using the index to get the values.
        return tuple(
            int(current[i] and not previous[i])
            for (i, c), p in zip(enumerate(current), previous)
        )
    except IndexError:
        return Empty()

get_released()

Return the keys that have just been released i.e. those that are not down this tick, but were down the previous tick.

Returns:
  • ChannelTuple

    a tuple of integers for each input channel. 1 = released, 0 = not released.

robingame/input/queue.py
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
def get_released(self) -> ChannelTuple:
    """
    Return the keys that have just been released
    i.e. those that are not down this tick, but were down the previous tick.

    Returns:
        a tuple of integers for each input channel. 1 = released, 0 = not released.
    """
    try:
        current = self[-1]
        previous = self[-2]
        return tuple(
            int(previous[i] and not current[i])
            for (i, c), p in zip(enumerate(current), previous)
        )
    except IndexError:
        return Empty()

is_down(key)

Check if a key is currently held down

Returns:
  • int

    1 if down; 0 otherwise

robingame/input/queue.py
109
110
111
112
113
114
115
116
117
def is_down(self, key) -> int:
    """
    Check if a key is currently held down

    Returns:
        1 if down; 0 otherwise
    """
    keys = self.get_down()
    return keys[key]

is_pressed(key)

Check if a key has been pressed this tick

Returns:
  • int

    1 if pressed; 0 otherwise

robingame/input/queue.py
 99
100
101
102
103
104
105
106
107
def is_pressed(self, key) -> int:
    """
    Check if a key has been pressed this tick

    Returns:
        1 if pressed; 0 otherwise
    """
    keys = self.get_pressed()
    return keys[key]

is_released(key)

Check if a key has been released this tick

Returns:
  • int

    1 if released; 0 otherwise

robingame/input/queue.py
119
120
121
122
123
124
125
126
127
def is_released(self, key) -> int:
    """
    Check if a key has been released this tick

    Returns:
        1 if released; 0 otherwise
    """
    keys = self.get_released()
    return keys[key]