My collide_rect function is not working as I expect to be. The problem is when press the key 'r', it should be able to reset everything and continue the game. But when I actually press the key 'r', it does not change anything when I add in the pause statement. I want to have the game pause when two of the sprites I have(ball, obstacle) collide. After the user inputs the letter 'r', it should go back to running and reset position for both sprites. The error I am getting is when I press the key 'r', it does not change anything on the surface.
This is my while loop:
paused = False
def display_text(text):
font = pygame.freetype.Font('helvetica.ttc', 32)
text_attributed = font.render_to(gameDisplay, (300,300), text, black)
while not crashed:
time = pygame.time.get_ticks()
obstacle.change_x()
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
ball.jump_true()
if event.key == pygame.K_SPACE:
ball.jump_true()
if event.key == pygame.K_r:
paused = not paused
if ball.collide == True:
gameDisplay.fill(white)
display_text('You Lost! type "R" to restart')
paused = True
if paused == True:
ball.reset_position()
obstacle.reset_position()
pygame.display.flip()
clock.tick(20)
else:
ball.jump()
ball.test_collision(obstacle)
gameDisplay.fill(white)
ball.update()
obstacle.update()
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
Don't overcomplicate things. You don't need multiple event loops. Use 1 main loop, 1 event loop and a state which indicates if the game is paused. e.g.:
paused = False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r
# Toggle pause
paused = not paused
if paused:
# "pause" mode
# [...]
else
# "run" mode
# [...]
# update display etc.
# [...]
This question already has answers here:
Why is my pause system not working in Pygame?
(2 answers)
Closed 8 years ago.
hi there i've spent hours trying to make a toggle pause in pygame that you press space and it pauses then you press space again to un-pause and i'm having no luck would any one be able to help me please?
############### 2nd attempt #############
global timedelay
timedelay = pygame.time.wait (0)
pause = 0
if event.type == KEYUP:
if event.key == K_p and pause == 0:
timedelay = pygame.time.wait (9999)
pause = 1
if event.key == K_p and pause == 0:
timedelay = pygame.time.wait (0)
pause = 0
timedelay
############### 1st attempt #############
if event.type == KEYDOWN:
pause = 0
if event.key == K_p and pause == 0:
while 1:
pause = 0
event = pygame.event.wait()
pause = 1
if event.type == KEYDOWN:
if event.key == K_p and pause == 0:
print "woo!"
pause = 0
break
Don't block your whole main loop from running, just skip the state change part of the loop. You still need to be able to respond to events or your app is "unresponsive". You also want to keep drawing as windows can be moved around and cover your game and the screen still needs to refresh. So:
game_over = False
paused = False
while not game_over:
# handle events
for event in pygame.event.get():
if event.type == KEYDOWN:
paused = False
if event.key == K_p:
paused = True
...
if not paused:
# handle game state change
# handle screen drawing
pygame.display.flip()
My problem is the menu, It shows "Press space to play!"
But when i press it, it doesn't work!
I think its a problem with the while loops
I can't display code correctly so here's a link to my code
https://github.com/Donutoftime44/nheon-shooter
I tried putting if statements in my code like
while not done:
if menu:
...
elif not menu:
...
But it still does'nt work!
Can someone help me?
You have
while menu:
for event in pg.event.get():
if event.type == QUIT:
pg.quit()
sys.exit()
if event.type == KEYUP:
if event.key == K_SPACE:
print "playing"
done = True
Because you never change menu the loop never breaks, I believe you may want to add menu = False in if event.key == K_SPACE:
Assuming you're talking about this portion of the code:
while menu:
for event in pg.event.get():
if event.type == QUIT:
pg.quit()
sys.exit()
if event.type == KEYUP:
if event.key == K_SPACE:
print "playing"
done = True
windowdisplay.fill(colors["gray"])
windowdisplay.blit(label, ((maxx / 2) - 100, maxy - 25))
pg.display.update()
It seems like you want to end the loop when the user presses space. In which case, you need:
if event.key == K_SPACE:
menu = False
Setting done equal to True does nothing, since done doesn't appear anywhere else in your code.
I am learning python as well as pygame. I am struggling a bit with finding the issue in my code. When I hold down a key and press another key at the same time, and then let go of them in the same order I press them, it sometimes makes my little character move backwards in the opposite direction.
Here is my code that I am struggling with:
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
keystate = pygame.key.get_pressed()
if event.type == pygame.QUIT: # if user clicked close
running = False # flag done to exit this loop
# all game logic / controls should go below this comment
elif event.type == KEYDOWN:
if keystate[K_SPACE]:
print ('pressed space')
player.move_up = True
elif keystate[K_RIGHT]:
print ('pressed right')
player.move_right = True
elif keystate[K_LEFT]:
print ('pressed left')
player.move_left = True
elif event.type == KEYUP:
if keystate[K_SPACE]:
print ('released space')
player.move_up = False
elif keystate[K_RIGHT]:
print ('released right')
player.move_right = False
elif keystate[K_LEFT]:
print ('released left')
player.move_left = False
if player.move_up:
player.pos[1] -= 3
if player.move_up == False:
if player.pos[1] < ground_level:
player.pos[1] +=3
if player.move_right:
player.pos[0] += 5
if player.move_left:
player.pos[0] -= 5`
So far I don't have any actual physics, and he just flies around. But that's okay, I just want to iron out the issues that I am already having.
You never update keystate's value on a KEYUP event. Thus, it still has whatever values it had whenever the last KEYDOWN event fired.
To fix this, change this...
if event.type == KEYDOWN:
keystate = pygame.key.get_pressed()
to this:
if event.type in (KEYDOWN, KEYUP):
keystate = pygame.key.get_pressed()
I'm attempting to work out simple controls for an application using pygame in Python. I have got the basics working, but I'm hitting a weird wall: I am using the arrow keys to control my character. If I hold down one arrow key, then hold down another arrow key (to move diagonally), the character moves as expected. However, if I release the second key that I pressed (while still holding down the first key), the character stops moving, even though I am still holding down that first key. Here is my simple movement code:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if pygame.key.get_pressed()[K_LEFT]:
player.pos = (player.pos[0] - 2, player.pos[1])
if pygame.key.get_pressed()[K_RIGHT]:
player.pos = (player.pos[0] + 2, player.pos[1])
if pygame.key.get_pressed()[K_UP]:
player.pos = (player.pos[0], player.pos[1] - 2)
if pygame.key.get_pressed()[K_DOWN]:
player.pos = (player.pos[0], player.pos[1] + 2)
Now, I was naturally very confused by this. So I tried to print some lines to debug. In the top of the main control loop, I wrote:
print (pygame.key.get_pressed()[K_DOWN], pygame.key.get_pressed()[K_RIGHT])
print pygame.event.get()
...to output a tuple displaying the state of the down and right arrow keys, and then display the pygame event queue. My results baffled me even more. If I move the character diagonally down and right, pressing the down key first and then the right key, then release the right key to make it move simply downward, the character stops moving as before... but this is printed to the shell:
(1, 0)
[]
That is, when I release the right arrow key and still hold down the down arrow key, pygame.key.get_pressed() understands that the down arrow key is still being held down, but there is nothing in the event queue.
Also, earlier in the code (before the control loop) I am invoking
pygame.key.set_repeat(1, 2)
to make the character continue to move while the key is held down.
Any help will be appreciated! Thanks :)
For things like movement, you should not check for events (like KEYDOWN or KEYUP), but check every iteration of your mainloop if your movement keys are pressed (using get_pressed).
In your code, you check the pressed keys only if there's also a KEYDOWN event.
There are also some other things to consider:
You should seperate the key-mapping and the speed of your player, so it will be easier later on to change either of this.
You should determine a movement vector and normalize it first, since otherwise, if your vertical and horizontal movement speed is 10, your diagonal movement speed would be ~14.
Working example:
import pygame
pygame.init()
screen = pygame.display.set_mode((200, 200))
run = True
pos = pygame.Vector2(100, 100)
clock = pygame.time.Clock()
# speed of your player
speed = 2
# key bindings
move_map = {pygame.K_LEFT: pygame.Vector2(-1, 0),
pygame.K_RIGHT: pygame.Vector2(1, 0),
pygame.K_UP: pygame.Vector2(0, -1),
pygame.K_DOWN: pygame.Vector2(0, 1)}
while run:
for e in pygame.event.get():
if e.type == pygame.QUIT: run = False
screen.fill((30, 30, 30))
# draw player, but convert position to integers first
pygame.draw.circle(screen, pygame.Color('dodgerblue'), [int(x) for x in pos], 10)
pygame.display.flip()
# determine movement vector
pressed = pygame.key.get_pressed()
move_vector = pygame.Vector2(0, 0)
for m in (move_map[key] for key in move_map if pressed[key]):
move_vector += m
# normalize movement vector if necessary
if move_vector.length() > 0:
move_vector.normalize_ip()
# apply speed to movement vector
move_vector *= speed
# update position of player
pos += move_vector
clock.tick(60)
just use the events return data, instead of trying to poll, you're already checking if its a keydown event TYPE, now just interrogate the KEY index, like so:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_LEFT:
player.pos = (player.pos[0] - 2, player.pos[1])
rest of code.....
also consider using a separate data structure to store the state of your controls, then just use the events to update that data structure. That will help make the controls a bit more flexible as you wont be relying on the event queue to cause your character to move, which in my experience causes problems like: not being able to push more than two buttons at a time, and odd delay or timing issues with character movements. so something like:
keystates={'up':False, 'down':False, 'left':False, 'right':False}
running=True
#start main pygame event processing loop here
while running:
for event in pygame.event.get():
if event.type == QUIT:
running=False
#check for key down events
if event.type == KEYDOWN:
if event.key == K_UP:
keystates['up']=True
if event.key == K_DOWN:
keystates['down']=True
if event.key == K_LEFT:
keystates['left']=True
if event.key == K_RIGHT:
keystates['right']=True
#check for key up events
if event.type == KEYUP:
if event.key == K_UP:
keystates['up']=False
if event.key == K_DOWN:
keystates['down']=False
if event.key == K_LEFT:
keystates['left']=False
if event.key == K_RIGHT:
keystates['right']=False
#do something about the key states here, now that the event queue has been processed
if keystates['up']:
character.moveUp() #or whatever your call for these are...
if keystates['down']:
character.moveDown()
if keystates['left']:
character.moveLeft()
if keystates['right']:
character.moveRight()
#gracefully exit pygame here
pygame.quit()
You are using event-based input , but in this case you want polling-based input. Then you don't mess with key-repeats.
import pygame
from pygame.locals import *
done = False
player.pos = Rect(0,0,10,10)
while not done:
for event in pygame.event.get():
# any other key event input
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESC:
done = True
elif event.key == K_F1:
print "hi world mode"
# get key current state
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
player.pos.left -= 10
if keys[K_RIGHT]:
player.pos.left += 10
if keys[K_UP]:
player.pos.top -= 10
if keys[K_DOWN]:
player.pos.left += 10
if keys[K_SPACE]:
print 'firing repeated gun'
My guess is that set repeat doesn't work the way that you think it will. Basically, after your second key goes up, the repeat doesn't happen. This would seem to make sense to me: open up a text editor and hold down the "A" key. "A"s will spill out across the screen. Then, press the "J" key with the "A" key still held down. The "A"s stop. That is a typical key repeat system.
I'm not sure using this "set_repeat" method is going to work out in the end anyway. Basically, any key that the player presses will now "repeat", even if they click "fire" or "jump".
As an alternative, try saving the state when the user presses or releases. Don't use the set_repeat, but do something like the following:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if pygame.key.get_pressed()[K_LEFT]:
player.moving_left = True
if pygame.key.get_pressed()[K_RIGHT]:
player.moving_right = True
if pygame.key.get_pressed()[K_UP]:
player.moving_up = True
if pygame.key.get_pressed()[K_DOWN]:
player.moving_down = True
elif event.type == KEYUP:
if pygame.key.get_pressed()[K_LEFT]:
player.moving_left = False
if pygame.key.get_pressed()[K_RIGHT]:
player.moving_right = False
if pygame.key.get_pressed()[K_UP]:
player.moving_up = False
if pygame.key.get_pressed()[K_DOWN]:
player.moving_down = False
# Somewhere else in your game loop...
if player.moving_left:
player.pos[0] -= 2
if player.moving_right:
player.pos[0] += 2
if player.moving_up:
player.pos[1] -= 2
if player.moving_right:
player.pos[1] += 2