so i'm doing the states of my game right now :
import pygame
import sys
screen=pygame.display.set_mode((1200,700))
play_image=pygame.Surface((100,200))
play_image.fill('red')
play_rect=play_image.get_rect(topleft=(200,200))
retry_image=pygame.Surface((100,200))
retry_image.fill('red')
retry_rect=retry_image.get_rect(topleft=(200,200))
game_over=False
menustatus=True
while menustatus:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
pygame.font.quit()
sys.exit()
mouse_pos=pygame.mouse.get_pos()
mousecheck=pygame.mouse.get_pressed()
if play_rect.collidepoint(mouse_pos) and mousecheck[0]:
game_over=True
menustatus=False
screen.blit(play_image,play_rect)
pygame.display.update()
while game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
pygame.font.quit()
sys.exit()
mouse_pos=pygame.mouse.get_pos()
mousecheck=pygame.mouse.get_pressed()
if retry_rect.collidepoint(mouse_pos) and mousecheck[0]:
menustatus=True
game_over=False
screen.blit(retry_image,retry_rect)
pygame.display.update()
problem is, when i click the red rectangle, which is a placeholder for my play button to head into the gameover screen, it crashes instead of showing me a game over screen
I've written a function state_machine() which decides what is happening and what to do next, but is uses states to 'jump' from one thing to another:
import pygame
import sys
screen=pygame.display.set_mode((1200,700))
play_image=pygame.Surface((100,200))
play_image.fill('red')
play_rect=play_image.get_rect(topleft=(200,200))
retry_image=pygame.Surface((100,200))
retry_image.fill('red')
retry_rect=retry_image.get_rect(topleft=(200,200))
def state_machine(state):
if state == "menu_status":
if play_rect.collidepoint(mouse_pos) and mousecheck[0]: #checks if player clicks a button to play
state = "game_over"
elif state == "game_over":
if retry_rect.collidepoint(mouse_pos) and mousecheck[0]: #checks if player clicks a button to retry
state = "game_active"
elif state == "game_active":
if player.rect.y>screen_height: #checks if player dies
state = "game_over"
return state
game_state = "menu_status"
while True:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
pygame.font.quit()
sys.exit()
mouse_pos=pygame.mouse.get_pos()
mousecheck=pygame.mouse.get_pressed()
game_state = state_machine(game_state)
screen.blit(play_image,play_rect)
pygame.display.update()
I've not run this code because I'm not sure I've captured everything from your code.
Related
I am trying to add a pause menu in my game SpaceInvaders with the last frame of the game in the background but when I load the pause scene my game does not show the game in the background
the background game looks like this
the first time I load pause it shows this
and then whenever i load pause it behaves normally like this
my game has 3 files :
1)game file
2)pause file
3)init file (that connects above two)
Game file
import pygame
from __init__ import __INIT__
pygame.display.set_caption("Endless")
pygame.init()
screen=pygame.display.set_mode((1920/2,1080/2),pygame.RESIZABLE)
def menu():
running=True
while running:
screen.blit(pygame.image.load("docs/bg.png"),(0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
__INIT__("pause")
pygame.display.update()
menu()
Pause file
import pygame
from __init__ import __INIT__
pygame.display.set_caption("Pause")
pygame.init()
screen=pygame.display.set_mode((1920/2,1080/2),pygame.RESIZABLE)
def PAUSE():
running=True
while running:
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
__INIT__("menu")
if event.key == pygame.K_h:
from __init__ import hello
hello()
screen.blit(pygame.image.load("docs/D_effect.png"),(0,0))
pygame.display.update()
PAUSE()
init file
def __INIT__(a):
if a=="pause":
from pause import PAUSE
PAUSE()
if a=="menu":
from endless import menu
menu()
I don't know what is causing this issue because it only does it one time I am a beginner it might be a silly mistake I am sorry if that happens
in any case, if u find it difficult to understand my problem please run the endless file in Space_invaders/Space_invaders/endless.py
provided here
https://drive.google.com/file/d/1FUhGNdXp4CgYcr9PAfey-6ElZhVYMKem/view?usp=sharing
The problem is recursion. menu calls PAUSE, PAUSE calls menu:
menu
|
-> PAUSE
|
-> menu
|
-> PAUSE
|
...
You don't need the extra application loop for PAUSE at all. Just add use game_state variable. e.g.:
import pygame
pygame.display.set_caption("Endless")
pygame.init()
screen=pygame.display.set_mode((1920/2,1080/2),pygame.RESIZABLE)
def menu():
bg = pygame.image.load("docs/bg.png")
bg_pause = pygame.image.load("docs/D_effect.png")
game_state = 'running'
while game_state != 'quit':
if game_state == 'pause':
screen.blit(bg_pause, (0,0))
else:
screen.blit(bg, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_state = 'quit'
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
if game_state == 'running':
game_state = 'pause'
else:
game_state = 'running'
if game_state == 'running':
# draw game scene
# [...]
pass
pygame.display.update()
pygame.quit()
quit()
menu()
Do not load the background images in every frame. This causes lagging. pygame.image.load is a very time consuming process, the image file has to be loaded from the volume and decoded. Load the images before the application loop and use them in the loop.
I use this code to get a separate position of each left click on pygame:
for event in pygame.event.get():
if event.type==QUIT:
running=False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = event.pos
I use mouse_x and mouse_y for drawing , but they are always change. So, how to get an exact position of each click on a screen in pygame and to use them to draw ?
Thank you
1. To get the position when the mouse is clicked
You can use pygame.event.get() to get the position at the exact frame when you begin to press the button like that:
import pygame
from pygame.locals import * # import constants like MOUSEBUTTONDOWN
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == MOUSEBUTTONDOWN and event.button = 0: # detect only left clicks
print(event.pos)
pygame.display.flip()
pygame.quit()
exit()
2. To get the position each frame
In this case, you can use pygame.mouse.get_pos() like that:
import pygame
from pygame.locals import * # import constants like MOUSEBUTTONDOWN
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
print(pygame.mouse.get_pos())
pygame.display.flip()
pygame.quit()
exit()
If you want to get the mouse position only if the left button is pressed:
Place the line print(pygame.mouse.get_pos()) in if pygame.mouse.get_pressed()[0]::
...
if pygame.mouse.get_pressed()[0]: # if left button of the mouse pressed
print(pygame.mouse.get_pos())
...
This code actually detects all kinds of mouse clicks, if you just want the left clicks you can add this to your if statement:
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
You are also not getting the coordinates the right way, you need to write it like this:
mouse_x, mouse_y = pygame.mouse.get_pos()
If you need to use all the clicks that are happening you need to store the x_mouse and y_mouse to a log which you can do like this:
# This outside the pygame loop
mouse_clicks = []
# This inside the pygame loop
for event in pygame.event.get():
if event.type==QUIT:
running=False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
mouse_clicks.append(pygame.mouse.get_pos())
Now you have a list of tuples with all x,y coordinates for all clicks
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
I have some python code that uses a pygame window to establish which key is being pressed. When a key is pressed, the code heads off and does things before coming back to see what the next key pressed might be.
The problem I have is that if the user presses a key repeatedly, even while the 'code heads off and does things', pygame seems to remember what has been pressed rather than waiting for the next keypress. What I want is for the code to ignore any keypresses while the 'go and do stuff' is done then once that's finished, get the next keypress. Hope this makes sense!
import pygame
import time
pygame.init()
screen = pygame.display.set_mode((450,282))
screen.fill((0,0,0))
pygame.display.flip()
clock = pygame.time.Clock()
done = False
def go_and_do_things():
print("doing things")
time.sleep(2)
print("things done")
# Loop as long as done == False
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.KEYDOWN:
keypressedcode = event.key # This is the ASCII code
print("keypressedcode is " + str(keypressedcode))
go_and_do_things()
elif event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
clock.tick(60)
time.sleep(4)
pygame.quit()
You could use pygame.event.clear. As written below, it will discard any keypresses during go_and_do_things().
while not done:
for event in pygame.event.get(): # User did something
# Any key down
if event.type == pygame.KEYDOWN:
keypressedcode = event.key # This is the ASCII code
print("keypressedcode is " + str(keypressedcode))
go_and_do_things()
pygame.event.clear(eventtype=[pygame.KEYDOWN,
pygame.KEYUP)
elif event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
clock.tick(60)
This is a fairly simple problem, you just need to add another
event.type for keyup. You also need to add a variable to make it stop
running which I will label as stopV if event.type == pygame.KEYUP:
stopV = True This should let you instantly stop it when you want to. edit because I want to reword this:
Re-doing this to make it more clear.
import pygame
import time
pygame.init()
screen = pygame.display.set_mode((450,282))
screen.fill((0,0,0))
pygame.display.flip()
clock = pygame.time.Clock()
done = False
unClick = False
def go_and_do_things():
if unClick == False
print("hello")
# do anything you want in the function here
else
return
while not done:
for event in pygame.event.get(): # User did something
# Any key down
if event.type == pygame.KEYDOWN:
keypressedcode = event.key # This is the ASCII code
print("keypressedcode is " + str(keypressedcode))
go_and_do_things()
if event.type == pygame.KEYUP:
unClick == True
elif event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
clock.tick(60)
I'm trying to play and stop a music in my main page.
It's kind of weird.
From my code,
if the user press "m", suppose, the music should be off.
However, the music didn't off. It continue
UnboundLocalError: local variable 'music_playing' referenced before assignment
Can someone help me with my code?
pickUpSound = pygame.mixer.music.load('test.mp3')
pygame.mixer.music.play(-1)
music_playing = True
def mainMenu():
main = pygame.image.load('menu.jpg')
screen.blit(main,(0,0))
while True:
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == KEYDOWN:
if event.key == ord('m'):
if music_playing:
pygame.mixer.music.stop()
else:
pygame.mixer.music.play(-1)
music_playing = not music_playing
As it is written, event.type should be simultaneously equal to KEYDOWN and pygame.K_KP_ENTERat the same time. The second should be event.key instead of event.type.
if event.key == pygame.K_KP_ENTER:
EDIT
There seems to be something wrong with the "keypad enter" key, I commented the problematic line (maybe try with another key, for example, I used K_a, and was able to start/stop by pressing "a")
import pygame
def mainMenu():
pygame.display.init()
pygame.display.set_mode([128,128])
screen = pygame.display.get_surface()
#
pygame.mixer.init()
pickUpSound = pygame.mixer.music.load('test.mp3')
pygame.mixer.music.play(-1)
music_playing = True
#
main = pygame.image.load('menu.jpg')
screen.blit(main,(0,0))
while True:
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
#if event.key == pygame.K_KP_ENTER:
if music_playing:
pygame.mixer.music.stop()
print "stopping"
else:
pygame.mixer.music.play(-1)
print "playing"
music_playing = not music_playing
mainMenu()
n.b. When running this code, I see the messages "playing" and "stopping" each time I press any key.
With if event.key == pygame.K_a: the music should start/stop by pressing "a".