I am making a game that shows game over on screen at the end of the game and if the player presses any key, the game starts again.
Game over screen is displayed but the problem is that when I am pressing any key, the game is not starting. I suspect function gameOverScreen() is not returning out of while loop, I could not understand why.
This function is called when the game is over, and it's continuously running until the player press any key:
def gameOverScreen():
textFont = pygame.font.Font('freesansbold.ttf',90)
while True:
overSurf = textFont.render('GAME OVER',True,RED)
overRect = overSurf.get_rect()
overRect.center = (WINDOWWIDTH/2,WINDOWHEIGHT/2)
DISPLAYSURF.blit(overSurf,overRect)
drawPressKeyMessage()
checkForKeyPress()
if checkForKeyPress():
pygame.event.get() #clear event queue
return
pygame.display.update()
FPSCLOCK.tick(FPS)
Function to check key press is:
def checkForKeyPress():
if len(pygame.event.get(QUIT)) > 0:
terminate()
keyUpEvents = pygame.event.get(KEYUP)
if len(keyUpEvents) == 0:
return None
else:
return keyUpEvents[0].key
Main function which call all functions is:
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
pygame.display.set_caption('Wormy')
showStartScreen()
while True:
runGame()
showGameOverScreen()
Your keypress handler is called twice.
checkForKeyPress()
if checkForKeyPress():
The first call strips the event queue of kedown events so the second time it is called there is no keypress, so the loop cannot terminate.
There are two solutions:
either: remove the first call - take away the first of these lines:
checkForKeyPress() -- delete this line
if checkForKeyPress():
or: Store the result in a variable and use the variable in the if statement:
keyPress = checkForKeyPress()
if keyPress:
...
Related
So I'm trying to implement a class for a basic game. It woked without the class but now instead of spawning the "coin" it pops up and then immediatly dissapears. No idea as it's in the main loop. I have a moving "player" that works fine.
Here's my code:
class Coin_Class:
def __init__(self):
coin_1 = pygame.Rect(425, 30, 40, 40)
pygame.draw.rect(WIN, YELLOW, coin_1)
pygame.display.update()
# def coin_collect():
# if player.colliderect():
# coin_1.x = random.randint(0, 800)
# coin_1.y = random.randint(0, 250)
# pygame.event.post(pygame.event.Event(coin_collected))
# global score
# score += 1
# print(score)
coin_class = Coin_Class()
# main function loop
def main():
score_check = 0
clock = pygame.time.Clock()
run = True
while run:
# game speed
clock.tick(FPS)
# initialise pygame
pygame.init()
# checking all the events in pygame and looping them
for event in pygame.event.get():
# checking quit function is pressed
if event.type == pygame.QUIT:
run = False
pygame.quit()
exit()
keys_pressed = pygame.key.get_pressed() # recognise key presses
player_movement(keys_pressed, player) # movement function
draw_window() # create window function
coin_class
main()
# runs the main file
if __name__ == "__main__":
main()
Add a draw method to the coin class (also class names per PEP 8 should be in CapitalCase not Capital_Snake_Case so CoinClass):
class Coin_Class:
def __init__(self):
self.coin_1 = pygame.Rect(425, 30, 40, 40)
...
def draw(self):
pygame.draw.rect(WIN, YELLOW, self.coin_1)
And in the loop instead of using
coin_class
you would now use
coin_class.draw()
The rest can stay the same, except remove pygame.init() from the loop and put it somewhere at the start of the code after imports
this script is supposed to move 2 rectangles whenever the cursor gets in one of them, i see them flashing sometimes, but they're not moving, they move right 30 and then they go back to 0
import pygame
pygame.init()
screen= pygame.display.set_mode((700,500))
while True:
ex = pygame.Rect(30,30,60,60)
exz= pygame.Rect(0,30,30,60)
for event in pygame.event.get():
if event.type == 256:
pygame.quit()
if event.type == 1024:
cursor_pos=pygame.mouse.get_pos()
print(cursor_pos[1].__str__()+"=y")
print(cursor_pos[0].__str__()+"=x")
print(exz.x.__str__()+"exz.x"+", "+exz.y.__str__()+"exz.y")
if(cursor_pos[0]+cursor_pos[1]) < ((exz.x+30)+exz.y*3) and (cursor_pos[0]+cursor_pos[1])>30 and cursor_pos[1]<=90 and cursor_pos[1]>=30:
exz.right+=30
ex.right+=30
print("exz:"+exz.x.__str__()+", "+exz.y.__str__())
print("exs:"+ex.x.__str__()+", "+ex.y.__str__())
pygame.display.set_caption("Cursor is in area")
else:
pygame.display.set_caption("Cursor is not in area")
pygame.draw.rect(screen,(255,0,0),ex)
pygame.draw.rect(screen,(0,255,0),exz)
pygame.display.update()
screen.fill((50,50,50))
your last 5 lines should be inside the while loop block, to update the screen.
I don't know if this is what you wanted, but:
import pygame
pygame.init()
screen= pygame.display.set_mode((700,500))
ex = pygame.Rect(30,30,60,60) #this has to be outside of the while loop, otherwise the position resets every time
exz= pygame.Rect(0,30,30,60) #same of ex
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: #I don't know what 256 and 1024 means, but this is way better
pygame.quit()
#This has to be outside the for event loop
cursor_pos=pygame.mouse.get_pos() #you shall update the cursor every fps, and not by a if statement
if ex.collidepoint(cursor_pos) or exz.collidepoint(cursor_pos): #Idk what you did here, but i think this is just way simpler
exz.x+=30
ex.x+=30
pygame.display.set_caption("Cursor is in area")
else:
pygame.display.set_caption("Cursor is not in area")
pygame.draw.rect(screen,(255,0,0),ex) #the draws methods were outside the while loop
pygame.draw.rect(screen,(0,255,0),exz)
pygame.display.update()
screen.fill((50,50,50))
This code moves the two rects whenever the mouse gets inside of one of them.
Your glitching is because ex and exz are inside the while loop, so you were re-setting the position every time. I removed the prints but those were not a problem
my python/Pygame program starts with a button that calls a function and a button that quits the game. I wanna push this first button, then a function gets called one time and after that, it should return to the beginning button screen and let me call the function again by button click. How can I do that? Currently i am only able to click the button, call the function and then the game ends. In the code below you see the most important parts of the code.
def function():
....
def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
done = False
def quit_game(): # A callback function for the button.
nonlocal done
done = True
button1 = create_button(100, 100, 250, 80, 'function', function)
button2 = create_button(100, 200, 250, 80, 'quit', quit_game)
# A list that contains all buttons.
button_list = [button1, button2]
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# This block is executed once for each MOUSEBUTTONDOWN event.
elif event.type == pygame.MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if event.button == 1:
for button in button_list:
# `event.pos` is the mouse position.
if button['rect'].collidepoint(event.pos):
# Increment the number by calling the callback
# function in the button list.
button['callback']()
screen.fill(WHITE)
for button in button_list:
draw_button(button, screen)
pygame.display.update()
clock.tick(30)
main()
What you need here is to isolate each screen/game loop into its own special function:
So, for my button screen I can make a function like this:
def title():
button1 = create_button(100, 100, 250, 80, 'game', game) # This will call the game function later in the file
button2 = create_button(100, 200, 250, 80, 'quit_game', quit_game)
# A list that contains all buttons.
button_list = [button1, button2]
# And so on with the rest of the code...
For the main game, you can do the same:
def game():
button1 = create_button(100, 100, 250, 80, 'Exit', title) # This button will return you to the title
# And whatever else you need
After that, at the end of the file, you can add this:
if __name__ == '__main__':
pygame.init()
title() # Call the title first, and then further functions
pygame.quit()
You will have to note that when you activate the buttons callback, a return afterwards is needed in order to deload that screen, otherwise you would just be layering game loops on top of eachother.
So, during the event loop:
if event.button == 1:
for button in button_list:
# `event.pos` is the mouse position.
if button['rect'].collidepoint(event.pos):
# Increment the number by calling the callback
# function in the button list.
button['callback']()
return # Leave the function now that the new one is called.
I'm currently programming a game in Python 3.6 using Pygame.
My game has a start menu, with a button that is highlighted when hovered over.
When the button is clicked, the start menu disappears and the game starts.
The only problem is, the start button remains... I've tried using boolean values and if statements to make it disappear when the menu does, but to no avail.
To make matters worse, the pygame code that allows the window to be closed doesn't work (highlighted by commenting out). Could anyone help me with these small problems? They seem trivial, but I'm new to pygame and I can't seem to find a fix anywhere.
You will need the pictures below to run the program:
This is the photo of the girl.
This is the background photo.
The code:
#Imports
import sys
import pygame
pygame.init() #Initialise Pygame
#RGB colours
GREY = (128,128,128)
WHITE = (255,255,255)
BLACK = (0,0,0)
#fonts
title_font = pygame.font.Font('freesansbold.ttf',72)
menu_font = pygame.font.Font('freesansbold.ttf',32)
#images
girl_img = pygame.image.load('emily.png')
background_img = pygame.image.load('tech_lab.png')
class Game: #Game Class
def __init__(self): #Constructor
self.size = width, height = (1000,563)
self.screen = pygame.display.set_mode(self.size)
def menu_screen(self): #Menu Screen Function
intro = True
while intro:
## for event in pygame.event.get(): #To close window
## print(event)
## if event.type == pygame.QUIT:
## pygame.quit()
## sys.exit()
self.screen.fill(GREY) #Set background colour
self.screen.blit(title_font.render('EXAMPLE', True, BLACK), (330,100)) #Display game title
start_button = pygame.draw.rect(self.screen, (BLACK), pygame.Rect(410,310,180,55)) #Display start button rect
self.screen.blit(menu_font.render('Play', True, GREY), (425,310)) #Display start button text
pygame.display.flip() #Update display
while True:
pygame.event.get() #Get pygame events
click_pos = pygame.mouse.get_pos() #Get mouse position
if 410+180 > click_pos[0] > 410 and 310+55 > click_pos[1] > 310: #If mouse position within start button rect...
pygame.draw.rect(self.screen, (WHITE), pygame.Rect(410,310,180,55)) #then change colour of start button rect
if (pygame.mouse.get_pressed())[0] == 1: #If start button rect clicked...
start_game(self) #Start main game
else:
pygame.draw.rect(self.screen, (BLACK), pygame.Rect(410,310,180,55)) #Otherwise start button rect colour is black
self.screen.blit(menu_font.render('Play', True, GREY), (425,310))#Display start button text
pygame.display.flip() #Update display
def start_game(game): #Main game function
game.screen.blit(background_img, [0,0]) #Display background image
game.screen.blit(girl_img, [80,25]) #Display image
pygame.display.flip() #Update display
def main():
game = Game() #Instantiate class 'game'
game.menu_screen() #Call menu screen function
main()
This loop within a loop thing is going to cause nothing but problems and has to go:
while intro:
....
while True
....
here is some pseudo code:
Class Game:
def menu_screen():
displaying = True
while displaying:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
# evaluate mouse click
if clicked button
displaying = False
self.game()
# drawing code for your images
pygame.display.flip()
def game():
game_running = True
while game_running:
# game running logic and drawing
def main():
# get the Game setup and call main menu
Basically, have your Game class control everything. it will have a menu function which displays the menu. Then they click the button and it goes to a different function within the game class for the actual game.
The start button was remaining because you never cleared the screen when going into the start_game() function. As far as why the close window button wasn't working, it is because of the loop within a loop as i mentioned above. You were trapped in the inner
while True:
loop and you could never get back to the event checking from above. (The quit code itself is fine, although you don't need pygame.quit() because you are quitting the program entirely with sys.ext())
Short of completely reworking your code, this can get you started on the right track.
I need to kb input onto a pygame screen
at the moment it appears on the idle shell
any advice would be appreciated.
This code is extracted from a larger program
mostly screen based but i need to input some
data (numeric) from the kb at times
import sys
import pygame
from pygame.locals import *
pygame.init()
N= ''
screen = pygame.display.set_mode((600,600))
font= pygame.font.Font(None,40)
screen.fill((255,255,255))
pygame.display.flip
pygame.display.update()
def score(C,y):
SetWnd = font.render( C,True,(0,0,255))
screen.blit(SetWnd, (15, 100+y))
pygame.display.update()
def start():
while True:
name=''
for evt in pygame.event.get():
if evt.type == KEYDOWN:
if evt.unicode.isalnum(): # unicode
name+=evt.unicode
print name,
elif evt.key == K_BACKSPACE:
name = name[:-1]
print name,
elif evt.key == K_RETURN:
return N
elif evt.type == QUIT:
pygame.quit()
sys.exit()
def Pchange(c,y):
block = font.render(N, True, (0,0,0))
rect = block.get_rect()
rect.move_ip(75,100 + y)
screen.blit(block,rect)
pygame.display.flip()
score('wind', 0)
score('elev',20)
N = start()
Pchange(N,0)
Pchange(N,20)
Firstly you draw the score twice, which i assume works well.
The problem lies in you start function.
You are not calling any draw or update function in your while loop.
In your event foreach, you add a digit to name, and exit the while loop when enter is pressed. Then you draw twice with Pchange, but you are the function does not use the right parameters. You have:
def Pchange(c,y):
block = font.render(N, True, (0,0,0))
you are using the global N which is ''. So to fix that, you need to change N to c.
The next problem is that the game quits right after pressing enter. Since you pasted only a part of the program, this might not be the case. If it is, make another while loop, and just wait for the ESC key to call pygame.quit() and sys.exit()