1

I am having a problem with pyGame (complete newbie here). I practice with event.key and would like to unpress / cut off key that is pressed continuously. I have tried to google it and checked this site, but that led to no promising results. Whole thing takes place in

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

(full lines 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")

This works just fine if up arrow is pressed once, but keeps on executing yChange in a loop in case it was not released - that of course is not desired at all. Could you help me with this please?

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
NewBe
  • 61
  • 1
  • 7

3 Answers3

3

If you only want the player to be able to jump 10 'units' per up press then stop in place, you could simply set yChange to 0 each frame after you add it to mainCharY.

However, if you're looking for a more robust jumping system (button is pressed, player moves up for a few frames, then stops and falls back down) more is required.

To give you an idea: what if you had some logic at the end of each frame that checks if mainCharY > 0 (player is not on ground) and, if so, subtracts some number from yChange (as if gravity were pulling them down)?

In the above case, your code should avoid the repeating up press problem. It might be easier to just test (mainCharY > 0) instead of using an isJumping variable.

Sam Holloway
  • 121
  • 3
1

I don't think it's likely at all that pygame could miss a key event.

I think the problem is that you're not setting isJumping to false anywhere, which stops the changing of yChange forever after the first press. If I'm interpreting this correctly, the following code should work:

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

One thing to keep in mind is that this jumping system won't look very natural. Look to @SamHolloway's answer for more clarification on this.

1

It seems you're misunderstanding how the event queue and event loop work. When you press a key, a single pygame.KEYDOWN event gets added to the event queue. Calling pygame.event.get empties the event queue and puts all events into a list over which you iterate with the for loop: for event in pygame.event.get():. That means pygame doesn't know that you're still holding the key, it will only see that you've pressed UP once. It will also notice that you release the key and add a pygame.KEYUP event to the queue.

In your case you're decreasing the yChange variable to -10 when you press the UP key. In the while loop mainCharY will then be decremented by -10 each frame and the character will move upwards. As soon as you release the key, the yChange is reset to 0 and the player character stops.

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

To implement jumping in your game, you should add a GRAVITY constant which you add to your y-velocity each frame to accelerate downwards. When the character touches the ground, set the y-velocity to 0 and a variable (on_ground or something similar) to True, so that you know that the player can jump. When the player presses the jump key, you can set the y-velocity to a negative value and the sprite will start to move upwards until the GRAVITY pulls him down again. Here's a complete example.

skrx
  • 19,980
  • 5
  • 34
  • 48