Related
Im trying to make a game with pygame where I can click a sprite then click somewhere on the screen for the sprite to move towards. So far, I'm able to click the sprite and get a response but I'm not sure how to tell the sprite to go to a given location where I click. I've seen something online with sprite.goal but I can't seem to make it work.
This is what I have
if event.type==pygame.MOUSEBUTTONDOWN:
pos=pygame.mouse.get_pos()
#White is a rectangle
if White.collidepoint(pos):
Moving=True
elif Moving==True:
#This is where I would tell it to move to pos
I'll show you a very simple example. Write a function that moves a point 1 step to a target point and returns the new position:
def move_to_target(pos, target):
x, y = pos
if x < target[0]:
x += 1
elif x > target[0]:
x -= 1
if y < target[1]:
y += 1
elif y > target[1]:
y -= 1
return (x, y)
Set a new target when the mouse button is pressed and call the function at each frame:
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
def move_to_target(pos, target):
x, y = pos
if x < target[0]:
x += 1
elif x > target[0]:
x -= 1
if y < target[1]:
y += 1
elif y > target[1]:
y -= 1
return (x, y)
my_sprite = pygame.Surface((20, 20), pygame.SRCALPHA)
pygame.draw.circle(my_sprite, (255, 255, 0), (10, 10), 10)
pos = (200, 200)
target = (200, 200)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
target = event.pos
pos = move_to_target(pos, target)
window.fill(0)
window.blit(my_sprite, pos)
pygame.display.flip()
clock.tick(100)
pygame.quit()
exit()
For variable speed and a straighter and smoother movement, you need to tweak the function. See How to make smooth movement in pygame.
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
LERP_FACTOR = 0.05
minimum_distance = 0
maximum_distance = 100
def move_to_target(pos, target):
target_vector = pygame.math.Vector2(*target)
follower_vector = pygame.math.Vector2(*pos)
new_follower_vector = pygame.math.Vector2(*pos)
distance = follower_vector.distance_to(target_vector)
if distance > minimum_distance:
direction_vector = (target_vector - follower_vector) / distance
min_step = max(0, distance - maximum_distance)
max_step = distance - minimum_distance
step_distance = min_step + (max_step - min_step) * LERP_FACTOR
new_follower_vector = follower_vector + direction_vector * step_distance
return (new_follower_vector.x, new_follower_vector.y)
my_sprite = pygame.Surface((20, 20), pygame.SRCALPHA)
pygame.draw.circle(my_sprite, (255, 255, 0), (10, 10), 10)
pos = (200, 200)
target = (200, 200)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
target = event.pos
pos = move_to_target(pos, target)
window.fill(0)
window.blit(my_sprite, pos)
pygame.display.flip()
clock.tick(100)
pygame.quit()
exit()
This question already has an answer here:
How can I add an image or icon to a button rectangle in Pygame?
(1 answer)
Closed 1 year ago.
How can I stick an image to a rectangle? I think it has something to do with the blit function. I want to blit the image onto the rectangle on line 50.
import pygame
import sys
pygame.init()
FPS = 60
start_smallfont = pygame.font.SysFont('Corbel', 45)
start_text = start_smallfont.render('Start', True, (255, 255, 255))
rect_smallfont = pygame.font.SysFont('Corbel', 33)
rect_text = rect_smallfont.render('You', True, (255, 255, 255))
x = 375
y = 335
vel = 0.1
startWIDTH, startHEIGHT = 170, 80
screenWIDTH, screenHEIGHT = 800, 720
WIN = pygame.display.set_mode((screenWIDTH, screenHEIGHT))
pygame.display.set_caption(":D")
def main():
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if 800/2-85 <= mouse[0] <= 800/2-85+startWIDTH and 720/2-40 <= mouse[1] <= 720/2-40+startHEIGHT:
clock.tick(FPS)
run = False
while True:
global x, y
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
WIN.fill((0, 0, 0))
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel:
x -= vel
if keys[pygame.K_RIGHT] and x < screenWIDTH - 50 - vel:
x += vel
if keys[pygame.K_UP] and y > vel:
y -= vel
if keys[pygame.K_DOWN] and y < screenHEIGHT - 50 - vel:
y += vel
pygame.draw.rect(WIN, (255, 0, 0), (x, y, 50, 50))
pygame.display.update()
mouse = pygame.mouse.get_pos()
if 800/2-85 <= mouse[0] <= 800/2-85+startWIDTH and 720/2-40 <= mouse[1] <= 720/2-40+startHEIGHT:
pygame.draw.rect(WIN, (255, 91, 91), (800/2-85, 720/2-40, startWIDTH, startHEIGHT))
else:
pygame.draw.rect(WIN, (255, 0, 0), (800/2-85, 720/2-40, startWIDTH, startHEIGHT))
WIN.blit(start_text, (800/2-85+42,720/2-40+20))
pygame.display.update()
if __name__ == "__main__":
main()
Any basic tutorial like this one shows how to do it, so it's not clear what you're having trouble with, since you didn't specify what issues you're having. This should work in your code though:
# goes at the top of the script:
image_to_draw = pygame.image.load('something.png')
# to draw the image:
WIN.blit(image_to_draw, (x, y, 50, 50))
I'm trying to write my first game in pygame and successfully made a title screen, but can't find a way to make the 'play' button take the user to the actual gameplay. I have a function dedicated to the title screen, and when the user clicks the play button it stops the title screen loop and starts the gameplay loop, although the gameplay loop code doesn't work. The title screen just freezes and the game doesn't start. I also have never used Stack overflow so I'll just paste my code here I guess:
import sys
import random
pygame.init()
# title
game_title = 'GAME-TITLE'
# set display
win = pygame.display.set_mode((750, 500))
pygame.display.set_caption(game_title)
# load images
cloud = pygame.image.load('999-cloud-clipart-free-download-transparent-png-cloud-clipart-cloud-clipart-transparent-1044_592.png')
cloud = pygame.transform.scale(cloud, (128, 72))
# clock
clock = pygame.time.Clock()
# font
pygame.font.init()
font = pygame.font.SysFont('verdanaboldttf', 60)
font_2 = pygame.font.SysFont('timesnewromanttf', 30)
# colors
red = (255, 0, 0)
blue = (0, 0, 255)
green = (0, 255, 0)
white = (255, 255, 255)
light_blue = (173, 216, 230)
blue = (48, 131, 159)
navy = (0, 0, 200)
black = (0, 0, 0)
# clouds
cloud_values = []
i = 0
while i < 10:
cloud_values.append([random.randint(-750, -80), random.randint(-50, 550)])
i += 1
def title_screen():
run_title = True
run = True
show_help = False
play_game = False
while run_title:
clock.tick(10)
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
play_button = pygame.draw.rect(win, blue, pygame.Rect(150, 175, 450, 75))
help_button = pygame.draw.rect(win, blue, pygame.Rect(150, 275, 450, 75))
quit_button = pygame.draw.rect(win, blue, pygame.Rect(150, 375, 450, 75))
text = font_2.render('PLAY', True, white)
text_2 = font_2.render('HELP', True, white)
text_3 = font_2.render('QUIT', True, white)
title = font.render(game_title, True, navy)
win.blit(text, (340, 197))
win.blit(text_2, (340, 297))
win.blit(text_3, (340, 397))
win.blit(title, (165, 60))
for i in range(len(cloud_values)):
win.blit(cloud, (cloud_values[i][0], cloud_values[i][1]))
cloud_values[i][0] += 10
if cloud_values[i][0] > 760:
cloud_values[i][0] = random.randint(-750, -80)
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
run = False
pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
if pos[0] > 150 and pos[0] < 600 and pos[1] > 175 and pos[1] < 250:
play_game = True
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 275 and pos[1] < 375:
show_help = True
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 375 and pos[1] < 450:
run = False
if pos[0] > 150 and pos[0] < 600 and pos[1] > 175 and pos[1] < 250:
pygame.draw.rect(win, blue, pygame.Rect(145, 170, 460, 85))
win.blit(text, (340, 197))
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 275 and pos[1] < 375:
pygame.draw.rect(win, blue, pygame.Rect(145, 270, 460, 85))
win.blit(text_2, (340, 297))
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 375 and pos[1] < 450:
pygame.draw.rect(win, blue, pygame.Rect(145, 370, 460, 85))
win.blit(text_3, (340, 397))
if play_game or show_help or not run:
run_title = False
pygame.display.flip()
return run_title, play_game, run, show_help
def game_play():
run_game = True
run = True
x = 10
while run_game:
# set new background
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
# run gameplay here
return run
def show_help_screen():
show_help = True
while show_help:
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
# show help_screen
def show_results_screen():
run = False
show_results = True
while show_results:
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
# show results
return run
def run_game(run_title, play_game, run, show_help):
run = True
while run:
if play_game:
game_play()
show_results = True
elif show_help:
show_help_screen()
run_title = True
elif show_results:
run = show_results_screen()
pygame.quit()
sys.exit()
run_title, play_game, run, show_help = title_screen()
run_game(run_title, play_game, run, show_help)```
I went through your code, and I haven't seen an update once.
So since it's your first here's a quick lesson:
when there is any movement, any changes, anything that is changing on your window it won't show up unless you update it, using:
pygame.display.update()
or
pygame.display.flip()
When outputting things, think of them as layers, if you output one image, and then a second image. The first image won't show.
(That's if they are the same size but you know what I mean.)
This question already has answers here:
PyInstaller, spec file, ImportError: No module named 'blah'
(3 answers)
Pyinstaller Unable to access Data Folder
(1 answer)
Python - pygame error when executing exe file
(3 answers)
Closed 2 years ago.
I have been at this for about 2 hours now and I am getting quite frustrated, I have created a pygame file which doesn't use any external fonts or images (which i know is the main issue on why the game screen usually crashes) however I run mine and in the console I get the usual Hello from pygame community and then my game window pops up for roughly a second ad then disappears again with no error messages in the console.
I even installed OBS just to check if the error message was popping up too fast for me to see however there is no error message in sight. I also tried turning on Debug in the .spec file however everything seemed normal (To be fair this is my first time converting a .py to a .exe so i dont really know what I am looking for when it comes to the debug)
I also tried using cx_freeze but I just kept getting this error when building
"TypeError: expected str, bytes or os.PathLike object, not NoneType" and all the fixes I could find were for Pyinstaller not cx_freeze, ideally i would prefer to use cx_freeze but I cant even build an exe with that at least with pyinstaller I have an exe to show (even if it is broken)
This is my command window when I run the exe just before it crashes, nothing more is printed after this
My code is as follows :
import random
import pygame
#import matplotlib.pyplot as plt
from pygame.locals import *
import time
import numpy as np
import sys
import os
pygame.init()
# Window details
windowWidth = 1000
windowHeight = 600
pixSize = 2
FPS = 60
numberofcells = 100
screen = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption("Infection Game")
class Cell:
def __init__(self):
self.xPos = random.randrange(1, windowWidth)
self.yPos = random.randrange(1, windowHeight)
self.speed = 2
self.isInfected = False
self.infectionRange = 5
self.move = [None, None]
self.direction = None
def cellDraw(self):
if not self.isInfected:
pygame.draw.rect(screen, (255, 255, 255), (self.xPos, self.yPos, pixSize, pixSize), 0)
else:
pygame.draw.rect(screen, (0, 255, 0), (self.xPos, self.yPos, pixSize, pixSize), 0)
def cellMovement(self):
directions = {"S": ((-1, 2), (1, self.speed)), "SW": ((-self.speed, -1), (1, self.speed)),
"W": ((-self.speed, -1), (-1, 2)), "NW": ((-self.speed, -1), (-self.speed, -1)),
"N": ((-1, 2), (-self.speed, -1)), "NE": ((1, self.speed), (-self.speed, -1)),
"E": ((1, self.speed), (-1, 2)),
"SE": ((1, self.speed), (1, self.speed))} # ((min x, max x)(min y, max y))
directionsName = ("S", "SW", "W", "NW", "N", "NE", "E", "SE") # possible directions
if random.randrange(0, 5) == 2: # move about once every 5 frames
if self.direction is None: # if no direction is set, set a random one
self.direction = random.choice(directionsName)
else:
a = directionsName.index(self.direction) # get the index of direction in directions list
b = random.randrange(a - 1,
a + 2) # set the direction to be the same, or one next to the current direction
if b > len(directionsName) - 1: # if direction index is outside the list, move back to the start
b = 0
self.direction = directionsName[b]
self.move[0] = random.randrange(directions[self.direction][0][0], directions[self.direction][0][1]) + 0.35
self.move[1] = random.randrange(directions[self.direction][1][0], directions[self.direction][1][1]) + 0.35
if self.xPos < 5 or self.xPos > windowWidth - 5 or self.yPos < 5 or self.yPos > windowHeight - 5: # if cell is near the border of the screen, change direction
if self.xPos < 5:
self.direction = "E"
elif self.xPos > windowWidth - 5:
self.direction = "W"
elif self.yPos < 5:
self.direction = "S"
elif self.yPos > windowHeight - 5:
self.direction = "N"
self.move[0] = random.randrange(directions[self.direction][0][0], directions[self.direction][0][1]) + 0.35
self.move[1] = random.randrange(directions[self.direction][1][0], directions[self.direction][1][1]) + 0.35
if self.move[0] is not None: # add the relative coordinates to the cells coordinates
self.xPos += self.move[0]
self.yPos += self.move[1]
def Infect(self, uninfected, uninfected_array):
indices = np.greater(uninfected_array[:, 0], self.xPos - self.infectionRange) * \
np.greater(self.xPos + self.infectionRange, uninfected_array[:, 0]) * \
np.greater(uninfected_array[:, 1], self.yPos - self.infectionRange) * \
np.greater(self.yPos + self.infectionRange, uninfected_array[:, 1])
for i in np.where(indices)[0]:
uninfected[i].isInfected = True
font = pygame.font.SysFont(None, 20)
def drawText(text, font ,colour, surface, x, y):
textobj = font.render(text, 1 , colour)
textrect = textobj.get_rect()
textrect.topleft = (x,y)
surface.blit(textobj,textrect)
def main_menu(numberofcells):
while True:
screen.fill((0,0,0))
drawText('main menu', font, (255, 255, 255), screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 100, 200, 50)
button_2 = pygame.Rect(50, 200, 200, 50)
if button_1.collidepoint((mx, my)):
if click:
gameLoop(numberofcells)
if button_2.collidepoint((mx, my)):
if click:
numberofcells = options(numberofcells)
pygame.draw.rect(screen, (255, 0, 0), button_1)
drawText('start sim', font, (0,0,0), screen, 127, 120)
pygame.draw.rect(screen, (255, 0, 0), button_2)
drawText('options', font, (0,0,0), screen, 130, 220)
click = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
if event.type == MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.update()
pygame.time.Clock().tick(FPS)
def options(numberofcells):
running = True
while running:
screen.fill((0,0,0))
drawText('options - press ESC to return to menu', font, (255, 255, 255), screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 300, 200, 50)
button_2 = pygame.Rect(50, 400, 200, 50)
pygame.draw.rect(screen, (255, 0, 0), button_1)
drawText('100 cells', font, (0,0,0), screen, 127, 320)
pygame.draw.rect(screen, (255, 0, 0), button_2)
drawText('1000 cells', font, (0,0,0), screen, 127, 420)
if button_1.collidepoint((mx, my)):
if optclick:
numberofcells = 100
pygame.draw.rect(screen, (139, 0, 0), button_1)
if button_2.collidepoint((mx, my)):
if optclick:
numberofcells = 1000
pygame.draw.rect(screen, (139, 0, 0), button_2)
optclick = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
if event.type == MOUSEBUTTONDOWN:
if event.button == 1:
optclick = True
pygame.display.update()
pygame.time.Clock().tick(FPS)
return(numberofcells)
def gameLoop(numberofcells):
startTime = time.time()
xgraph = []
ygraph = []
cellList = []
for i in range(numberofcells):
cell = Cell()
cellList.append(cell)
cellList[0].isInfected = True
running = True
while running:
infectList = []
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
screen.fill((0, 0, 0))
for i in cellList:
i.cellDraw()
i.cellMovement()
infected = 0
uninfected = [i for i in cellList if not i.isInfected]
uninfected_array = np.array([[i.xPos, i.yPos] for i in uninfected])
if len(uninfected) > 0:
for i in cellList:
if i.isInfected:
i.Infect(uninfected, uninfected_array)
infected += 1
if infected == 0:
infected = len(cellList) - len(uninfected)
xgraph.append(time.time() - startTime)
ygraph.append(infected)
pygame.display.update() # update display
pygame.time.Clock().tick(FPS) # limit FPS
# figured this is what you wanted to do ;)
#plt.plot(xgraph, ygraph)
#plt.xlabel('time (s)')
#plt.ylabel('infected')
#plt.show()
main_menu(numberofcells)
I've been trying to make a game, and everything in there works so far except that the pause button , that when pressed the button P should pause and when pressed S should continue. I kinda understand the problem such that once in enters the while loop in the main code it wont get out. I tried putting the pause function inside the while loop. Please do help or provide tips to fix if possible thank you.
import pygame
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
Blue = (2,55,55)
def recursive_draw(x, y, width, height):
""" Recursive rectangle function. """
pygame.draw.rect(screen, WHITE,
[x, y, width, height],
1)
speed = [10,0]
rect_change_x = 10
rect_change_y = 10
# Is the rectangle wide enough to draw again?
if (width > 25):
# Scale down
x += width * .1
y += height * .1
width *= .8
height *= .8
# Recursively draw again
recursive_draw(x, y, width, height)
def recursive_draw2(x, y, width, height):
""" Recursive rectangle function. """
pygame.draw.rect(screen, Blue,
[x, y, width, height],
1)
speed = [10,0]
rect_change_x = 10
rect_change_y = 10
# Is the rectangle wide enough to draw again?
if (width > 25):
x += width * .1
y += height * .1
width *= .8
height *= .8
# Recursively draw again
recursive_draw2(x, y, width, height)
def paused():
screen.fill(black)
largeText = pygame.font.SysFont("comicsansms",115)
TextSurf, TextRect = text_objects("Paused", largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
while pause:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
#gameDisplay.fill(white)
button("Continue",150,450,100,50,green,bright_green,unpause)
button("Quit",550,450,100,50,red,bright_red,quitgame)
pygame.display.update()
clock.tick(15)
pygame.init()
#rectanglelist = [big()]
# Set the height and width of the screen
size = [700, 500]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
black=(0,0,0)
end_it=False
time = 100
USEREVENT = 0
pygame.time.set_timer(USEREVENT+1, 10)
milliseconds = 0
seconds = 0
start_it = False
while (end_it==False):
screen.fill(black)
myfont=pygame.font.SysFont("Britannic Bold", 40)
nlabel=myfont.render("Welcome to "+ " Jet shooter ", 1, (255, 0, 0))
label=myfont.render("Click on the mouse to start ", 1, (255, 0, 0))
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
end_it=True
screen.blit(nlabel,(200, 100))
screen.blit(label, (170,300))
pygame.display.flip()
while (start_it==False):
screen.fill(black)
myfont2=pygame.font.SysFont("Britannic Bold", 40)
label2=myfont2.render("Ready?", 1, (255, 0, 0))
screen.blit(label2, (300,250))
pygame.display.flip()
pygame.time.wait(3000)
start_it = True
fall = False
while (fall==False):
nlist = [3,2,1]
for i in (nlist):
screen.fill(black)
n = str(i)
myfont3=pygame.font.SysFont("Britannic Bold", 40)
score = myfont3.render(n,1,(255,0,0))
screen.blit((score), (350,250))
pygame.display.flip()
pygame.time.wait(1000)
screen.fill(black)
myfont4=pygame.font.SysFont("Britannic Bold", 40)
label4=myfont3.render("GOOO!!!", 1, (255, 0, 0))
screen.blit(label4, (300,250))
pygame.display.flip()
pygame.time.wait (1000)
fall = True
pause = 0
b = 0
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.KEYUP:
if event.key==K_p:
pause=True
if pause == True:
screen.fill(black)
font=pygame.font.SysFont("Britannic Bold", 40)
nlabelBB=myfont.render("Pause", 1, (255, 0, 0))
screen.blit(nlabelBB,(200, 100))
pygame.display.flip()
# Set the screen background
screen.fill(BLACK)
flip = 1
a = 0
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
recursive_draw(0, 0, 700, 500)
recursive_draw2(35,25, 625, 450)
**###I TRIED TO PUT THE PAUSE GAME HERE AND IF PRESSED P PAUSE AND S CONTINUE
while a == 0 :
if flip == 1 :
recursive_draw(35,25,625,450)
recursive_draw2(0, 0, 700, 500)
flip = flip + 1
pygame.display.flip()
if event.type == pygame.KEYUP:
if event.key==K_p:
a = 1
screen.fill(black)
font=pygame.font.SysFont("Britannic Bold", 40)
nlabelBB=myfont.render("Pause", 1, (255, 0, 0))
screen.blit(nlabelBB,(200, 100))
pygame.display.flip()
if event.key==K_s:
a = 0
if flip == 2 :
recursive_draw(0, 0, 700, 500)
recursive_draw2(35, 25, 625, 450)
flip = flip - 1
pygame.display.flip()
if event.type == pygame.KEYUP:
if event.key==K_p:
a = 1
screen.fill(black)
font=pygame.font.SysFont("Britannic Bold", 40)
nlabelBB=myfont.render("Pause", 1, (255, 0, 0))
screen.blit(nlabelBB,(200, 100))
pygame.display.flip()
if event.key==K_s:
a = 0**
if event.type == pygame.QUIT:
done = True
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 60 frames per second
clock.tick(20)
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
Just use a single game loop for everything and keep track of the current state (e.g. main menu, pause screen, game scene) of your game..
Here's an example where we keep track of the state by a simple variable called state and act in our game loop accordingly:
import pygame, math, itertools
def magnitude(v):
return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))
def sub(u, v):
return [u[i]-v[i] for i in range(len(u))]
def normalize(v):
return [v[i]/magnitude(v) for i in range(len(v))]
pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
path = itertools.cycle([(26, 43), (105, 110), (45, 225), (145, 295), (266, 211), (178, 134), (250, 56), (147, 12)])
target = next(path)
ball, speed = pygame.rect.Rect(target[0], target[1], 10, 10), 3.6
pause_text = pygame.font.SysFont('Consolas', 32).render('Pause', True, pygame.color.Color('White'))
RUNNING, PAUSE = 0, 1
state = RUNNING
while True:
for e in pygame.event.get():
if e.type == pygame.QUIT: break
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_p: state = PAUSE
if e.key == pygame.K_s: state = RUNNING
else:
screen.fill((0, 0, 0))
if state == RUNNING:
target_vector = sub(target, ball.center)
if magnitude(target_vector) < 2:
target = next(path)
else:
ball.move_ip([c * speed for c in normalize(target_vector)])
pygame.draw.rect(screen, pygame.color.Color('Yellow'), ball)
elif state == PAUSE:
screen.blit(pause_text, (100, 100))
pygame.display.flip()
clock.tick(60)
continue
break
As you can see, the rectangle keeps moving until you press P, which will change the state to PAUSE; and a simple message will now be displayed instead of drawing/moving the rectangle further.
If you press S the state switches back to the normal mode; all done in a single game loop.
Further reading:
Pygame level/menu states
Mulitple Displays in Pygame
Trying to figure out how to track Pygame events and organize the game's functions