Coding Error with Python - python

I'm trying to code a game in python ( its a school assignment) and I want the game to have multiple screens, for example a title screen, an about screen, and the screen where you get to play the game. However, to keep things simple, I want all these screens to show up on the same window.
Currently, I've been defining commands that are running a specific screen, and telling python to run that command when the variables are correct (i.e. when the user has pressed the button to take them to the next screen). However, all I get is a blackscreen, and python immediately closes. The funny thing is that the log shows no sign of any problems, which is very strange.
If you could help me fix this code, it would be greatly appreciated.
import pygame
import random
name = 'Squash Ninja'
size = (700, 500)
rect_x = 50
rect_y = 50
rect_x1 = 345
rect_y1 = 397
rect_x_change = 10
rect_y_change = 10
rect_x_change1 = -10
rect_y_change1 = -10
vari = 0
#Colours#
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (18, 128, 13)
YELLOW = (234, 255, 0)
ORANGE = (255, 132, 0)
LGREEN = (0,255,0)
PURPLE = (204, 14, 166)
BLACK = (0, 0, 0)
#Starts Pygame#
pygame.init()
#Opens window#
size = (700, 500)
screen = pygame.display.set_mode(size)
#Running Variables#
done = False
title = True
about = False
#Screens#
def title():
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
print('User pressed mouse.')
elif event.type == pygame.KEYDOWN:
print("User pressed a key")
pygame.draw.line(screen, BLUE, [0,0], [100,100], 5)
elif event.type == pygame.KEYUP:
print("User let go of a key.")
elif event.type == pygame.QUIT:
done = True
screen.fill(BLUE)
pygame.draw.rect(screen,BLACK,[200,20,350,100],0)
pygame.draw.rect(screen,GREEN,[280,180,200,50],0)
pygame.draw.rect(screen,GREEN,[280,240,200,50],0)
pygame.draw.rect(screen,GREEN,[280,300,200,50],0)
font = pygame.font.SysFont('Calibri', 45, True, False)
text = font.render("Squash Ninja", True, LGREEN)
screen.blit(text, [255, 75])
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Play", True, YELLOW)
screen.blit(text, [350, 200])
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("About", True, YELLOW)
screen.blit(text, [340, 260])
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Quit", True, YELLOW)
screen.blit(text, [355, 320])
font = pygame.font.SysFont('Calibri', 10, True, False)
text = font.render("Version 1.2", True,WHITE)
screen.blit(text, [650, 470])
font = pygame.font.SysFont('Calibri', 10, True, False)
text = font.render("Created by Adrian Ngai", True,WHITE)
screen.blit(text, [600, 480])
font = pygame.font.SysFont('Calibri', 10, True, False)
text = font.render("Copyright 2014, all rights reserved.", True,WHITE)
screen.blit(text, [555, 490])
mouse = pygame.mouse.get_pos ()
if 280 + 200 > mouse [0] > 280 and 180+50 > mouse[1] > 180:
pygame.draw.rect(screen,LGREEN,[280,180,200,50],0)
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Play", True, RED)
screen.blit(text, [350, 200])
if 280 + 200 > mouse [0] > 280 and 240+50 > mouse[1] > 240:
pygame.draw.rect(screen,LGREEN,[280,240,200,50],0)
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("About", True, RED)
screen.blit(text, [340, 260])
if event.type == pygame.MOUSEBUTTONDOWN:
title = False
about = True
if 280 + 200 > mouse [0] > 280 and 300+50 > mouse[1] > 300:
pygame.draw.rect(screen,LGREEN,[280,300,200,50],0)
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Quit", True, RED)
screen.blit(text, [355, 320])
if event.type == pygame.MOUSEBUTTONDOWN:
done = True
#bouncing rectangle#
pygame.draw.rect(screen, LGREEN, [rect_x, rect_y, 50, 50])
rect_x += rect_x_change
rect_y += rect_y_change
if rect_y > 450 or rect_y < 0:
rect_y_change = rect_y_change * -1
if rect_x > 650 or rect_x < 0:
rect_x_change = rect_x_change * -1
pygame.draw.rect(screen, PURPLE, [rect_x1, rect_y1, 50, 50])
rect_x1 += rect_x_change1
rect_y1 += rect_y_change1
if rect_y1 > 450 or rect_y1 < 0:
rect_y_change1 = rect_y_change1 * -1
if rect_x1 > 650 or rect_x1 < 0:
rect_x_change1 = rect_x_change1 * -1
for i in range(50):
x = random.randrange(0, 800)
y = random.randrange(0, 800)
pygame.draw.circle(screen,WHITE,[x,y],3)
pygame.display.flip()
clock.tick(20)
def about() :
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
print('User pressed mouse.')
elif event.type == pygame.KEYDOWN:
print("User pressed a key")
pygame.draw.line(screen, BLUE, [0,0], [100,100], 5)
if event.type == pygame.QUIT:
done = True
screen.fill(BLUE)
pygame.draw.rect(screen,BLACK,[200,20,350,100],0)
font = pygame.font.SysFont('Calibri', 45, True, False)
text = font.render("About", True, LGREEN)
screen.blit(text, [255, 75])
pygame.draw.rect(screen,GREEN,[280,300,200,50],0)
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Back", True, YELLOW)
screen.blit(text, [355, 320])
mouse = pygame.mouse.get_pos ()
if 280 + 200 > mouse [0] > 280 and 300+50 > mouse[1] > 300:
pygame.draw.rect(screen,LGREEN,[280,300,200,50],0)
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Back", True, RED)
screen.blit(text, [355, 320])
if event.type == pygame.MOUSEBUTTONDOWN:
title = True
about = False
pygame.display.flip()
clock.tick(20)
def done():
while not done:
print()
while done:
pygame.quit()
#Game Loop#
while vari == 0:
done()
while title:
title()
while about:
about()
#Closing Sequence#
print('Test fail :(')
pygame.quit()

I think your problem might be here
done = False
...
def done():
while not done:
print()
while done:
pygame.quit()
Even though you have the variable "done" assigned earlier, you're reassigning it to a function. Because done is no longer false, the function executes the second loop ("while done:") and immediately quits.
To get the behavior you're expecting, you should rename the function done() to something like is_done(). i.e.
def is_done():
while not done:
print()
while done:
pygame.quit()

Related

How do I get my game to loop when calling the function from a button?

I'm trying to fix my game. When the game is over, it calls a crash() function. It gives the user the option to play again or quit. When calling my game_loop function in the "Play Again" button inside the crash() function, the game will not restart. Any suggestions? Thanks in advance.......................
import math
import random
import time
import pygame
from pygame import mixer
# Intialize the pygame
pygame.init()
# next setup the display
display_width = 800
display_height = 600
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('waterbackground.jpg')
# game clock to time frames per second
clock = pygame.time.Clock()
# Sound
mixer.music.load("ocean.wav")
mixer.music.play(-1)
# setup colors needed in the game
black = (0,0,0)
white = (255, 255, 255)
red = (200, 0, 0)
bright_red = (255,0,0)
block_color = (53,115,255)
green = (0,200,0)
bright_green = (0,255,0)
# Caption and Icon
pygame.display.set_caption("Pirate War")
icon = pygame.image.load('pirateship.png')
pygame.display.set_icon(icon)
# cannon
cannonImg = pygame.image.load('cannonball.png')
cannonX = 0
cannonY = 480
cannonX_change = 0
cannonY_change = 10
cannon_state = "ready"
# Player
playerImg = pygame.image.load('cannon.png')
playerX = 370
playerY = 480
playerX_change = 0
# Score
score_value = 0
# add explosion sound
crash_sound = pygame.mixer.Sound("explosion.wav")
# ship
shipImg = []
shipX = []
shipY = []
shipX_change = []
shipY_change = []
num_of_ships = 6
for i in range(num_of_ships):
shipImg.append(pygame.image.load('pirateship.png'))
shipX.append(random.randint(0, 736))
shipY.append(random.randint(50, 150))
shipX_change.append(4)
shipY_change.append(40)
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
testY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
credits_font = pygame.font.Font('freesansbold.ttf', 24)
# text object function called by message display function
def text_objects(text, font):
textSurface = font.render(text, True, white)
return textSurface, textSurface.get_rect()
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER!", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
crash()
def game_credits_text(text):
over_text = over_font.render(text, True, (255, 255, 255))
screen.blit(over_text, (200, 150))
def game_credits_text_small(text):
credits_text = credits_font.render(text, True, (255, 255, 255))
screen.blit(credits_text, (20, 350))
def game_intro_text_small(text):
credits_text = credits_font.render(text, True, (255, 255, 255))
screen.blit(credits_text, (125, 375))
def player(x, y):
screen.blit(playerImg, (x, y))
def ship(x, y, i):
screen.blit(shipImg[i], (x, y))
def fire_cannon(x, y):
global cannon_state
cannon_state = "fire"
screen.blit(cannonImg, (x + 16, y + 10))
def isCollision(shipX, shipY, cannonX, cannonY):
distance = math.sqrt(math.pow(shipX - cannonX, 2) + (math.pow(shipY - cannonY, 2)))
if distance < 27:
return True
else:
return False
# function to setup message display
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf', 70)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2), (display_height/2))
screen.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
def crash():
#add crash sound
pygame.mixer.music.stop()
pygame.mixer.Sound.play(crash_sound)
game_credits_text("Game Over!")
game_credits_text_small("Created by: Dominique Kellam, Hayley Cull and Dewayne Bowen")
while True:
# check for quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill((0, 0, 0))
#add buttons to start screen
button("Play Again",150, 450, 100, 50, green, bright_green, game_loop)
button("Quit",550, 450, 100, 50, red, bright_red, quitgame)
pygame.display.update()
clock.tick(15)
def button(msg, x, y, w, h, ic, ac, action=None):
mouse = pygame.mouse.get_pos() # returns a list of [x,y]
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y: #check is mouse over button
# redraw the rectange with active color when mouseover
pygame.draw.rect(screen, ac, (x, y, w, h))
#check for a click
if click[0] == 1 and action!=None:
action()
else:
pygame.draw.rect(screen, ic, (x, y, w, h))
# now display text on top of button that was just redrawn
smallText = pygame.font.Font('freesansbold.ttf', 20)
TextSurf, TextRect = text_objects(msg, smallText)
TextRect.center = ((x+(w/2)), (y+(h/2)))
screen.blit(TextSurf, TextRect)
def quitgame():
pygame.quit()
quit()
# start screen code
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects("Pirate War", largeText)
game_intro_text_small("[space bar] - fire cannon, [<] [>] arrows to move")
TextRect.center = ((display_width/2), (display_height/2))
screen.blit(TextSurf, TextRect)
#add buttons to start screen
button("Go!",150, 450, 100, 50, green, bright_green, game_loop)
button("Quit",550, 450, 100, 50, red, bright_red, quitgame)
pygame.display.update()
clock.tick(15)
def game_loop():
global playerX
global playerX_change
global cannonX
global cannonY
global cannon_state
global score_value
# Game Loop
running = True
while running:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if cannon_state == "ready":
cannonSound = mixer.Sound("cannon_x.wav")
cannonSound.play()
# Get the current x cordinate of the spaceship
cannonX = playerX
fire_cannon(cannonX, cannonY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# ship Movement
for i in range(num_of_ships):
# Game Over
if shipY[i] > 440:
for j in range(num_of_ships):
shipY[j] = 2000
game_over_text()
break
shipX[i] += shipX_change[i]
if shipX[i] <= 0:
shipX_change[i] = 1 #######SHIP MOVEMENT
shipY[i] += shipY_change[i]
elif shipX[i] >= 736:
shipX_change[i] = -1 ######SHIP MOVEMENT
shipY[i] += shipY_change[i]
# Collision
collision = isCollision(shipX[i], shipY[i], cannonX, cannonY)
if collision:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
cannonY = 480
cannon_state = "ready"
score_value += 1
shipX[i] = random.randint(0, 736)
shipY[i] = random.randint(50, 150)
ship(shipX[i], shipY[i], i)
# cannon Movement
if cannonY <= 0:
cannonY = 480
cannon_state = "ready"
if cannon_state == "fire":
fire_cannon(cannonX, cannonY)
cannonY -= cannonY_change
player(playerX, playerY)
show_score(textX, testY)
pygame.display.update()
game_intro()
You are setting the ship y to 2000 which is > 400 so it just goes back to crash. Change this to zero and it will work.

How to update text appearing on button click in pygame module

I was making a code where on clicking a button, a string will be chosen randomly from myList and be displayed. I am doing this using pygame module. The problem here is that the text does not remain, it just flashes for one frame.
Here's the code:
import pygame
import random
pygame.init()
size = (500, 400)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Project")
bg = pygame.image.load("bg.jpg")
# declaring variables and lists
white = (255, 255, 255)
black = (0, 0, 0)
light_grey = (224, 224, 224)
dark_grey = (200, 200, 200)
text = pygame.font.SysFont("Agency FB", 20)
myList = ["China", "Italy", "Russia", "India", "USA", "Canada", "France", "Japan", "Brazil", "Egypt"]
# text for button
button_text = text.render("Country", True, black)
rb = random.choice(myList)
font = pygame.font.SysFont("Agency FB", 50)
bFont = font.render(str(rb), True, white)
var = True
while var:
screen.blit(bg, (0, 0))
# store mouse position
mouse = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
var = False
# button click
if event.type == pygame.MOUSEBUTTONDOWN:
# pick one from list and blit
if 50 <= mouse[0] <= 50 + 75 and 350 <= mouse[1] <= 350 + 35:
screen.blit(bFont, (50, 100))
# make button
if 50 <= mouse[0] <= 50 + 75 and 350 <= mouse[1] <= 350 + 35:
pygame.draw.rect(screen, dark_grey, (50, 350, 75, 35), 0)
else:
pygame.draw.rect(screen, light_grey, (50, 350, 75, 35), 0)
screen.blit(button_text, (55, 355))
pygame.display.update()
How can I get the text to be there and not vanish in the next frame?
Do not create bFont before the main application loop, but initialize it with None:
bFont = None
Choose and render a random string when the button is pressed:
while var:
# [...]
for event in pygame.event.get():
# [...]
# button click
if event.type == pygame.MOUSEBUTTONDOWN:
# pick one from list and blit
button_rect = pygame.Rect(50, 350, 75, 35)
if button_rect.collidepoint(event.pos):
rb = random.choice(myList)
bFont = font.render(str(rb), True, white)
Draw the text in the main application loop if bFont is set:
var = True
while var:
# [...]
if bFont:
screen.blit(bFont, (50, 100))
pygame.display.update()
Complete example:
import pygame
import random
pygame.init()
size = (500, 400)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Project")
bg = pygame.image.load("bg.jpg")
# declaring variables and lists
white = (255, 255, 255)
black = (0, 0, 0)
light_grey = (224, 224, 224)
dark_grey = (200, 200, 200)
text = pygame.font.SysFont("Agency FB", 20)
myList = ["China", "Italy", "Russia", "India", "USA", "Canada", "France", "Japan", "Brazil", "Egypt"]
# text for button
button_text = text.render("Country", True, black)
button_rect = pygame.Rect(50, 350, 75, 35)
font = pygame.font.SysFont("Agency FB", 50)
bFont = None
var = True
while var:
# store mouse position
mouse = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
var = False
# button click
if event.type == pygame.MOUSEBUTTONDOWN:
# pick one from list and blit
if button_rect.collidepoint(event.pos):
rb = random.choice(myList)
bFont = font.render(str(rb), True, white)
screen.blit(bg, (0, 0))
# make button
if button_rect.collidepoint(mouse):
pygame.draw.rect(screen, dark_grey, (50, 350, 75, 35), 0)
else:
pygame.draw.rect(screen, light_grey, (50, 350, 75, 35), 0)
screen.blit(button_text, (55, 355))
if bFont:
screen.blit(bFont, (50, 100))
pygame.display.update()
Try using another boolean var
if event.type == pygame.MOUSEBUTTONDOWN:
if 50 <= mouse[0] <= 50 + 75 and 350 <= mouse[1] <= 350 + 35:
show_text = True
if show_text:
time_check = pygame.time.get_ticks ()
b_font = font.render (random.choice (my_list), True,(255,255,255))
screen.blit (b_font, (50, 100)
if time_check >= 2000: #2000 miliseconds
show_text = False
time_check = 0
Here it will display your text for two seconds

pygame display not changing

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.)

can't make call function to make a quit box appear in pygame

I'm trying to make it if you press ESC a quit box appears with the text "Do you want to quit?" on it. If the user clicks y the program ends. I think the first problem may be in the quitBox function but I don't know at all what is wrong in it. To me the function name and variables look okay. when i call the function it says that
name 'quitBoxPosX' is not defined
I think same goes with quitBoxPosY
Here's the code:
import pygame
import random
pygame.init()
# variables
mainLoop = True
font1 = pygame.font.SysFont('comicsansms', 25)
font2 = pygame.font.SysFont('underline', 35)
white = [255, 255, 255]
green = [0, 150, 0]
gray = [200, 200, 200]
black = [0, 0, 0]
clickNum = 0
clickAmount = 1
FPS = pygame.time.Clock()
pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLESAMPLES, 2)
screen = pygame.display.set_mode((1300, 700))
# functions
def switchButton01(events, buttonPlusPos):
global button02
button02 = pygame.transform.scale(button02, (100, 100))
screen.blit(button02, [580, 350])
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
global clickNum
clickNum += 1
global clickplusx, clickplusy
clickplusx = mouse
clickplusy = mouse
return (clickplusx, clickplusy)
return buttonPlusPos
def quitBox():
global quitBoxImage
global quitBoxPosX, quitBoxPosY
quitBoxImage = pygame.transform.scale(quitBoxImage, (300, 200))
quitBoxPosX = 430
quitBoxPosY = 200
return (quitBox, quitBoxPosX, quitBoxPosY)
# load images
button01 = pygame.image.load('button_100.png')
button02 = pygame.image.load('button_100hovered.png')
icon = pygame.image.load('icon_128.png')
buttonPlusImage = pygame.image.load('buttonPlus_32.png')
upgradeIcon = pygame.image.load('upgradesicon_64.png')
quitBoxImage = pygame.image.load('emptyGUI.png')
# title, icon
pygame.display.set_caption("incremental button")
pygame.display.set_icon(icon)
buttonPlusPos = None
while mainLoop:
pygame.display.flip()
FPS.tick(144)
screen.fill(white)
# actual content in the game
events = pygame.event.get()
mouse = pygame.mouse.get_pos()
# define objects
button01 = pygame.transform.scale(button01, (100, 100))
click_counter_text = font1.render("Click counter: ", True, black, white)
button01rect = button01.get_rect(center=(630, 400))
button01collidepoint = button01rect.collidepoint(pygame.mouse.get_pos())
click_counter = font1.render((str(clickNum)), True, black, white)
upgradeIcon = pygame.transform.smoothscale(upgradeIcon, (30, 30))
upgrades = font2.render('UPGRADES:', True, black)
FPScounter = font1.render('Frames per second:' + str(int(FPS.get_fps())), True, black, white)
# show objects
screen.blit(FPScounter, [20, 10])
screen.blit(button01, [580, 350])
screen.blit(click_counter_text, [525, 50])
upgradesBG = pygame.draw.rect(screen, gray, (1060, 44, 193, 600))
screen.blit(upgradeIcon, [1064, 46])
screen.blit(upgrades, [1100, 50])
screen.blit(click_counter, [700, 50])
if button01collidepoint:
buttonPlusPos = switchButton01(events, buttonPlusPos)
if buttonPlusPos:
screen.blit(buttonPlusImage, buttonPlusPos)
# quits
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
quitBoxPos = quitBox(quitBoxPosX, quitBoxPosY)
if quitBoxPos:
screen.blit(quitBoxImage(quitBoxPosX, quitBoxPosY))
font1.render(quitBox, 'Do you want to quit?', True, black, white)
if event.type == pygame.KEYDOWN and event.key == pygame.K_y:
pygame.quit()
quit()
quitBox has to return a the quit box data tuple, which consist of the image and the position of the box:
def quitBox():
img = pygame.transform.scale(quitBoxImage, (300, 200))
text = font1.render('Do you want to quit?', True, black, white)
img.blit(text, text.get_rect(center = img.get_rect().center))
return img, (430, 200)
You have to initialize the variable quitBoxData before the main application loop and to draw the box in the loop if quitBoxData is set:
quitBoxData = None
buttonPlusPos = None
while mainLoop:
# [...]
if quitBoxData:
screen.blit(*quitBoxData)
# [...]
When a KEYDOWN event occurs, then you have to do different things, dependent if quitBoxData is set or not. If it is not set and ESC is pressed, then you have to invoke quitBox and to get the data. If quitBoxData is not set an y is pressed, then leave the application (mainLoop = False) else continue (quitBoxData = None):
while mainLoop:
# [...]
# quits
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if quitBoxData:
if event.key == pygame.K_y:
mainLoop = False
else:
quitBoxData = None
else:
if event.key == pygame.K_ESCAPE:
quitBoxData = quitBox()
Full application code:
import pygame
import random
pygame.init()
# variables
mainLoop = True
font1 = pygame.font.SysFont('comicsansms', 25)
font2 = pygame.font.SysFont('underline', 35)
white = [255, 255, 255]
green = [0, 150, 0]
gray = [200, 200, 200]
black = [0, 0, 0]
clickNum = 0
clickAmount = 1
FPS = pygame.time.Clock()
pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLESAMPLES, 2)
screen = pygame.display.set_mode((1300, 700))
# functions
def switchButton01(events, buttonPlusPos):
global button02
button02 = pygame.transform.scale(button02, (100, 100))
screen.blit(button02, [580, 350])
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
global clickNum
clickNum += 1
global clickplusx, clickplusy
clickplusx = mouse
clickplusy = mouse
return (clickplusx, clickplusy)
return buttonPlusPos
def quitBox():
img = pygame.transform.scale(quitBoxImage, (300, 200))
text = font1.render('Do you want to quit?', True, black, white)
img.blit(text, text.get_rect(center = img.get_rect().center))
return img, (430, 200)
# load images
button01 = pygame.image.load('button_100.png')
button02 = pygame.image.load('button_100hovered.png')
icon = pygame.image.load('icon_128.png')
buttonPlusImage = pygame.image.load('buttonPlus_32.png')
upgradeIcon = pygame.image.load('upgradesicon_64.png')
quitBoxImage = pygame.image.load('emptyGUI.png')
# title, icon
pygame.display.set_caption("incremental button")
pygame.display.set_icon(icon)
quitBoxData = None
buttonPlusPos = None
while mainLoop:
pygame.display.flip()
FPS.tick(144)
screen.fill(white)
# actual content in the game
events = pygame.event.get()
mouse = pygame.mouse.get_pos()
# define objects
button01 = pygame.transform.scale(button01, (100, 100))
click_counter_text = font1.render("Click counter: ", True, black, white)
button01rect = button01.get_rect(center=(630, 400))
button01collidepoint = button01rect.collidepoint(pygame.mouse.get_pos())
click_counter = font1.render((str(clickNum)), True, black, white)
upgradeIcon = pygame.transform.smoothscale(upgradeIcon, (30, 30))
upgrades = font2.render('UPGRADES:', True, black)
FPScounter = font1.render('Frames per second:' + str(int(FPS.get_fps())), True, black, white)
# show objects
screen.blit(FPScounter, [20, 10])
screen.blit(button01, [580, 350])
screen.blit(click_counter_text, [525, 50])
upgradesBG = pygame.draw.rect(screen, gray, (1060, 44, 193, 600))
screen.blit(upgradeIcon, [1064, 46])
screen.blit(upgrades, [1100, 50])
screen.blit(click_counter, [700, 50])
if button01collidepoint:
buttonPlusPos = switchButton01(events, buttonPlusPos)
if buttonPlusPos:
screen.blit(buttonPlusImage, buttonPlusPos)
if quitBoxData:
screen.blit(*quitBoxData)
# quits
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if quitBoxData:
if event.key == pygame.K_y:
mainLoop = False
else:
quitBoxData = None
else:
if event.key == pygame.K_ESCAPE:
quitBoxData = quitBox()

How do you stop a method from running when you call another one?

When calling win.instructionScreen(screen, win), the instructions screen appears but the text from startScreen remains. Using screen.fill(BLACK) does not work because the main loop causes the text in startScreen to reappear, and using return to stop the startScreen method does not work.
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Game:
def __init__(self):
self.tickets = 0
def startScreen(self, screen, win):
titleText = pygame.font.SysFont('Showcard Gothic', 60)
subText = pygame.font.SysFont('Showcard Gothic', 20)
text = titleText.render("Our Game", True, WHITE)
cs = subText.render("Final Project", True, WHITE)
names = subText.render("Name 1, Name 2, Name 3, Name 4", True, WHITE)
screen.blit(text, [220, 200])
screen.blit(cs, [310, 265])
screen.blit(names, [150, 290])
mouse = pygame.mouse.get_pos()
if 493 > mouse[0] > 343 and 461 > mouse[1] > 411:
pygame.draw.rect(screen, RED, (343, 411, 150, 50))
else:
pygame.draw.rect(screen, GREEN, (343, 411, 150, 50))
buttonText = pygame.font.SysFont('Showcard Gothic', 30)
start = buttonText.render("Start!", True, WHITE)
screen.blit(start, [365, 425])
for event in pygame.event.get():
if 494 > mouse[0] > 343 and 461 > mouse[1] > 411:
if event.type == pygame.MOUSEBUTTONDOWN:
win.instructionScreen(screen, win)
pygame.display.update()
return
pygame.display.update()
def instructionScreen(self, screen, win):
background = pygame.image.load("background.png").convert()
screen.blit(background, [0, 0])
caption = pygame.image.load("caption.png").convert()
oak = pygame.image.load("oak.png").convert()
oak.set_colorkey(BLACK)
screen.blit(oak, [570, 130])
titleText = pygame.font.SysFont('Showcard Gothic', 60)
subText = pygame.font.SysFont('Showcard Gothic', 25)
text = titleText.render("Instructions", True, WHITE)
captionText = subText.render("Hey! Welcome to our game! Start by walking up", True, BLACK)
captionText2 = subText.render("to and playing Higher or Lower and racking up", True, BLACK)
captionText3 = subText.render("tickets. Then, when you get enough tickets,", True, BLACK)
captionText4 = subText.render("different games will be unlocked. Have fun!", True, BLACK)
screen.blit(text, [200, 80])
mouse = pygame.mouse.get_pos()
if 480 > mouse[0] > 325 and 550 > mouse[1] > 500:
pygame.draw.rect(screen, RED, (325, 500, 150, 50))
else:
pygame.draw.rect(screen, GREEN, (325, 500, 150, 50))
buttonText = pygame.font.SysFont('Showcard Gothic', 30)
screen.blit(caption, [3, 300])
pygame.draw.rect(screen, WHITE, (45, 320, 670, 110))
screen.blit(captionText, [45, 325])
screen.blit(captionText2, [45, 350])
screen.blit(captionText3, [45, 375])
screen.blit(captionText4, [45, 400])
play = buttonText.render("Play!", True, WHITE)
screen.blit(play, [357, 515])
#if 480 > mouse[0] > 325 and 550 > mouse[1] > 500:
# if event.type == pygame.MOUSEBUTTONDOWN:
# from gamescreen.py import gamescreen
pygame.display.update()
def clearScreen(self, screen):
screen.fill(WHITE)
def main():
pygame.init()
size = [800, 600]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Arcade City")
done = False
clock = pygame.time.Clock()
win = Game()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
done = True
win.startScreen(screen, win)
clock.tick(60)
if __name__ == "__main__":
main()
It's easier if you don't use nested functions. Call win.InstructionScreen() from the main function instead of from the method win.startScreen(). Use state variables to control the flow and return which state it should be from the methods.
win = Game()
current_screen = 'start'
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
done = True
if current_screen == 'start':
current_screen = win.startScreen(screen, win)
elif current_screen == 'instruction':
current_screen = win.instructionScreen(self, screen, win)
clock.tick(60)
This is just a mock-up, so you'll you have to change the methods after your own fittings. Put a return statement in both methods so they always return what the current screen should be.
TIP:
Instead of loading in your images and fonts every frame you could load them in the __init__ method and save them in a attribute variable.
EDIT:
To answer your actual question: You cannot stop an outer method to run. Think of it this way: You have a box in a room; can you get the box without entering the room? No. You have an inner method inside an outer method; can you get the inner method without entering the outer method? No.
If you only want the inner method to run without the outer method to be run, you have to call the inner method directly and not call the outer method.

Categories