pygame - отжать ключ на event.key

1

У меня проблема с pyGame (полный новичок здесь). Я тренируюсь с event.key и хотел бы отключить/отключить клавишу, которая будет нажата непрерывно. Я попытался это сделать и проверил этот сайт, но это не принесло многообещающих результатов. Вся вещь имеет место в

if event.key == pygame.K_UP and isJumping == False:

(полные строки 49 - 55)

## HOW TO UNPRESS K_UP IN CASE IT WAS PRESSED AND NOT RELEASED?
    if event.key == pygame.K_UP and isJumping == False:
        yChange -= 10
        isJumping = True

    elif event.key == pygame.K_UP and isJumping == True:
        print("X")

Это работает отлично, если стрелка вверх нажимается один раз, но продолжает выполнение yChange в цикле, если он не был выпущен - это, конечно, совсем не желательно. Не могли бы вы мне помочь?

import pygame

pygame.init() # Initialize pyGame module

# Set screen dimensions
screenW = 800
screenH = 600

# Set color
AQUA = (155, 255, 255)

# Set FPS
FPS = 60
fpsClock = pygame.time.Clock()

# Set character
mainChar = pygame.image.load('p1_front.png')
mainCharX = screenH / 2 # char X position
mainCharY = screenW / 2 # char Y position
isJumping = False
xChange = 0
yChange = 0
MOVSPEED = 1
# Set backgrounds
mainBg = pygame.image.load('bg_castle.png')
mainBg = pygame.transform.scale(mainBg, (screenW, screenH))

# Set the window, param in a tuple is width / height
DISPLAYSURF = pygame.display.set_mode((screenW, screenH))
# Set window name (game title)
pygame.display.set_caption("Newbie training")

while True: # Main loop of the game
#set BG
DISPLAYSURF.blit(mainBg, (0,0))

# Events loop below
for event in pygame.event.get():
    if event.type == pygame.QUIT: # Quit window when [x] is pressed
        pygame.quit()
        exit()

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_RIGHT:
            xChange += MOVSPEED
        elif event.key == pygame.K_LEFT:
            xChange -= MOVSPEED

        ## HOW TO UNPRESS K_UP IN CASE IT WAS PRESSED AND NOT RELEASED?
        if event.key == pygame.K_UP and isJumping == False:
            yChange -= 10
            isJumping = True

        elif event.key == pygame.K_UP and isJumping == True:
            print("X")



    if event.type == pygame.KEYUP:
        if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
            xChange = 0
        if event.key == pygame.K_UP:
            yChange = 0
    #print(event)

mainCharX += xChange
mainCharY += yChange
DISPLAYSURF.blit(mainChar, (mainCharX, mainCharY)) # Load character
pygame.display.update() #update window
fpsClock.tick(FPS) # FPS goes always after update
Теги:
pygame

3 ответа

1
Лучший ответ

Кажется, вы не понимаете, как работает очередь событий и цикл событий. Когда вы нажимаете клавишу, в pygame.KEYDOWN событий добавляется одно событие pygame.KEYDOWN. Вызов pygame.event.get опорожняет очередь событий и помещает все события в список, по которому вы перебираете цикл for event in pygame.event.get():: for event in pygame.event.get(): Это означает, что pygame не знает, что вы все еще держите ключ, он только увидит, что вы нажали UP один раз. Он также заметит, что вы отпустите ключ и добавите событие pygame.KEYUP в очередь.

В вашем случае вы уменьшаете переменную yChange до -10 при нажатии клавиши UP. В цикле while mainCharY будет mainCharY на -10 каждый кадр, и символ будет двигаться вверх. Как только вы отпустите ключ, yChange сбрасывается на 0 и символ игрока останавливается.

if event.type == pygame.KEYUP:
    if event.key == pygame.K_UP:
        yChange = 0

Чтобы реализовать прыжки в вашей игре, вы должны добавить константу GRAVITY, которую вы добавляете к своей скорости y, чтобы каждый кадр ускорялся вниз. Когда персонаж коснется земли, установите для y-velocity значение 0 и переменную (on_ground или что-то подобное) в значение True, чтобы вы знали, что игрок может прыгать. Когда игрок нажимает клавишу перехода, вы можете установить у-скорость на отрицательное значение, и спрайт начнет двигаться вверх, пока GRAVITY снова не опустит его. Вот полный пример.

3

Если вы хотите, чтобы игрок мог прыгать на 10 'единиц' на прессу, тогда остановитесь на месте, вы можете просто установить yChange на 0 каждый кадр после добавления его в mainCharY.

Однако, если вы ищете более надежную систему прыжков (нажата кнопка, игрок перемещается вверх на несколько кадров, затем останавливается и падает назад) требуется больше.

Чтобы дать вам представление: что, если в конце каждого фрейма была какая-то логика, проверяющая, если mainCharY> 0 (игрок не на земле) и, если это так, вычитает некоторое число из yChange (как если бы гравитация вытягивала их)?

В приведенном выше случае ваш код должен избегать повторной проблемы с прессой. Возможно, было бы проще просто проверить (mainCharY> 0) вместо использования переменной isJumping.

1

Я не думаю, что это вообще возможно, что pygame может пропустить ключевое событие.

Я думаю, проблема заключается в том, что вы не устанавливаете isJumping на false в любом месте, что останавливает изменение yChange навсегда после первого нажатия. Если я правильно это интерпретирую, следующий код должен работать:

if event.type == pygame.KEYDOWN:
    ...  # Your other code

    if event.key == pygame.K_UP and not isJumping:  # "== False" is not necessary
        yChange -= 10
        isJumping = True


if event.type == pygame.KEYUP:
    ...  # Your other code

    if event.key == pygame.K_UP and isJumping:
        yChange = 0
        isJumping = False  # <-- This is the addition to the code

Одна вещь, о которой нужно помнить, заключается в том, что эта система прыжков не будет выглядеть очень естественной. Посмотрите на ответ @SamHolloway, чтобы получить больше разъяснений по этому вопросу.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню