Weird glitching out Pygame Python images - python

I have no idea why when the button is pressed it doesnt just go to the next function. It goes back to the other one its really weird and annoying.
It should go to the whattodo function but it does for like half a second then goes to the other. Anyone know why?
#!/usr/bin/python
import pygame
pygame.init()
screen = pygame.display.set_mode((1400,700))
pygame.display.set_caption("Anti-Docter")
titlescreen = pygame.image.load('titleframe.bmp')
boxinfo = pygame.image.load('boxinfo.bmp')
black = (0,0,0)
white = (255,255,255)
randommommycolor = (255,139,12)
Brown = (102,51,0)
Lighter_Brown = (120,59,5)
def mts(text, textcolor, x, y, fs):
font = pygame.font.Font(None,fs)
text = font.render(text, True, textcolor)
screen.blit(text, [x,y])
def buttonPlay(x,y,w,h,ic,ac):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(screen, ac,(x,y,w,h))
if click[0] == 1:
whattodo()
else:
pygame.draw.rect(screen, ic,(x,y,w,h))
def whattodo():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.blit(boxinfo, (0,0))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.blit(titlescreen, (0,0))
buttonPlay(580, 350, 200, 90, Brown, Lighter_Brown)
mts("Play", black, 620, 365, 80)
pygame.display.update()

Every time your main loop repeats, it calls 'buttonPlay'. There is nothing inside 'whattodo' that changes this behaviour, so 'whattodo' runs once then control flow passes back to the main loop, which just repeats 'buttonPlay'.

Related

Fixing an error where the code goes unresponsive after one cycle

I'm trying to have the for loop run 5 iterations of the code below it but once it runs once and i try to click the rectangle the code goes unresponsive.
I can't see why this is happening so i'm looking for some help.
def Reaction_game():
intro = True
while intro == True:
for event in pygame.event.get():
#Stops game when close is selected
if event.type == pygame.QUIT:
file=open('currentuser.txt', 'w')
file.close()
pygame.quit()
quit()
Reaction_times=[]
for x in range (5):
clicked = False
BackGround = Background("background1.png",[0,0])
screen.fill(white)
screen.blit(BackGround.image, BackGround.rect)
pygame.draw.rect(screen, black,(0,0,1000,55))
Font = pygame.font.SysFont('TitilliumWeb.ttf',72)
Label = Font.render("Get Ready:", 1, white)
screen.blit(Label, (380,0,325,75))
pygame.display.update()
time.sleep(2)
screen.blit(BackGround.image, BackGround.rect)
pygame.draw.rect(screen, black,(0,0,1000,55))
Font = pygame.font.SysFont('TitilliumWeb.ttf',72)
Label = Font.render("Go:", 1, white)
screen.blit(Label, (450,0,325,75))
pygame.display.update()
RectX = randrange(50,950)
RectY = randrange(60,513)
round_rect(screen,(RectX,RectY,75,40),(black),10,5,(white))
pygame.display.update()
TimeStart = time.time()
while clicked !=True:
mouse = pygame.mouse.get_pos()
if RectX+75 > mouse[0] > RectX and RectY+40 > mouse[1] > RectY:
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
TimeEnd = time.time()
ReactionTime = TimeEnd - TimeStart
Reaction_times.append(ReactionTime)
clicked = True
else:
pass
Reaction_game()
I expect the code to run 5 iterations of this little reaction time game but it doesn't even get past the first loop before going unresponsive.
You have to use for event in pygame.event.get(): inside while clicked to get new events from system. Without this you have the same values in event.type and even.button.
Even pygame.mouse.get_pos() can't work correclty because it uses data created by pygame.event.get() (or similar)
If you have event MOUSEBUTTONDOWN, MOUSEBUTTONUP then you have mouse position in event.pos and you don't need pygame.mouse.get_pos()
while not clicked:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if RectX+75 > event.pos[0] > RectX and RectY+40 > event.pos[1] > RectY:
TimeEnd = time.time()
ReactionTime = TimeEnd - TimeStart
Reaction_times.append(ReactionTime)
clicked = True
EDIT:
You can keep Rectangle position and size in pygame.Rect()
RectX = randrange(50,950)
RectY = randrange(60,513)
rect = pygame.Rect(RectX, RectY, 75, 40)
and then you can use rect instead of (RectX,RectY,75,40)
round_rect(screen, rect, black , 10, 5, white)
and you can use rect to check if you clicked in rectangle rect.collidepoint(event.pos)
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if rect.collidepoint(event.pos):
TimeEnd = time.time()
ReactionTime = TimeEnd - TimeStart
Reaction_times.append(ReactionTime)
clicked = True
EDIT: working example with other changes - ie. I use pygame.time.wait() instead of time.sleep() and pygame.time.get_ticks() instead of time.time(). Both use miliseconds instead of seconds.
import pygame
import random
# --- constants ---
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
# --- main ---
pygame.init()
screen = pygame.display.set_mode((1000, 600))
reaction_times= []
for x in range(5):
clicked = False
screen.fill(WHITE)
pygame.draw.rect(screen, BLACK, (0, 0, 1000, 55))
font = pygame.font.SysFont(None, 72)
label = font.render("Get Ready:", 1, WHITE)
screen.blit(label, (380, 0, 325, 75))
pygame.display.update()
pygame.time.wait(2000) # 2000ms = 2s
pygame.draw.rect(screen, BLACK, (0, 0, 1000, 55))
font = pygame.font.SysFont(None, 72)
label = font.render("Go:", 1, WHITE)
screen.blit(label, (450, 0, 325, 75))
pygame.display.update()
x = random.randrange(50, 950)
y = random.randrange(60, 513)
rect = pygame.Rect(x, y, 75, 40)
pygame.draw.rect(screen, BLACK, rect)
pygame.display.update()
time_start = pygame.time.get_ticks()
while not clicked:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if rect.collidepoint(event.pos):
print('clicked')
time_end = pygame.time.get_ticks()
reaction_time = (time_end - time_start)/1000 # convert to seconds
reaction_times.append(reaction_time)
clicked = True
print(reaction_times)
pygame.quit()

Pygame won't quit after calling the function

I'm having some trouble while trying to quit from a function that I made. It just doesn't seem to break the loop. The game opens and I can play around but I can't quit, It just stays there without doing anything and the icon on the task bar goes full yellow.
Here's my code:
import pygame, os, sys, math
black = (0,0,0)
white = (255,255,255)
grey = (128, 128, 128)
gameDisplay = pygame.display.set_mode((800,600))
def game_menu():
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
pygame.display.set_caption(".")
menu = True
events = pygame.event.get()
while menu:
for event in events:
if event.type == pygame.QUIT:
menu = False
pygame.quit()
quit()
DISPLAYSURF = pygame.display.set_mode((800, 600))
DISPLAYSURF.fill(black)
font = pygame.font.Font('MATRIX.ttf',60)
TextSurf, TextRect = text_objects("MATRIX PASA PALABRA", font,white)
TextRect.center = ((600/2),(50))
gameDisplay.blit(TextSurf, TextRect)
#Jugar
button("Jugar",300,200,200,50,None)
button("Instrucciones",300,275,200,50,None)
button("Dificultad",300,350,200,50,None)
button("Salir",300,425,200,50,None)
pygame.display.update()
def text_objects(text, font,color):
textSurface = font.render(text, True, color)
return textSurface, textSurface.get_rect()
def button(msg,x,y,w,h,action=None):
mouse = pygame.mouse.get_pos()
events = pygame.event.get()
if x+w> mouse[0] > (x) and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay,grey,(x,y,w,h))
for event in events:
if event.type ==pygame.MOUSEBUTTONUP and msg=="Salir":
pygame.quit()
quit()
elif event.type==pygame.MOUSEBUTTONUP and msg=="Jugar":
None
else:
pygame.draw.rect(gameDisplay,white,(x,y,w,h))
smalltext= pygame.font.Font("MATRIX.ttf",30)
textsrf,textrct=text_objects(msg,smalltext,black)
textrct.center = ((x+(w/2)),(y+(h/2)))
gameDisplay.blit(textsrf,textrct)
if __name__ == "__main__":
game_menu()
Thanks and sorry for my bad english.
The reason why it doesn't work is that you call pygame.event.get multiple times per frame. The event queue will be emptied after the first call, so the events won't get processed correctly. There should be only one pygame.event.get call per frame.
To fix this problem, you can assign the list of events that pygame.event.get returns to a variable in the main while loop and then pass it to the button function.
while menu:
events = pygame.event.get()
for event in events:
# etc.
button("Jugar",300,200,200,50,events,None)
Add an events parameter to the button function:
def button(msg,x,y,w,h,events,action=None):
mouse = pygame.mouse.get_pos()
if x+w> mouse[0] > (x) and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay,grey,(x,y,w,h))
for event in events:
# etc.
BTW, this button function keeps popping up here again and again, probably because it's a really bad way to implement buttons. I'd recommend a solution similiar to one of these: https://stackoverflow.com/a/47664205/6220679 or search for pygame GUI toolkits (SGC is pretty good).
The others have already mentioned that the indentation in your example is wrong and that sys.exit is a better way to quit than the quit function.
Here's a fixed, complete example:
import pygame, os, sys, math
black = (0,0,0)
white = (255,255,255)
grey = (128, 128, 128)
gameDisplay = pygame.display.set_mode((800,600))
def game_menu():
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
pygame.display.set_caption(".")
DISPLAYSURF = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
menu = True
while menu:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
menu = False
pygame.quit()
sys.exit()
DISPLAYSURF.fill((30, 30, 30))
font = pygame.font.Font(None,60)
TextSurf, TextRect = text_objects("MATRIX PASA PALABRA", font,white)
TextRect.center = ((600/2),(50))
gameDisplay.blit(TextSurf, TextRect)
#Jugar
button("Jugar",300,200,200,50,events,None)
button("Instrucciones",300,275,200,50,events,None)
button("Dificultad",300,350,200,50,events,None)
button("Salir",300,425,200,50,events,None)
pygame.display.update()
clock.tick(60)
def text_objects(text, font,color):
textSurface = font.render(text, True, color)
return textSurface, textSurface.get_rect()
def button(msg,x,y,w,h,events,action=None):
mouse = pygame.mouse.get_pos()
if x+w> mouse[0] > (x) and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay,grey,(x,y,w,h))
for event in events:
if event.type ==pygame.MOUSEBUTTONUP and msg=="Salir":
pygame.quit()
sys.exit()
elif event.type==pygame.MOUSEBUTTONUP and msg=="Jugar":
print("jugar")
else:
pygame.draw.rect(gameDisplay,white,(x,y,w,h))
smalltext= pygame.font.Font(None,30)
textsrf,textrct=text_objects(msg,smalltext,black)
textrct.center = ((x+(w/2)),(y+(h/2)))
gameDisplay.blit(textsrf,textrct)
if __name__ == "__main__":
game_menu()
If you import sys then you can use that to exit your code.
import sys
def game_menu():
menu = True
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
Try adding pygame.display.quit() before the line pygame.quit(). This should close any open displays.
Edit:
The problem is that most of your program isn't inside the while loop. Most importantly, the events = pygame.event.get() isn't inside the while loop so the events are never updated.
Rearranging the code to something like this should work:
def game_menu():
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
pygame.display.set_caption(".")
menu = True
while menu:
events = pygame.event.get()
DISPLAYSURF = pygame.display.set_mode((800, 600))
DISPLAYSURF.fill(black)
font = pygame.font.Font('MATRIX.ttf',60)
TextSurf, TextRect = text_objects("MATRIX PASA PALABRA", font,white)
TextRect.center = ((600/2),(50))
gameDisplay.blit(TextSurf, TextRect)
#Jugar
button("Jugar",300,200,200,50,None)
button("Instrucciones",300,275,200,50,None)
button("Dificultad",300,350,200,50,None)
button("Salir",300,425,200,50,None)
pygame.display.update()
for event in events:
if event.type == pygame.QUIT:
menu = False
pygame.quit()
quit()

Pygame buttons not functioning [duplicate]

This question already has answers here:
Pygame mouse clicking detection
(4 answers)
How can I add an image or icon to a button rectangle in Pygame?
(1 answer)
Closed 2 years ago.
def button(text, x, y, width, height, inactive_color, active_color,action = None):
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
#click1 = pygame.MOUSEBUTTONDOWN()
if x + width > cur[0] > x and y+height > cur[1] > y:
pygame.draw.rect(gameDisplay, active_color, (x,y,width,height))
if click[0] == 1 and action !=None:
if action == "start": #actions define what each thing does. modify the actions for it to do different things.
game_intro()
pygame.display.update()
if action == "play":
scene1()
pygame.display.update()
if action == "next":
scene1_p2()
pygame.display.update()
if action == "next1":
scene1_p3()
pygame.display.update()
if action == "next2":
scene2()
pygame.display.update()
if action == "next3":
scene2_p2()
pygame.display.update()
else:
x + width > cur[0] > x and y+height > cur[1] > y
pygame.draw.rect(gameDisplay, inactive_color, (x,y,width,height))
text_to_button(text,black,x,y,width,height)
def game_title():
title = True
while title:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
gameDisplay.blit(opimg, [0, 0])
message_to_screen("TBN", red, -100, size='large')
pygame.draw.rect(gameDisplay, blue, (380, 500, 230, 50))
text_to_button("Press to Start", red, 450, 500, 100, 50)
mouse = pygame.mouse.get_pos()
#print(mouse)
if 380+230 > mouse[0] > 380 and 500+50 > mouse[1] > 500:
button("Press to Start",380, 500, 230, 50,blue,light_blue,"start")
'''
if event.type == pygame.KEYDOWN:
if event.key == pygame.MOUSEBUTTONDOWN:
title = False
game_intro()
'''
pygame.display.update()
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Welcome to TBN", red, -100, size='large')
message_to_screen('This is a story based RPG',
black,
10)
message_to_screen('By Stephen Wang',
black,
50)
message_to_screen('Assets used not owned by me but by their respective owners.',
black,
100)
button("Play", 420, 550, 150, 50, blue, light_blue,action="play")
pygame.display.update()
def scene1():
scene1= True
mouse_click=False
while scene1 == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(black)
button("I can't hear anything...", 0,700 , 1000, 100, blue,blue,action="next")
pygame.display.update()
def scene1_p2():
scene1= True
while scene1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(black)
button("Where am I?", 0,700 , 1000, 100, blue, blue,action="next1")
pygame.display.update()
def scene1_p3():
scene1= True
while scene1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(black)
button("Slowly, I opened my eyes.", 0,700 , 1000, 100, blue, blue,action="next2")
pygame.display.update()
def scene2():
scene2 = True
while scene2:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
gameDisplay.blit(forest, [0, 0])
button("Nearby, I could hear the sounds of battle.", 0, 700, 1000, 100, blue, blue, action="next3")
pygame.display.update()
def scene2_p2():
scene2 = True
while scene2:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
gameDisplay.blit(forest, [0, 0])
button("Nearby, I could hear the sounds of battle.", 0, 700, 1000, 100, blue, blue, action="next3")
pygame.display.update()
game_title()
game_intro()
So that is the code that I have. I am currently making a choose your own adventure type game for school. Since I'm still new to Pygame, I don't know how to do the textboxes so I create a new screen for each update. I use the button as a textbox, and when it is pressed, it proceeds to the next screen.
However, when I tried to add more screens in, the buttons just straight up won't function at all. Please help!

How do i program a button in python (without Tkinter)?

I've recently started learning Python3 and I was trying to make a game with Python3 by importing pygame. I tried to make a menu and I am having some struggles with it. I just tried to make it seem like its a button by letting the rectangle change color when you hover over it but its not working. I already tried some things but its not working. Anyhow here is the full code: hastebin link.
This is the part where I tried to make a button:
def game_intro():
intro = True
gameDisplay.fill(white)
largeText = pygame.font.Font('freesansbold.ttf', 90)
TextSurf, TextRect = text_objects("Run Abush Run!", largeText)
TextRect.center = ((display_width / 2), (display_height / 2))
gameDisplay.blit(TextSurf, TextRect)
mouse = pygame.mouse.get_pos()
if 150+100 > mouse[0] > 150 and 430+50 > mouse[1] > 430:
pygame.draw.rect(gameDisplay, bright_green, (150,430,100,50))
else:
pygame.draw.rect(gameDisplay, green, (150, 430, 100, 50))
smallText = pygame.font.Font('freesansbold.ttf' ,20)
textSurf, textRect = text_objects("START!", smallText)
textRect.center = ( (150+(100/2)), (450+(430/2)) )
gameDisplay.blit(textSurf, textRect)
pygame.draw.rect(gameDisplay, red, (550, 430, 100, 50))
pygame.display.update()
clock.tick(15)
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
The problem here is that you're only doing your mouseover test once, at the start of the function. If the mouse later moves into your rectangle, it won't matter, because you never do the test again.
What you want to do is move it into the event loop. One tricky bit in PyGame event loops is which code you want to run once per event (the inner for event in… loop), and which you only want to run once per batch (the outer while intro loop). Here, I'm going to assume you want to do this once per event. So:
def game_intro():
intro = True
# ... other setup stuff
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
mouse = pygame.mouse.get_pos()
if 150+100 > mouse[0] > 150 and 430+50 > mouse[1] > 430:
pygame.draw.rect(gameDisplay, bright_green, (150,430,100,50))
else:
pygame.draw.rect(gameDisplay, green, (150, 430, 100, 50))
It looks like some of the other stuff you do only once also belongs inside the loop, so your game may still have some problems. But this should get you past the hurdle you're stuck on, and show you how to get started on those other problems.
Here is a button that should suit your needs:
class Button(object):
global screen_width,screen_height,screen
def __init__(self,x,y,width,height,text_color,background_color,text):
self.rect=pygame.Rect(x,y,width,height)
self.x=x
self.y=y
self.width=width
self.height=height
self.text=text
self.text_color=text_color
self.background_color=background_color
def check(self):
return self.rect.collidepoint(pygame.mouse.get_pos())
def draw(self):
pygame.draw.rect(screen, self.background_color,(self.rect),0)
drawTextcenter(self.text,font,screen,self.x+self.width/2,self.y+self.height/2,self.text_color)
pygame.draw.rect(screen,self.text_color,self.rect,3)
Use the draw function to draw your button, and the check function to see if the button is being pressed.
Implemented into a main loop:
button=Button(x,y,width,height,text_color,background_color,text)
while not done:
for event in pygame.event.get():
if event.type==QUIT:
terminate()
elif event.type==pygame.MOUSEBUTTONDOWN:
if button.check():
#what to do when button is pressed
#fill screen with background
screen.fill(background)
button.draw()
pygame.display.flip()
clock.tick(fps)
This is what i did and it works now:
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
# print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.Font('freesansbold.ttf', 90)
TextSurf, TextRect = text_objects("Run Abush Run!", largeText)
TextRect.center = ((display_width / 2), (display_height / 2))
gameDisplay.blit(TextSurf, TextRect)
mouse = pygame.mouse.get_pos()
# print(mouse)
if 150 + 100 > mouse[0] > 150 and 450 + 50 > mouse[1] > 450:
pygame.draw.rect(gameDisplay, bright_green, (150, 450, 100, 50))
else:
pygame.draw.rect(gameDisplay, green, (150, 450, 100, 50))
pygame.draw.rect(gameDisplay, red, (550, 450, 100, 50))
pygame.display.update()
clock.tick(15)
Thank you for the help #abarnert

Python pygame - avoiding accidental continuous clicking

Edit: added a longer example code.
I'm having trouble with coding buttons in pygame. I'm a newbie to the pygame module, so be gentle.
Basically, the goal is to make a point-and-click telltale kind of game. The player gets presented with two choices each gameloop, ie "go left" or "go right". Accordingly, there are two buttons in each gameloop, all located at the same coordinates.
Here is the function:
import pygame
import os
import time
pygame.init()
display_width= 1280
display_height = 720
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
def button(msg,x, y, w, h, ic, ac, action=None): #message, x y location, width, height, inactive and active colour
if action ==None:
pygame.display.update()
clock.tick(15)
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay, ac,(x,y,w,h))
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
pygame.display.update()
clock.tick(15)
if action == "left1":
game_loop("loop1-1.png",0,0,"left2","left2","","")
else:
pygame.draw.rect(gameDisplay, ic,(x,y,w,h))
smallText = pygame.font.SysFont('timesnewroman',20)
textSurf, textRect = text_objects(msg, smallText, silver)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def game_loop(pic,width,heigth,act1,act2,left,right):
intro = True
while intro:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
gameDisplay.blit(get_image(pic), (0, 0)) #MAIN MENU PIC
button(left,440,450,width,heigth, dark_gray, gray, action=act1)#start nupp
button(right,740,450,width,heigth, dark_gray, gray, action=act2)#exit nupp
pygame.display.update()
clock.tick(15)
The problem occurs when I click the button carelessly, meaning if I don't purposefully click on the left mouse button as fast as I can. Once game_loop1 is called and if I click for a bit longer, the program will read the first click again in this game_loop1 and run the next game_loop and then the next etc. This means the player can accidentally skip through gameloops.
Is there a way to delay the program after the first click(however long it is)? Or maybe a way to include keyup in the function, so it won't count the click in the next gameloop?
Thanks!
I think your original code is a bit too convoluted to fix it and I'll rather show you some better ways to do what you want. You need a finite-state machine to transition between different states/scenes. You can find a simple example with functions as scenes here.
If the logic in your scenes is mostly the same, you could also try to just swap out the data for the scene, for example the background image. Each state/scene needs to know to which new states it can switch, so I put the data into a dictionary of dictionaries. The nested dicts contain the background image of the scene and the connected left and right scenes. When the user presses a button/rect I check if it was the left or right button and then switch to the corresponding scene (subdict) in the states dictionary.
import pygame
pygame.init()
display_width= 1280
display_height = 720
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
# Use uppercase names for constants that should never be changed.
DARK_GRAY = pygame.Color('gray13')
BACKGROUND1 = pygame.Surface((display_width, display_height))
BACKGROUND1.fill((30, 150, 90))
BACKGROUND2 = pygame.Surface((display_width, display_height))
BACKGROUND2.fill((140, 50, 0))
BACKGROUND3 = pygame.Surface((display_width, display_height))
BACKGROUND3.fill((0, 80, 170))
states = {
'scene1': {'background': BACKGROUND1, 'left_scene': 'scene2', 'right_scene': 'scene3'},
'scene2': {'background': BACKGROUND2, 'left_scene': 'scene1', 'right_scene': 'scene3'},
'scene3': {'background': BACKGROUND3, 'left_scene': 'scene1', 'right_scene': 'scene2'},
}
def game_loop():
# The buttons are just pygame.Rects.
left_button = pygame.Rect(440, 450, 60, 40)
right_button = pygame.Rect(740, 450, 60, 40)
# The current_scene is a dictionary with the relevant data.
current_scene = states['scene1']
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEBUTTONDOWN:
# If the left button is clicked we switch to the 'left_scene'
# in the `current_scene` dictionary.
if left_button.collidepoint(event.pos):
current_scene = states[current_scene['left_scene']]
print(current_scene)
# If the right button is clicked we switch to the 'right_scene'.
elif right_button.collidepoint(event.pos):
current_scene = states[current_scene['right_scene']]
print(current_scene)
# Blit the current background.
gameDisplay.blit(current_scene['background'], (0, 0))
# Always draw the button rects.
pygame.draw.rect(gameDisplay, DARK_GRAY, left_button)
pygame.draw.rect(gameDisplay, DARK_GRAY, right_button)
pygame.display.update()
clock.tick(30) # 30 FPS feels more responsive.
game_loop()
pygame.quit()

Categories

Resources