pygame.key.set_repeat для джойстика

Я создаю меню с помощью pygame и хочу сделать его доступным для навигации с помощью определенного геймпада. В идеале я хочу иметь возможность многократно нажимать и удерживать * «вниз» на крестовине или получить что-то вроде клавиатуры, где первое нажатие кнопки имеет задержку перед повторным вводом одного и того же символа (по-видимому).

Я пытаюсь эмулировать функцию pygame.key.set_repeat(...) для джойстика. мой подход до сих пор был

pygame.time.set_timer(pygame.USEREVENT, 10)
DELAY_TIME = 0.250 #ms
y_delay = True
while not done:
    for event in pygame.event.get():
        y_axis = gamepad.get_axis(1)
        if y_axis > 0.5: # pushing down
            main_menu.move_down()
            redraw() #redraw everything on the surface before sleeping
            if y_delay:
                time.sleep(DELAY_TIME)
                y_delay = False #don't delay the next time the y axis is used


        elif y_axis < -0.5: #pushing up
            # repetitive I know, but I'm still working on it
            main_menu.move_up()
            redraw()
            if y_delay: 
                time.sleep(DELAY_TIME)
                y_delay = False 

        else:
            y_delay = True # delay the next time

моя проблема в том, что если кто-то нажимает вверх или вниз быстрее, чем DELAY_TIME, он ограничивается DELAY_TIME, прежде чем снова сможет двигаться. Кроме того, если кто-то отпускает и нажимает кнопку вверх/вниз в интервале time.sleep, python никогда не увидит, что она вообще была отпущена, и не допускает задержки.

Может быть, есть способ сделать это, используя события или каким-то образом сопоставив джойстик с клавишами? qjoypad мне не подходит, а joy2keys — мусор. Мне нужно было бы сделать сопоставление в программе python.


person Ryan Haining    schedule 23.03.2013    source источник


Ответы (1)


Sleep заставляет программу останавливать выполнение, так что это не вариант. Вы также можете сделать это без использования set_timer и событий. Я сделал это, используя пару флагов и get_ticks из pygame.time.

import pygame
from pygame.locals import *

def main():
    pygame.init()
    pygame.display.set_mode((480, 360))
    gamepad = pygame.joystick.Joystick(0)
    gamepad.init()

    delay = 1000
    neutral = True
    pressed = 0
    last_update = pygame.time.get_ticks()

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                return

        move = False
        if gamepad.get_axis(1) == 0:
            neutral = True
            pressed = 0
        else:
            if neutral:
                move = True
                neutral = False
            else:
                pressed += pygame.time.get_ticks() - last_update
        if pressed > delay:
            move = True
            pressed -= delay
        if move:
            print "move"
        last_update = pygame.time.get_ticks()

if __name__ == "__main__":
    main()
    pygame.quit()

Когда get_axis указывает на отсутствие движения, устанавливается нейтральный флаг, а нажатый таймер сбрасывается, в результате чего флаг движения остается неустановленным. Когда нейтральный флаг не установлен, если он установлен заново, устанавливается флаг перемещения. Если он не установлен заново, нажатый таймер увеличивается, и перемещение устанавливается только в том случае, если нажатый таймер больше, чем задержка.

person 0eggxactly    schedule 24.03.2013