Pygame sprite jump with pressed key - python

I'm currently making a 2D platformer, I want the player sprite to jump when it touches the ground and the jump key is being pressed.
I had this at the begging, seeing it wasn't doing what I wanted, I wrote a new code using boolean values.
Original code:
if not (event == None):
if (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_UP or event.key == pygame.K_SPACE):
if (self.vspeed == 0):
self.vspeed = -(self.speed)*2
New code:
if not (event == None):
if(event.type == pygame.KEYDOWN):
if (event.key == pygame.K_UP or event.key == pygame.K_SPACE):
jump_pressed = True
elif (event.type == pygame.KEYUP):
if (event.key == pygame.K_UP or event.key == pygame.K_SPACE):
jump_pressed = False
elif (jump_pressed == True and self.vspeed == 0):
self.vspeed = -(self.speed)*2
print("jump is pressed")
Sadly, the new code doesn't work and I don't understand why. I did alot of research and tests over the past week without any success. The player jumps when I press the key but it doesn't jump again when it touches the ground.
I need to release the key and press it again to make the player jump. "jump is pressed" only gets printed when I press down.
Looking forward to your help :)

Your code correctly sets the jump_pressed variable here:
if not (event == None):
if(event.type == pygame.KEYDOWN):
if (event.key == pygame.K_UP or event.key == pygame.K_SPACE):
jump_pressed = True
elif (event.type == pygame.KEYUP):
if (event.key == pygame.K_UP or event.key == pygame.K_SPACE):
jump_pressed = False
However, this case
elif (jump_pressed == True and self.vspeed == 0):
self.vspeed = -(self.speed)*2
print("jump is pressed")
is (almost) never true: the only way it can enter in that condition is that
event is not None.
event.type is neither KEYDOWN nor `KEYUP
jump_pressed is True and self.vspeed is 0.
You have to change the structure into
if event is not None:
if event.type == pygame.KEYDOWN:
if event.key in [pygame.K_UP, pygame.K_SPACE]:
jump_pressed = True
elif event.type == pygame.KEYUP:
if event.key in [pygame.K_UP, pygame.K_SPACE]:
jump_pressed = False
if jump_pressed and self.vspeed == 0:
self.vspeed = -(self.speed)*2
print("jump is pressed")
So that the jump_pressed check is performed even when no events are triggered.

problem can be because you have last elif inside for event loop.
You need something like this:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_UP, pygame.K_SPACE):
jump_pressed = True
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_UP, pygame.K_SPACE):
jump_pressed = False
# after `for` loop
if jump_pressed and self.vspeed == 0:
self.vspeed = -(self.speed)*2
print("jump is pressed")

Related

Require holding key down for movement in pacman pygame with game pad

I've been modifying the PACMAN pygame code from here. Currently, I have a function that requires players to hold down a direction key in order to keep moving in that direction. The code for that is:
def process_events(self):
for event in pygame.event.get(): # User did something
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: # exit program entirely
self.run_over = True
return True
elif event.key == pygame.key_r:
self.player.move_right()
elif event.key == pygame.key_l:
self.player.move_left()
elif event.key == pygame.key_u:
self.player.move_up()
elif event.key == pygame.key_d:
self.player.move_down()
elif event.type == pygame.KEYUP:
if event.key == pygame.key_r:
self.player.stop_move_right()
elif event.key == pygame.key_l:
self.player.stop_move_left()
elif event.key == pygame.key_u:
self.player.stop_move_up()
elif event.key == pygame.key_d:
self.player.stop_move_down()
return False
While this works perfectly for keyboard button presses, I'm trying to incorporate a gamepad, which uses capital letters to designate a key down button press and lower case letters for keyup button presses. For example, when moving in the downward direction, keypress down is "D" and keypress up/release is "d". Using the same function from above with the gamepad results in me having to button mash to barely move. I, therefore, modified the function to this:
def process_events(self):
for event in pygame.event.get(): # User did something
try:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: # exit program entirely
self.run_over = True
return True
elif event.key == pygame.key_r:
self.player.move_right()
elif event.key == pygame.key_l:
self.player.move_left()
elif event.key == pygame.key_u:
self.player.move_up()
elif event.key == pygame.key_d:
self.player.move_down()
except:
self.player.stop_move_right()
self.player.stop_move_left()
self.player.stop_move_up()
self.player.stop_move_down()
return False
However, with this new code, I simply tap a direction button and I move in that direction indefinitely until I press a different button. Is there a way for me to modify my code so that the player needs to hold down the gamepad direction button to move and they stop once the button is released?
Thanks to #qouify, I realized that my modified function was incorrectly set up. I therefore adjusted it to this, which now performs the correct functionality:
def process_events(self):
counter = []
for event in pygame.event.get(): # User did something
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: # exit program entirely
self.run_over = True
return True
else: # direction movement
if event.key in [pygame.K_LSHIFT, pygame.K_r, pygame.K_l, pygame.K_u, pygame.K_d]:
counter.append(pygame.key.name(event.key))
# right
if len(counter) == 2 and counter[0] == "left shift" and counter[1] == "r":
self.player.move_right()
elif len(counter) == 1 and counter[0] == "r":
self.player.stop_move_right()
# left
if len(counter) == 2 and counter[0] == "left shift" and counter[1] == "l":
self.player.move_left()
elif len(counter) == 1 and counter[0] == "l":
self.player.stop_move_left()
# up
if len(counter) == 2 and counter[0] == "left shift" and counter[1] == "u":
self.player.move_up()
elif len(counter) == 1 and counter[0] == "u":
self.player.stop_move_up()
# down
if len(counter) == 2 and counter[0] == "left shift" and counter[1] == "d":
self.player.move_down()
elif len(counter) == 1 and counter[0] == "d":
self.player.stop_move_down()
return False
I realize this may not be the most elegant or "pythonic" solution, in which case I'm happy for anyone to offer suggestions. Otherwise, I'll consider this solved.

how restarting game on pygame works

how can I restart the game with user input? i searched all over the place and i wasnt able to discover how i can restart my game, i just want to press ESC and my game restart, after knowing how to do that i will implement a button, but how can I restart my game? this is my main loop:
while True:
pygame.time.Clock().tick(fps)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
#input
elif event.type == pygame.KEYDOWN:
#snake
if event.key == ord('w'):
change_to = 'UP'
if event.key == ord('s'):
change_to = 'DOWN'
if event.key == ord('a'):
change_to = 'LEFT'
if event.key == ord('d'):
change_to = 'RIGHT'
#snake2
if event.key == pygame.K_UP:
change2_to = 'UP'
if event.key == pygame.K_DOWN:
change2_to = 'DOWN'
if event.key == pygame.K_LEFT:
change2_to = 'LEFT'
if event.key == pygame.K_RIGHT:
change2_to = 'RIGHT'
#quit game
if event.key == pygame.K_ESCAPE:
#here is where was supposed to restart the game
i cut the major part to not be so long but i dont know how to restart my game
I think it should be something like this
# imports
restart = False
while running:
if restart:
# create instance of all objects used
# score = 0
# Default values should be initialised
# Keyboard events go here
# code for restarting
if event.key == pygame.K_ESCAPE:
restart = True

How to correct Syntax error with my elif, if statement. what am I doing wrong?

import sys
import pygame
def check_events(ship):
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
# Move the ship to the right.
ship.moving_right = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False
def update_screen(ai_settings, screen, ship):
'''Update images on the screen and flip to the new screen.'''
Error:
File "/home/mark/python_work/game_functions.py", line 8
elif event.type == pygame.KEYDOWN:
^
SyntaxError: invalid syntax
[Finished in 0.2s with exit code 1]
In your function, your first condition should start with an if.
def check_events(ship):
if event.type == pygame.KEYDOWN: # <--- note the change here
if event.key == pygame.K_RIGHT:
# Move the ship to the right.
ship.moving_right = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False
You have an elif without an if preceding it. Just change the first elif to an if.
You cannot use elif before an if statement. Elif cannot be used without an if statement.
This is the right syntax.
import sys
import pygame
def check_events(ship):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
# Move the ship to the right.
ship.moving_right = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False
def update_screen(ai_settings, screen, ship):
'''Update images on the screen and flip to the new screen.'''

How to move an object when a key is held down?

I know this question can be seen as a duplicate, but I spent some hours searching and figuring out what is wrong at my code.
My problem is that my object, called player, doesn't move constantly when left or right key is being held down:
for event in pygame.event.get():
if event.type == QUIT:
self.terminate()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
self.terminate()
if event.key == K_LEFT or event.key == K_a:
self.moveRight = False
self.moveLeft = True
if event.key == K_RIGHT or event.key == K_d:
self.moveLeft = False
self.moveRight = True
if event.type == KEYUP:
if event.key == K_LEFT or event.key == K_a:
self.moveLeft = False
if event.key == K_RIGHT or event.key == K_d:
self.moveRight = False
# Move the player around
if self.moveLeft :
# Moves the player object to left with self.PLAYERMOVERATE pixels.
self.player.setLeftRight(-1 * self.PLAYERMOVERATE)
if self.moveRight :
self.player.setLeftRight(self.PLAYERMOVERATE)
I also tried this alternative:
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.player.setLeftRight(-1 * self.PLAYERMOVERATE)
if keys[pygame.K_RIGHT]:
self.player.setLeftRight(self.PLAYERMOVERATE)
I think that the problem is that you are not handling the input in the main game loop.
In your code you seem to be handling the input inside a method of the object Player. This is not how input should be handled. In your second code example there is a while True: loop which will mean the loop is never exited from and thus the method's execution is never finished. I suspect that there may be a similar issue in your first example.
Instead you should:
Create all objects and classes.
Write the main game loop.
The main game loop should handle input, then process the logic of the game and then render whatever should be rendered.
Here is a short code example.
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # Exit from pygame window
quit() # End python thread
if event.type == KEYDOWN:
if event.key == K_LEFT or event.key == K_a:
player.moveRight = False
player.moveLeft = True
if event.key == K_RIGHT or event.key == K_d:
player.moveLeft = False
player.moveRight = True
if event.type == KEYUP:
if event.key == K_LEFT or event.key == K_a:
player.moveLeft = False
if event.key == K_RIGHT or event.key == K_d:
player.moveRight = False
# Move player using method
if player.moveLeft:
# Move player
# ...
# Render player
I hope that this helped you and if you have any further questions please feel free to post them in the comment section below!

Why won't my Movement code work?

I am trying to make a character move around.
My problem is that when I run the program it immediately stops responding so I don't even know what the problem is.
Here is my code.
import pygame, sys
from pygame.locals import*
pygame.init()
DISPLAYSURF = pygame.display.set_mode((780, 500), 0, 32)
FPS = 30
fpsClock = pygame.time.Clock()
sprite = pygame.image.load('CharacterFront.png')
spritex = 50
spritey = 50
charLeft = False
charRight = False
charUp = False
charDown = False
while True:
DISPLAYSURF.blit(sprite,(spritex,spritey))
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if (event.key == K_LEFT):
charLeft = True
elif (event.key == K_d):
charRight = True
elif (event.key == K_w):
charUp = True
elif (event.key == K_s):
charDown = True
if event.type == KEYUP:
if (event.key == K_LEFT):
charLeft = False
elif (event.key == K_d):
charRight = False
elif (event.key == K_w):
charUp = False
elif (event.key == K_s):
charDown = False
while charLeft == True:
spritex -= 10
sprite=pygame.image.load('CharacterLeft.png')
while charRight == True:
spritex += 10
sprite=pygame.image.load('CharacterRight.png')
while charUp == True:
spritey -= 10
sprite=pygame.image.load('CharacterBack.png')
while charDown == True:
spritey += 10
sprite=pygame.image.load('CharacterFront.png')
pygame.display.update()
fpsClock.tick(FPS)
I have already tried many different ways to do this but the closest I got caused the character to get pasted over and over and I had to spam the directions to actually move more than 10 pixels.
Your while char.. loops never end. You are already looping (while True: at the top). Just make one move (e.g. spritey -= 10) and allow the outer loop to keep running.
For ideas on how to keep your character moving while a key is held, see this question.
Apart from what jonrsharpe said, you should not load the sprite every time a keypress is done.
Instead load all your images before, and just blit them when necessary.
So your code will look like this:
sprite_back = pygame.image.load('CharacterBack.png')
sprite_front = pygame.image.load('CharacterFront.png')
sprite_right = pygame.image.load('CharacterRight.png')
sprite_left = pygame.image.load('CharacterLeft.png')
sprite = sprite_front
while True:
DISPLAYSURF.blit(sprite,(spritex,spritey))
if charLeft == True:
spritex -= 10
elif charRight == True:
spritex += 10
elif charUp == True:
spritey -= 10
elif charDown == True:
spritey += 10
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if (event.key == K_LEFT):
charLeft = True
sprite=sprite_left
elif (event.key == K_d):
charRight = True
sprite=sprite_right
elif (event.key == K_w):
charUp = True
sprite=sprite_back
elif (event.key == K_s):
charDown = True
sprite=sprite_front
if event.type == KEYUP:
if (event.key == K_LEFT):
charLeft = False
elif (event.key == K_d):
charRight = False
elif (event.key == K_w):
charUp = False
elif (event.key == K_s):
charDown = False

Categories