This question already has answers here:
Pygame unresponsive display
(1 answer)
Pygame window not responding after a few seconds
(3 answers)
Closed 2 years ago.
my code:
def shop_button(self):
click = pygame.mouse.get_pressed()
if click[0] == 1:
self.open_shop() # draws shop
self.inshop = True
while self.inshop:
pygame.time.delay(10)
mousepos = pygame.mouse.get_pos()
if click[0] == 1 and b.mouse_on_button(mousepos[0], mousepos[1], b.escapex, b.escapex2, b.escapey, b.escapey2):
self.inshop = False
whenever you click on the shop button this function is run, however, while self.inshop is inside an if statement like such the game instantly stops responding and crashes. This could be a very simple solution as I am semi-new to pygame and the python language as a whole. However, with that being said I can't seem to find a solution anywhere else.
The game does not crash, it does not respond, because you have a loop inside the main application loop. The inner loop has no event handling and update of the display.
def shop_button(self):
# [...]
while self.inshop:
pygame.time.delay(10)
mousepos = pygame.mouse.get_pos()
# [...]
The position which is returned by pygame.mouse.get_pos() is read from an internal cache. The cache is updated when the events are handled by either pygame.event.pump() or pygame.event.get().
That means if you retrieve the position in a loop, without handling the events, the the position does not reflect the current mouse position, it is continuously the same position, the position at the point when pygame.event.get() called, before the loop.
Furthermore the display Surface won't change, without updating the display, by either pygame.display.flip() or pygame.display.update().
You have a main application loop, use it. The main application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
Never implemented nested application loops. You have to change the control flow and the design of your applcaition.
Related
So right now, i have a platformer and i want to make it so when i click on a button, the whole game restarts.
In main.py:
level=Level(level_map,screen)
while running:
if game_state=='game_active':
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
pygame.font.quit()
sys.exit()
level.run()
screen.blit(sky_surface,(0,0))
pygame.display.update()
clock.tick(60)
in level.py:
class Level:
def __init__(self,level_data,surface):
self.display_surface=surface
self.level_building(level_data)
def level_building(self,tilesheet):
self.coins=pygame.sprite.Group()
self.player=pygame.sprite.GroupSingle()
for row_index,row in enumerate(level_map):
for col_index,cell in enumerate(row):
self.x=col_index*tile_size
self.y=row_index*tile_size
if cell=='R':
self.coin_sprite=Recyclables((self.x+22,self.y+55))
self.coins.add(self.coin_sprite)
if cell=='P':
self.player_sprite=Player((self.x+10,self.y))
self.player.add(self.player_sprite)
def collisions(self):
playercoin=pygame.sprite.groupcollide(self.coins,self.player,True,False) # kills the coin (to show it has been picked up)
if len(playercoin)==1:
self.score+=1
def run(self):
self.coins.draw(self.display_surface)
self.collisions()
self.player.draw(self.display_surface)
After my game finishes running, what is a good way to restart everything, and respawn all the sprites that were killed? (did not show the kill code since it'd be too long) so far i've tried killing all sprites after the game but i don't know how to re-draw everything.
In PyGame, you're in full control of what's being drawn on the screen every frame, so I'm not sure why you wouldn't be sure how to redraw things.
Since you apparently have already encapsulated your game logic into the Level class, restarting the level shouldn't require more than just
level = Level(level_map, screen)
so subsequent calls to level.run() use a fresh level.
(Also, unless you're doing esoteric things that you're not showing us here, you shouldn't necessarily need to even "kill sprites".)
This question already has answers here:
Pygame window not responding after a few seconds
(3 answers)
Why is nothing drawn in PyGame at all?
(2 answers)
Closed 2 years ago.
MacOSX 10.15.2, Python 3.8 and Pygame 2.0.0.
Hello! I am currently trying to make a dark purple (87,61,122) background in Pygame, but it only appears as a black background, seemingly frozen and loading forever.
Here is my code:
import pygame
bgcolor = [87,61,122]
pygame.init()
screen = pygame.display.set_mode((1600,900))
screen.fill(bgcolor)
pygame.display.flip
Is there anything wrong with the code or is Pygame just refusing to co-operate?
pygame.display.flip is not a function call. You missed the parentheses.
However, you have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system. This will update the contents of the entire display.
The typical PyGame application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (draw all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
import pygame
bgcolor = [87,61,122]
pygame.init()
screen = pygame.display.set_mode((1600,900))
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
# handle events
for event in pygame.event.get():
if event.type == QUIT:
run = False
# clear display
screen.fill(bgcolor)
# draw scene
# [...]
# update display
pygame.display.flip()
pygame.quit()
exit()
change pygame.display.flip by pygame.display.flip()
or pygame.display.update()
not that without IDLE, this script will display a window and directly destroy it.
To add like loop:
import pygame
bgcolor = [87,61,122]
pygame.init()
screen = pygame.display.set_mode((1600,900))
loop = True
while loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False #Quiting
screen.fill(bgcolor)
pygame.display.update()
This question already has answers here:
Pygame unresponsive display
(1 answer)
Pygame window not responding after a few seconds
(3 answers)
Closed 2 years ago.
I am trying to understand why my program is loosing respond when I trying exit from game. I make some test and here is code:
import pygame
import time
pygame.init()
run=True
pygame.display.set_caption("test")
win=pygame.display.set_mode((200,200))
while run==True:
pygame.time.delay(16)
keys=pygame.key.get_pressed()
#for event in pygame.event.get():
#if event.type == pygame.QUIT:
#run=False
win.fill((125,125,125))
if keys[pygame.K_q]:
run=False
pygame.display.update()
pygame.quit()
If execute this code - windows can't properly exit from program when user pressed key "q".
If remove comments symbols # form 14,15,16 strings, all will work properly. Hitting "q" key will exit from program normally.
Only one question - why???
You have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
If you don't handle the events, pygame.key.get_pressed() will stop working. The states of the keys returned by pygame.key.get_pressed() are evaluated internally when the events are handled.
At least you've to call pygame.event.pump():
while run==True:
pygame.time.delay(16)
pygame.event.pump()
keys=pygame.key.get_pressed()
if keys[pygame.K_q]:
run=False
win.fill((125,125,125))
pygame.display.update()
How do you make the code stop for a moment before checking for something else? (I'm new to code)
if BonusTime==True and Drop==True:
if event.type == pygame.MOUSEBUTTONDOWN:
window.blit(Fired,(mouseX-12,mouseY-12))
Cankill=True
#I want it to delay here
Cankill=False
There is a cross hair that follows the mouse and when I click it, it fires. The problem is, you can just hold the mouse down and leave the cross hair in one place. Whenever an enemy walks into the cross hair, they die. I need it so even when you hold it will only fire once. I plan to make it delay the if statement, to set "Cankill" to true and then wait a second, after waiting, it should set "Cankill" to false. I've already looked through a lot of other people's questions similar to this and haven't found something I can understand. So if you could please help me find out how to delay it in the way I need.
"Pausing" is not what you want - if you do that, your game will just freeze, and nothing will move (since you are usign the OS mouse pointer, maybe it could move).
Anyway, the function to "pause" inside a game is pygame.time.wait(1000) - the number is in miliseconds.
Waht you actually need is to mark down the time the click was made, continue with the game, and when 1 second has passed, reset the variable back to the other state.
Something along:
last_trigger = 0
while True:
# game updating code goes here (getting events, and such)
...
if Cankill and pygame.time.get_ticks() - last_trigger > 1000:
Cankill = False
if event.type == pygame.MOUSEBUTTONDOWN:
window.blit(Fired,(mouseX-12,mouseY-12))
Cankill=True
last_trigger = pygame.time.get_ticks()
The "get_ticks" call returns the number of miliseconds that passed since pygame was initialized - and is usefull for this time of timers.
This question already has answers here:
How to efficiently hold a key in Pygame?
(7 answers)
Closed 8 years ago.
I am trying to write a Pong game in which I can move the paddle using the up and down arrows. I created a Paddle object that updates by a given amount (passed as the parameter "num" in the code below) each time the up key is pressed. What I want to do is allow the user to hold the up button down which would cause the paddle to continuously move in the up direction. I tried writing this event handling in a while loop, but I got stuck in an infinite loop. Here is the code below:
for event in PE.get():
if event.type == PG.KEYDOWN:
keystate = PG.key.get_pressed()
if event.key == PG.K_ESCAPE:
done = True
while keystate[PL.K_UP]:
rightPaddle.update(-20)
if event.type == PG.QUIT:
done = True
Below is the code for the Paddle object:
class Paddle(object):
def __init__(self, x, y):
self.topleftx = x
self.toplefty = y
self.width = 15
self.height = 100
def draw(self, surface):
rect = PR.Rect(self.topleftx, self.toplefty, \
self.width, self.height)
surface.fill(WHITE, rect)
def update(self, num):
self.toplefty += num
I checked other stackoverflow questions on this topic, which is how I found the PG.key.getPressed() method, but other answers suggest using "sprites" which I'm not sure how to use. Could anyone offer some advice on how to go about performing this task?
The problem with the while loop is that it's evaluating the one keydown event. That event will always be whatever it starts as, and there's no chance for it to change within the event handling code. What you want to catch is the PG.KEYUP event that follows it. So you'll have something (logically) like
if event.type == PG.KEYDOWN and keystate[PL.K_UP]:
key_up_pressed = True
elif event.type == PG.KEYUP and keystate[PL.K_UP]:
key_up_pressed = False
Obviously, you can factor that better, but the key_up_pressed state will get evaluated in your main loop once every so often (frame, millisecond, whatever), and move the paddle.
In this code:
while keystate[PL.K_UP]:
rightPaddle.update(-20)
… there is nothing that can change keystate. So, if keystate[PL.K_UP] is true once, it will be true forever. Hence the infinite loop.
You could fetch the current key information from pygame each time through the loop, which would at least make it not infinite—but it would still mean your entire program blocks up until the user releases the key.
Without knowing whether you intended to write a frame-rate-driven game or an event-loop-driven game, I can't tell you exactly how to fix it.
But either way, the key point is that you don't want to move over and over as long as the key is held down, you want to move at a certain speed, processing other events in between, as long as the key is held down. Either way, you'll use the KEYDOWN and KEYUP events to set some kind of flag that tells you to move the paddle. Then, once per frame, or using a timer event, or in some other way, you will use the current flag value to move the paddle.