2023-05-11 14:01:02 -04:00
|
|
|
import pygame
|
2023-05-14 19:26:09 -04:00
|
|
|
from collections import deque
|
2023-05-13 10:48:59 -04:00
|
|
|
|
2023-05-11 14:01:02 -04:00
|
|
|
class InputHandler:
|
2023-05-11 15:31:36 -04:00
|
|
|
"""
|
|
|
|
Class that is implemented into surfaces in order to control the
|
|
|
|
pressing of buttons on both the real hardware and on a keyboard.
|
2023-05-12 11:20:00 -04:00
|
|
|
|
|
|
|
Attributes:
|
|
|
|
clock (pygame.time.Clock): Pygame clock used for input time calculations.
|
|
|
|
last_input_tick (int): The tick that the last input was registered on.
|
|
|
|
|
2023-05-11 15:31:36 -04:00
|
|
|
"""
|
|
|
|
|
2023-05-13 10:48:59 -04:00
|
|
|
def __init__(self, pygame_clock, tick_check=True):
|
2023-05-12 11:20:00 -04:00
|
|
|
"""
|
|
|
|
Create a InputHandler object using a given Pygame clock.
|
2023-05-11 15:31:36 -04:00
|
|
|
|
2023-05-12 11:20:00 -04:00
|
|
|
Args:
|
2023-05-13 10:48:59 -04:00
|
|
|
pygame_clock (:obj:`pygame.time.Clock`): A pygame clock to use as the clock for input time calculations.
|
|
|
|
tick_check (bool, optional): Bool to ignore inputs that happen to quickly after another. Defaults to True.
|
2023-05-11 15:31:36 -04:00
|
|
|
|
2023-05-12 11:20:00 -04:00
|
|
|
"""
|
|
|
|
self.clock = pygame_clock
|
2023-05-13 10:48:59 -04:00
|
|
|
self.tick_check = tick_check
|
2023-05-11 14:01:02 -04:00
|
|
|
self.last_input_tick = 0
|
2023-05-14 19:26:09 -04:00
|
|
|
self.dev_check = deque()
|
|
|
|
self.dev_code = deque()
|
|
|
|
for button in [pygame.K_DOWN, pygame.K_DOWN, pygame.K_UP, pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT,
|
|
|
|
pygame.K_RIGHT, pygame.K_LEFT, pygame.K_a]:
|
|
|
|
self.dev_code.append(button)
|
|
|
|
self.dev_found = False
|
2023-05-11 14:01:02 -04:00
|
|
|
|
|
|
|
def create_event(self, pressed_button):
|
|
|
|
"""
|
2023-05-12 11:20:00 -04:00
|
|
|
Create a pygame event given a GPIO code and post it to the pygame event handler.
|
|
|
|
Args:
|
|
|
|
pressed_button (int): The GPIO code to be registered and pressed.
|
|
|
|
|
2023-05-11 14:01:02 -04:00
|
|
|
"""
|
|
|
|
# Register a button click so long as the last button click happened no less than two frames ago
|
2023-05-13 10:48:59 -04:00
|
|
|
if self.tick_check:
|
|
|
|
if pygame.time.get_ticks() - self.last_input_tick > self.clock.get_time() * 2:
|
|
|
|
pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'key': pressed_button}))
|
|
|
|
pygame.event.post(pygame.event.Event(pygame.KEYUP, {'key': pressed_button}))
|
2023-05-14 19:26:09 -04:00
|
|
|
self.dev_check.append(pressed_button)
|
|
|
|
if len(self.dev_check) > len(self.dev_code):
|
|
|
|
self.dev_check.popleft()
|
2023-05-13 10:48:59 -04:00
|
|
|
else:
|
2023-05-11 14:01:02 -04:00
|
|
|
pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'key': pressed_button}))
|
|
|
|
pygame.event.post(pygame.event.Event(pygame.KEYUP, {'key': pressed_button}))
|
|
|
|
self.last_input_tick = pygame.time.get_ticks()
|
|
|
|
|
2023-05-12 11:20:00 -04:00
|
|
|
def handle_keyboard(self):
|
|
|
|
"""Handle keyboard presses and generate corresponding GPIO codes to create events."""
|
2023-05-11 14:01:02 -04:00
|
|
|
|
|
|
|
# Checks if a corresponding keyboard key has been pressed. If it has, emulate a button press.
|
|
|
|
for keyboard_event in pygame.event.get():
|
|
|
|
if keyboard_event.type == pygame.QUIT:
|
|
|
|
running = False
|
|
|
|
if keyboard_event.type == pygame.KEYDOWN:
|
|
|
|
if keyboard_event.key == pygame.K_a:
|
2023-05-13 10:46:34 -04:00
|
|
|
self.create_event(pygame.K_a)
|
2023-05-11 14:01:02 -04:00
|
|
|
if keyboard_event.key == pygame.K_b:
|
2023-05-13 10:46:34 -04:00
|
|
|
self.create_event(pygame.K_b)
|
|
|
|
if keyboard_event.key == pygame.K_KP_ENTER:
|
|
|
|
self.create_event(pygame.K_KP_ENTER)
|
2023-05-11 14:01:02 -04:00
|
|
|
if keyboard_event.key == pygame.K_RIGHT:
|
2023-05-13 10:46:34 -04:00
|
|
|
self.create_event(pygame.K_RIGHT)
|
2023-05-11 14:01:02 -04:00
|
|
|
if keyboard_event.key == pygame.K_LEFT:
|
2023-05-13 10:46:34 -04:00
|
|
|
self.create_event(pygame.K_LEFT)
|
2023-05-11 14:01:02 -04:00
|
|
|
if keyboard_event.key == pygame.K_DOWN:
|
2023-05-13 10:46:34 -04:00
|
|
|
self.create_event(pygame.K_DOWN)
|
2023-05-11 14:01:02 -04:00
|
|
|
if keyboard_event.key == pygame.K_UP:
|
2023-05-13 10:46:34 -04:00
|
|
|
self.create_event(pygame.K_UP)
|
2023-05-11 14:01:02 -04:00
|
|
|
if keyboard_event.key == pygame.K_ESCAPE:
|
|
|
|
running = False
|
|
|
|
|
|
|
|
def update(self):
|
2023-05-12 11:20:00 -04:00
|
|
|
"""Run either the GPIO handler or the keyboard handler to check for input and create events."""
|
2023-05-13 10:46:34 -04:00
|
|
|
self.handle_keyboard()
|
2023-05-14 19:26:09 -04:00
|
|
|
if self.dev_code == self.dev_check:
|
|
|
|
self.dev_found = True
|