Quit Algorithm pygame Not working properly [duplicate] - python

This question already has an answer here:
Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?
(1 answer)
Closed 2 years ago.
In this I want the program to close when they hit the quit button but if I enable my Check_Key_Press() function, the Close() function does not work however If I comment out the Check_Key_Press() function then it works again.
import pygame
pygame.init()
width, height = 500,500
win = pygame.display.set_mode((width, height))
pygame.display.set_caption("Tic Tac Toe(GUI)")
clock = pygame.time.Clock()
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
Tile_dime = 59
Diff = (Tile_dime+1)/2
board_det = [['-',(width/2-3*Diff,height/2-3*Diff)],['-',(width/2-Diff,height/2-3*Diff)],['-',(width/2+Diff,height/2-3*Diff)],
['-',(width/2-3*Diff,height/2-Diff)],['-',(width/2-Diff,height/2-Diff)],['-',(width/2+Diff,height/2-Diff)],
['-',(width/2-3*Diff,height/2+Diff)],['-',(width/2-Diff,height/2+Diff)],['-',(width/2+Diff,height/2+Diff)]]
def draw_board():
for i in range(len(board_det)):
pygame.draw.rect(win, white, [board_det[i][1], (Tile_dime, Tile_dime)])
def Close():
global run
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
def Check_Key_Press():
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
pass
if event.key == pygame.K_LEFT:
pass
run = True
while run:
clock.tick(60)
draw_board()
Check_Key_Press()
Close()
pygame.display.update()

pygame.event.get() get all the messages and remove them from the queue. If pygame.event.get () is called in multiple event loops, only one loop receives the events, but never all loops receive all events. As a result, some events appear to be missed.
Get the events once and use them in multiple loops or pass the list or events to functions and methods where they are handled:
def Close(event_list):
global run
for event in event_list:
if event.type == pygame.QUIT:
run = False
def Check_Key_Press(event_list):
for event in event_list:
if event.type == pygame.KEYDOWN:
pass
if event.key == pygame.K_LEFT:
pass
run = True
while run:
clock.tick(60)
event_list = pygame.event.get()
draw_board()
Check_Key_Press(event_list)
Close(event_list)
pygame.display.update()

Related

PYGAME : Why does calling a function inside the game loop inside Game loop make my game lag?

I am making a simple game where enemies move around on the screen and we need to shoot them.I wanted to modularize my code so I wanted to replace the game loop logic with a function.But as soon as I do that, there's a drop in fps. Does calling a function inside while loop reduces the fps?
Without using functions,my game loop is :
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.shoot()
pygame.display.update()
#blit bg
displaysurf.blit(background,(0,0))
#render group of sprites
target_group.draw(displaysurf)
crosshair_group.draw(displaysurf)
#call the update methods
crosshair_group.update()
target_group.update()
#display fps
#print(clock.get_fps())
#restrict to 60frames drawing per second
clock.tick(60)
With the function:
def first_level():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.shoot()
pygame.display.update()
#blit bg
displaysurf.blit(background,(0,0))
#render group of sprites
target_group.draw(displaysurf)
crosshair_group.draw(displaysurf)
#call the update methods
crosshair_group.update()
target_group.update()
#display fps
#print(clock.get_fps())
#restrict to 60frames drawing per second
clock.tick(60)
while True:
first_level()
But the moment I add this function,my game starts to lag due to reduction in FPS.Why does this happen?
It looks like you messed up your indentation. pygame.display.update() and everything after that should not be part of the for event ... loop.
def first_level():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.shoot()
pygame.display.update()
#blit bg
displaysurf.blit(background,(0,0))
#render group of sprites
target_group.draw(displaysurf)
crosshair_group.draw(displaysurf)
#call the update methods
crosshair_group.update()
target_group.update()
#display fps
#print(clock.get_fps())
#restrict to 60frames drawing per second
clock.tick(60)
while True:
first_level()

Pygame application doesn't close out the first time

I am building a small game in pygame and I wanted a function to exit out. However it takes multiple clicks to exit and it is not consistent either. Also the windows exit function is restarting the program, too Here is the part of the code that deals with exiting
if isKill:
pygame.mixer.music.stop()
gameover = myfont.render("Press R to Respawn", False, (255, 255, 255))
rect = gameover.get_rect()
rect.center = screen.get_rect().center
screen.blit(gameover, rect)
if event.type == KEYDOWN:
if event.key == K_r:
gameloop()
and
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
*gameloop() is the whole script
Instead of event.type, you can use the pygame builtin event QUIT
Refer the following code
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#Can use pygame.quit() in place of running=False if the above line doesn't work.
This while loop is the starting of gameloop. The contents of the gameloop should be inside it.
Don't call the gameloop() function inside the while loop
Perhaps use sys.exit to stop the program.
Try:
import sys
import pygame
while 1:
#code
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
In your game loop, you should always keep the loop running at one level. In your code, the respawn actually freezes the current level and reruns the game at a lower level. This is why several quit commands are required to exit the game.
When the player respawns, reset the game variables, then continue the game loop.
Update your code similar to this:
if isKill: # game is over
pygame.mixer.music.stop()
gameover = myfont.render("Press R to Respawn", False, (255, 255, 255))
rect = gameover.get_rect()
rect.center = screen.get_rect().center
screen.blit(gameover, rect)
if event.type == KEYDOWN:
if event.key == K_r:
#gameloop() # remove this
dospawn() # initialize\reset game variables here (can use same function at game start)
isKill = False # start new game
continue # skip rest of game process

Why does my pygame window freeze and crash?

Whenever I try to run my program it freezes up and crashes. I'm not a master pygame coder, but I'm almost sure its something to do with my main loop. It's supposed to allow the user to move left and right using arrow keys. I've tried adding a clock and changing the size of the screen but that didn't work. Here is the code:
import pygame
import sys
import random
import time
pygame.init()
screen = pygame.display.set_mode((500,500))
events = pygame.event.get()
clock = pygame.time.Clock()
x = 50
y = 50
game_over = False
while not game_over:
for event in events:
if event.type != pygame.QUIT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
elif event.key == pygame.K_LEFT:
x -= 5
else:
sys.exit()
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (x,y,50,50))
clock.tick(30)
pygame.display.update()
The code needs to process the event queue continuously, otherwise your operating environment will consider your window to be non-responsive (locked up). Your code is almost there, except it only fetches the new events once, but this needs to be done every iteration of the main loop.
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((500,500))
clock = pygame.time.Clock()
x = 50
y = 50
game_over = False
while not game_over:
events = pygame.event.get() # <<-- HERE handle every time
for event in events:
if event.type != pygame.QUIT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
elif event.key == pygame.K_LEFT:
x -= 5
else:
sys.exit()
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (x,y,50,50))
clock.tick(30)
pygame.display.update()
You cant do foe event in events, as when you call pygame.events.get(), you are updating them, you are updating them once and looping over them every frame, you need to use for event in pygame.event.get(): so you are calling the function every frame and updating the events every frame
unless you were trying to do this?
events = pygame.event.get
...
for event in events():
which does the same as above

How to create skip functionality pygame? [duplicate]

This question already has an answer here:
Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?
(1 answer)
Closed 2 years ago.
I'm trying to create a way in pygame for the player to skip the tutorial phase simply by pressing "escape". However, I can't seem to get it to work when using the following:
for event in pygame.event.get():
if event.type == pygame.K_ESCAPE:
brek2 = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
run2 = False
brek = True
if brek or brek2:
break
pygame.time.delay(1000)
if brek:
break
Here's the full loop of the tutorial phase if you need it:
while run2:
# intro sequence
pygame.event.pump()
fade(screen_width, screen_height, BLACK)
fade(screen_width, screen_height, WHITE)
techi = pygame.transform.scale(pygame.image.load("Techi-Joe.gif"), (75, 75))
bg = pygame.Surface((screen_width, screen_height))
bg.fill(WHITE)
win.blit(pygame.transform.scale(bg, (screen_width, screen_height)), (0, 0))
win.blit(techi, (100, 600))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
run2 = False
pygame.time.delay(1000)
brek2 = False
presss = 1
brek = False
techi_bubble = pygame.transform.scale(pygame.image.load("techi_speech_bubble.png"), (700, 350))
techi_font = pygame.font.Font('Consolas.ttf', 25)
for a in range(len(techi_says)):
win.blit(pygame.transform.scale(bg, (screen_width, screen_height)), (0, 0))
win.blit(techi_bubble, (175, 300))
win.blit(techi, (100, 600))
writeLikeCode(techi_says[a], 235, 350, techi_font, 20)
for event in pygame.event.get():
if event.type == pygame.K_ESCAPE:
brek2 = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
run2 = False
brek = True
if brek or brek2:
break
pygame.time.delay(1000)
if brek:
break
Here's some addition code referenced as function writeLikeCode:
techi_says = ["Hello, User!", "My name is Techi-Joe.", "I'm a programmer,", "and this is my first game:",
"Dunk the Chief!", "in Dunk the Chief,", "your main objective", "is to dunk any US president", "you choose",
"in a cold tub of water!", "yay!"]
# writeLikeCode function
def writeLikeCode(string, xpos, ypos, font, fontsize):
for x in range(len(string)):
lstring = split(string)
text = font.render(lstring[x], 1, GREEN)
win.blit(text, (xpos + (x * fontsize), ypos))
pygame.time.delay(50)
pygame.display.update()
and here's the split function:
def split(string):
return [char for char in string]
pygame.event.get() does not only get the events, It also removes the events from the event queue. If you call pygame.event.get() twice in a row, then the first call will retrieve the events, but the 2nd call returns an empty list.
for event in pygame.event.get(): # returns the list of events
# [...]
for event in pygame.event.get(): # returns empty list
# [...]
If the event occurs after between the 2 calls of pygame.event.get(), then the event will be received be the 2nd call. But that will be a rare case.
pygame.K_ESCAPE is not an event type (see pygame.event), it is a key see (pygame.key).
If you want to detect if the ESC was pressed, then you have to detect the KEYDOWN event and to evaluate if the .key attribute is K_ESCAPE. e.g:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
run2 = False
brek = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
brek2 = True

Pygame used in VS Code with Pygame Snippets [duplicate]

This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
What all things happens inside pygame when I press a key? When to use pygame.event==KEYDOWN
(1 answer)
Closed 2 years ago.
I have installed vs code and added pygame snippets to use pygame library. My big problem is, every time I try to use any key option of pygame, like pygame.KEYDOWN or pygame.QUIT it tells me that QUIT is not a function of pygame. Can someone help me?
Everything else seems to work, like display or surface
even pygame.key.get_pressed() don’t make problems.
import pygame, random, sys
from pygame.locals import *
from pygame.key import *
def set_Background():
screen = pygame.display.set_mode((500,500))
surface = pygame.image.load('Background.png')
surface = pygame.transform.scale(surface, (500, 500))
screen.blit(surface, (0,0))
pygame.display.update()
return screen
def set_Enemy():
enemy = pygame.image.load('Enemy.png')
enemy = pygame.transform.scale(enemy, (50, 50))
return enemy
def set_Player():
player = pygame.image.load('Player.png')
player = pygame.transform.scale(player, (70, 70))
return player
RUNNING = True
while RUNNING:
background = set_Background()
enemy = set_Enemy()
player = set_Player()
enemy_rect = enemy.get_rect()
player_rect = player.get_rect()
e_x = random.randint(10,450)
e_y = random.randint(10,450)
background.blit(enemy, (e_x, e_y))
pygame.display.update()
for event in pygame.event.get():
key = pygame.key.get_pressed()
if event.type == key[pygame.K_ESCAPE]:
#module pygame has no K_ESCAPE member
sys.exit()
if event.type == pygame.QUIT:
#says module pygame has no QUIT member
sys.exit()
pygame.key.get_pressed() shouldn't be in the event loop, but in the main while loop. In the event loop you need to check if the event type is pygame.QUIT and then set the running flag to False.
Here's a fixed version:
import pygame
pygame.init()
screen = pygame.display.set_mode((500,500))
clock = pygame.time.Clock()
running = True # Uppercase names are for constants not variables.
while running:
# The event loop.
for event in pygame.event.get():
# If a pygame.QUIT event is in the queue.
if event.type == pygame.QUIT:
running = False
# To check if it was a `KEYDOWN` event.
elif event.type == pygame.KEYDOWN:
# If the escape key was pressed.
if event.key == pygame.K_ESCAPE:
running = False
# Use pygame.key.get_pressed to see if a key is held down.
# This should not be in the event loop.
key = pygame.key.get_pressed()
if key[pygame.K_UP]:
print('up arrow pressed')
screen.fill((30, 30, 30))
pygame.display.flip()
clock.tick(60)
Add from pygame.locals import * at the top of your code.
You are mixing two types of key presses in one go. You should instead either
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SOMEKEY:
do_something()
or
keys = pygame.key.get_pressed()
if keys[pygame.K_somekey]:
do_something()
so the code above with the pygame.key.get_pressed() should not be in the event loop

Categories

Resources