"Stuttering" StartMenu for Pygame - python

I've been working on and off on a text-based adventure game for a few years now. It originally started as a way to learn Python, then I moved on to projects more relevant to my career after I became comfortable with the language. I'm now somewhat competent (Still a noob, but you know, progress) and I'd like to go back to the game to add in more complex functionality.
One thing that is annoying me is a visual bug in my start menu. Below is the code:
import pygame
from pygame_functions import setBackgroundImage
import gamefile
pygame.init()
display_width = 1500
display_height = 750
startMenu = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("The Woodsman's Tale")
black = (0, 0, 0)
green = (0, 200, 0)
white = (255, 255, 255)
dark_red = (200, 0, 0)
bright_green = (0, 255, 0)
leaf_green = (0, 175, 75)
brown = (102, 51, 0)
red = (255, 0, 0)
clock = pygame.time.Clock()
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def button(msg, x, y, w, h, ic, ac, action=None):
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(startMenu, ac, (x, y, w, h))
if click[0] == 1 and action is not None:
if action == 'play':
gamefile.rungame()
start_menu().intro = False
elif action == 'quit':
pygame.quit()
quit()
else:
pygame.draw.rect(startMenu, ic, (x, y, w, h))
smallText = pygame.font.Font("freesansbold.ttf", 20)
TextSurf, TextRect = text_objects(msg, smallText)
TextRect.center = (x + (w / 2), (y + (h / 2)))
startMenu.blit(TextSurf, TextRect)
def start_menu():
intro = True
while intro:
setBackgroundImage('startScreen.png')
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
largeText = pygame.font.Font('BRADHITC.ttf', 90)
TextSurf, TextRect = text_objects("The Woodsman's Tale", largeText)
TextRect.center = (display_width / 2, display_height / 3)
startMenu.blit(TextSurf, TextRect)
button('Play', 350, 500, 200, 150, green, leaf_green, 'play')
button('Quit', 850, 500, 200, 150, dark_red, red, 'quit')
pygame.display.update()
clock.tick(15)
if __name__ == '__main__':
start_menu()
The setbackgroundimage function being imported is this:
def setBackgroundImage(img):
global bgSurface, backgroundImage
surf = loadImage(img)
backgroundImage = surf
screen.blit(surf, [0, 0])
bgSurface = screen.copy()
updateDisplay()
Now, the start menu works great. Everything functions properly. My issue is that when I click on the title bar, for example to move the window, the start menu begins stuttering visually.
Exactly what is happening is this: Once I click on the title bar, the "buttons" of the start menu and the Title text of the game disappear. Once the click is released, the buttons and Title text reappear, but stutter rapidly.
I'm not really sure if I'm providing enough for anyone to be able to tell what's going wrong, so I apologize if that's the case.

The fist issue is that setBackgroundImage seems to update the display (updateDisplay()).
The display has to be updated once at the end of the main application loop, and should not be updated multiple times. That cause the flickering. Remove the display update from setBackgroundImage:
def start_menu():
intro = True
while intro:
setBackgroundImage('startScreen.png') # draw background but do no update the display
# [...]
pygame.display.update() # the one and only update at the end of the loop
clock.tick(15)
The second issue, that the background image is loaded in setBackgroundImage. That cause that the image is loaded continuously in every frame. That causes a performance impact.
Load the image before the main loop and pass the Surface object to setBackgroundImage:
def start_menu():
surf = loadImage('startScreen.png')
intro = True
while intro:
setBackgroundImage(surf)
# [...]

Related

Pygame not transitioning to the next image

I am working on my first python project. I have some buttons, 'Yes' and 'No' after the initial question of "do you want to play?". When I press no it closes the game. When I click yes, I'd like it for it to jump to the next function where it displays the text "so you've decided to play", and although I can see it jump to the next text for a little bit, it quickly switches back to the previous question and buttons of "Do you wish to play?" with the Yes and No buttons. How can I fix this? I've tried to order pygame.display.update() in different ways but so far no luck. Any help would be appreciated, thanks guys. Here is my code:
import pygame
pygame.init()
win=pygame.display.set_mode((800,700))
win.fill((255,255,255))
our_game_display=pygame.Surface((800,700))
font_name = pygame.font.get_default_font()
class button():
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def draw(self, win, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.SysFont('comicsans', 60)
text = font.render(self.text, 1, (255, 255, 255))
win.blit(text, (
self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))
def isOver(self, pos):
# Pos is the mouse position or a tuple of (x,y) coordinates
if pos[0] > self.x and pos[0] < self.x + self.width:
if pos[1] > self.y and pos[1] < self.y + self.height:
return True
return False
def yes_no_choice():
#win.fill((0,0,0))
YesButton.draw(win,(255,255,255))
NoButton.draw(win,(255,255,255))
def draw_text(text, size, x, y):
pygame.font.init()
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, (255,255,255))
text_rect = text_surface.get_rect()
text_rect.center = (x, y)
our_game_display.blit(text_surface, text_rect)
def beginning_question():
our_game_display.fill((0, 0, 0))
draw_text('The story of this game depends on your choices. Do you wish to play?', 20, 800 / 2, 700 / 2 - 100)
win.blit(our_game_display, (0, 0))
yes_no_choice()
pygame.display.update()
def begin_game():
our_game_display.fill((0,0,0))
draw_text("So you've decided to play...very well.", 20, 800 / 2, 700 / 2 - 100)
win.blit(our_game_display,(0,0))
pygame.display.update()
#game loop
running = True
YesButton=button((0,0,0),100,500,250,100,'Yes')
NoButton=button((0,0,0),450,500,250,100,'No')
while running:
beginning_question()
for event in pygame.event.get():
pos=pygame.mouse.get_pos()
if event.type==pygame.QUIT:
running = False
pygame.quit()
quit()
if event.type==pygame.MOUSEBUTTONDOWN:
if YesButton.isOver(pos):
begin_game()
if NoButton.isOver(pos):
running=False
pygame.quit()
quit()
if event.type==pygame.MOUSEMOTION:
if YesButton.isOver(pos):
YesButton.color=(0,0,139)
elif NoButton.isOver(pos):
NoButton.color=(0,0,139)
else:
YesButton.color=(0,0,0)
NoButton.color=(0,0,0)
The reason why it only flashes for a second and then switches back is because the drawing for the "So you've decided to play" only happens in frames where you click the yes button. It should happen continuously after you hit the yest button. Here is one potential solution:
Have a boolean variable game_begun to keep track of whether the game has begun or not (initially false):
YesButton = button((0, 0, 0), 100, 500, 250, 100, 'Yes')
NoButton = button((0, 0, 0), 450, 500, 250, 100, 'No')
game_begun = False # New variable
After the user clicks the yes button, set that variable to true:
if event.type == pygame.MOUSEBUTTONDOWN:
if YesButton.isOver(pos):
game_begun = True
if NoButton.isOver(pos):
running = False
pygame.quit()
quit()
Finally, in the game loop (not the event loop), have a condition to check if the game has begun, and if so, then call the begin_game function. If not, then draw the beginning question:
if game_begun:
begin_game()
else:
beginning_question()
This might not be the absolute best solution, but it should suffice for your first python project. As you add more states to your game, you should use a string variable to keep track of you game state instead of a boolean. Happy coding!

pygame.quit() giving init.font error while switching files

I made a main python file that holds the whole game itself and for each window, I'm using different files. For instance, for the beginning of the game, I want to create a window where you can choose the language with 2 boxes, which makes a variable = 1 or 2. The main file reads the variable and with an if condition the language is defined.
The main problem is that when I want to close the language file and resume with the main one, it pops up an error saying the font is not defined when I did pygame.quit()
MAIN FILE
import pygame
from lib.pygame_functions import *
from pygame.locals import *
import time
import random
def language():
import lib.language.languageVS
from lib.language.languageVS import lang
language()
pygame.quit()
if lang == '1':
from languages.en import *
lang_selection = 1
print(selection_language)
elif lang == '2':
from languages.es import *
lang_selection = 1
print(selection_language)
pygame.init()
white = (255,255,255)
black = (0,0,0)
green = (0, 200, 0)
red = (200, 0, 0)
blue = (0, 0, 200)
bright_green = (0, 255, 0)
bright_red = (255, 0, 0)
bright_blue = (0, 0, 255)
introbackground = pygame.image.load('introbg.png')
gameDisplay = pygame.display.set_mode((800, 600)) #surface
pygame.display.set_caption('Neon Fight') #titutlo
def names():
import lib.playernames.TEXTINPUT
from lib.playernames.TEXTINPUT import a
print(a)
import lib.playernames.TEXTINPUT2
from lib.playernames.TEXTINPUT2 import b
print(b)
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
def quitgame():
pygame.quit()
quit()
def game():
time.sleep(4)
def startgame():
pygame.quit()
names()
game()
def button(msg, x, y, w, h, ic, ac, action=None):
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))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, ic, (x, y, w, h))
smallText = pygame.font.Font('freesansbold.ttf', 20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y+(h/2)))
gameDisplay.blit(textSurf, textRect)
def game_intro():
intro = True
while intro:
gameDisplay.blit(introbackground, (0, 0))
#gameDisplay.fill(white)
mouse = pygame.mouse.get_pos()
#print(mouse)
#BUTTONS
button('Play', 350, 325, 100, 50, green, bright_green, startgame)
button('Instructions', 350, 400, 100, 50, blue, bright_blue)
button('Quit', 350, 475, 100, 50, red, bright_red, quitgame)
pygame.display.update()
#quit_x
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
pygame.quit() #desinizialization
quit()
game_intro()
gameExit = False
while not gameExit: #quit_x
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameDisplay.fill(white)
pygame.display.update() #actualizar_surface
pygame.quit() #desinizialization
quit()
lib.language.languageVS
import pygame
from pygame.locals import *
import time
import random
lang = 0
pygame.init() #inizialization
white = (255,255,255)
black = (0,0,0)
green = (0, 200, 0)
red = (200, 0, 0)
blue = (0, 0, 200)
bright_green = (0, 255, 0)
bright_red = (255, 0, 0)
bright_blue = (0, 0, 255)
gameDisplay = pygame.display.set_mode((800, 600)) #surface
pygame.display.set_caption('Neon Fight') #titutlo
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
def english():
global lang
lang = 1
pygame.quit()
def spanish():
global lang
lang = 2
pygame.quit()
def button(msg, x, y, w, h, ic, ac, action=None):
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))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, ic, (x, y, w, h))
smallText = pygame.font.Font('freesansbold.ttf', 20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y+(h/2)))
gameDisplay.blit(textSurf, textRect)
def language():
language = True
while language:
gameDisplay.fill(white)
mouse = pygame.mouse.get_pos()
#print(mouse)
#BUTTONS
button('Play', 350, 325, 100, 50, green, bright_green, spanish)
button('Instructions', 350, 400, 100, 50, blue, bright_blue, english)
pygame.display.update()
#quit_x
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
pygame.quit() #desinizialization
quit()
language()
gameExit = False
while not gameExit: #quit_x
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameDisplay.fill(white)
pygame.display.update() #actualizar_surface
TRACEBACK:
Exception has occurred: error
font not initialized
File "F:\APPVISUAL\lib\language\languageVS.py", line 55, in button
smallText = pygame.font.Font('freesansbold.ttf', 20)
File "F:\APPVISUAL\lib\language\languageVS.py", line 73, in language
button('Play', 350, 325, 100, 50, green, bright_green, spanish)
File "F:\APPVISUAL\lib\language\languageVS.py", line 85, in <module>
language()
An easy solution would be to add pygame.init() before
smallText = pygame.font.Font('freesansbold.ttf', 20)
Managed to solve it. Apparently just changing the function worked. I thought that instead of using pygame.quit() to close the pygame module, i could just add everything on a loop and whenever an option is selected the loop stops going on and lets the code end by itself without forcing it. In that way i can import it in the main file and code keep running! This is what the code is in lib.languageVS file:
import pygame
from pygame.locals import *
import time
import random
import sys
lang = 0
pygame.init() #inizialization
white = (255,255,255)
black = (0,0,0)
green = (0, 200, 0)
red = (200, 0, 0)
blue = (0, 0, 200)
bright_green = (0, 255, 0)
bright_red = (255, 0, 0)
bright_blue = (0, 0, 255)
gameDisplay = pygame.display.set_mode((800, 600)) #surface
pygame.display.set_caption('Neon Fight') #titutlo
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
def english():
global lang
lang = 1
def spanish():
global lang
lang = 2
def button(msg, x, y, w, h, ic, ac, action=None):
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))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, ic, (x, y, w, h))
smallText = pygame.font.Font('freesansbold.ttf', 20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y+(h/2)))
gameDisplay.blit(textSurf, textRect)
def language():
language = True
while language == True:
gameDisplay.fill(white)
mouse = pygame.mouse.get_pos()
#print(mouse)
#BUTTONS
button('SPANISH', 350, 325, 100, 50, green, bright_green, spanish)
button('ENGLISH', 350, 400, 100, 50, blue, bright_blue, english)
if lang == 1:
language = False
elif lang == 2:
language = False
pygame.display.update()
#quit_x
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
pygame.quit() #desinizialization
language()
##OLD_VERSION
# def language():
# language = True
# while language:
# gameDisplay.fill(white)
# mouse = pygame.mouse.get_pos()
# #print(mouse)
# #BUTTONS
# button('SPANISH', 350, 325, 100, 50, green, bright_green, spanish)
# button('ENGLISH', 350, 400, 100, 50, blue, bright_blue, english)
# pygame.display.update()
# #quit_x
# for event in pygame.event.get():
# if event.type == pygame.QUIT:
# gameExit = True
# pygame.quit() #desinizialization
# if lang == 1:
# pygame.quit()
# elif lang == 2:
# pygame.quit()

Need help creating buttons in pygame

I have been assigned a homework problem in pygame to make two rectangles, one red , one green and when clicked, text appears which gives the name of the colour of the button, I have created the shapes successfully, however I don't know how to make the text appear when the button is clicked. Any help is appreciated
I have successfully drawn two rectangles using the pygame.draw.rect() function and I have called pos = pygame.mouse.get_pos() in order to get an x and y value for the user's mouse.
pos = pygame.mouse.get_pos()
x = pos[0]
y = pos[1]
screen.fill(WHITE)
pygame.draw.rect(screen, GREEN, [100, 300, 200, 200])
pygame.draw.rect(screen, RED, [400, 300, 200, 200])
pygame.display.flip()
clock.tick(60)
The result is two rectangles, one green, one red in the centre of the screen.
To verify if amouse button is pressed oyu can use pygame.mouse.get_pressed():
leftClicked = pygame.mouse.get_pressed()[0]
For text rendering you can use pygame.font or pygame.pygame.freetype. e. g:
import pygame.freetype
font = pygame.freetype.SysFont('Times New Roman', 30)
Define a pygame.Rect for each button:
rect_green = pygame.Rect(100, 300, 200, 200)
rect_red = pygame.Rect(400, 300, 200, 200)
Verify if the mouse button is pressed an the mouse coursor is on the button by .collidepoint()). e.g.:
pygame.draw.rect(screen, GREEN, rectGreen)
if leftClicked and rectGreen.collidepoint(pos):
text_surf, text_rect = font.render("GREEN", WHITE, size=30)
text_rect.center = rectGreen.center
screen.blit(text_surf, text_rect)
See the short example:
import pygame
import pygame.freetype
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
pygame.init()
size = (800,600)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
font = pygame.freetype.SysFont('Times New Roman', 30)
rect_green = pygame.Rect(100, 300, 200, 200)
rect_red = pygame.Rect(400, 300, 200, 200)
def DrawButton(surf, cursor_pos, pressed, rect, color, text_color, text):
pygame.draw.rect(surf, color, rect)
if pressed and rect.collidepoint(cursor_pos):
text_surf, text_rect = font.render(text, text_color, size=30)
text_rect.center = rect.center
screen.blit(text_surf, text_rect)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pos = pygame.mouse.get_pos()
x = pos[0]
y = pos[1]
leftClicked = pygame.mouse.get_pressed()[0]
screen.fill(WHITE)
DrawButton(screen, pos, leftClicked, rect_green, GREEN, BLACK, "GREEN")
DrawButton(screen, pos, leftClicked, rect_red, RED, BLACK, "RED")
pygame.display.flip()
clock.tick(60)
pygame.quit()

Can't find a way to get one of my pictures to stay on screen when my mouse click is pressed

I'm trying to get an image to stay on screen when my left click is pressed. I've been mostly following the Sentdex videos on youtube for info on how to draw the buttons etc, so if its a bit messy, its because i'm pretty new to pygame! The aim of this game is to be a First Person Shooter, but recently found out that's virtually impossible with python :( So im just carrying on with this project to see where else it could go. Any ideas/suggestions would be much appreciated!
import time
import pygame
from tkinter import *
#import pyautogui
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
display_width = 1200
display_height = 600
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
hgrey = (77,197,179)
hlight_grey = (255,102,106)
grey = (68,187,169)
light_grey = (247,94,98)
pygame.mixer.music.load('music/privia_the_begining.mp3')
pygame.mixer.music.play(-1)
counter = 0
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Privia 1.0')
clock = pygame.time.Clock()
gameIcon = pygame.image.load('pics/priviaicon.png')
bannerIcon = pygame.image.load('pics/priviabanner.png')
backgroundMenu = pygame.image.load('pics/bgm.png')
backgroundGameType = pygame.image.load('pics/bgmws.png')
pygame.display.set_icon(gameIcon)
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def messeage_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
def button(msg,x,y,w,h,ic,ac,action=None):
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))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, ic,(x,y,w,h))
smallText = pygame.font.Font("freesansbold.ttf",20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def quitgame():
pygame.quit()
quit()
pygame.mixer.stop()
def main_menu():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.blit(backgroundMenu, [0, 0])
gameDisplay.blit(bannerIcon,(300,4))
button("SinglePlayer",430,260,350,100,grey,hgrey,game_type)
button("Quit",507,400,200,50,light_grey,hlight_grey,quitgame)
pygame.display.update()
clock.tick(15)
def game_type():
gameDisplay.blit(backgroundGameType, [0, 0])
print("working")
main_menu()
The backgroundGameType image isn't staying on the screen because the code only displays (blits) it to screen when the mouse is held down within the region defined for the button.
If you want it say on the screen, one way would be to set a flag that is checked every iteration of in the main event processing loop (while intro:) that tracks whether or not to also display it even when the mouse is no longer in that region.
Below is your code modified to do this. Note I have commented out parts of it that have nothing to with the problem — something you should have done before posting your code (or better yet, have removed completely). See How to create a Minimal, Complete, and Verifiable Example.
An new global flag variable has been added named game_mode_selected and initialized to False, and its value is checked each iteration of the main loop. As long as it does not have a "truthy" value, a call is made to display the "SinglePlayer" button and check the state of the mouse. When the mouse is clicked within the region defined for it, and the associated action function, game_type() gets called, the value of this global flag gets changed to "remember" it happened.
Since I assume at that point you no longer wish to have the "SinglePlayer" button displayed, I also added a gameDisplay.fill(black) call to the beginning of the main loop. Without it the button will continue to be visible even though it not longer does anything.
import time
import pygame
from tkinter import *
#import pyautogui
#pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
display_width = 1200
display_height = 600
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
hgrey = (77,197,179)
hlight_grey = (255,102,106)
grey = (68,187,169)
light_grey = (247,94,98)
#pygame.mixer.music.load('music/privia_the_begining.mp3')
#pygame.mixer.music.play(-1)
counter = 0
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Privia 1.0')
clock = pygame.time.Clock()
#gameIcon = pygame.image.load('pics/priviaicon.png')
#bannerIcon = pygame.image.load('pics/priviabanner.png')
backgroundMenu = pygame.image.load('pics/bgm.png')
backgroundGameType = pygame.image.load('pics/bgmws.png')
#pygame.display.set_icon(gameIcon)
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def messeage_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
def button(msg, x, y, w, h, ic, ac, action=None):
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))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, ic, (x,y,w,h))
smallText = pygame.font.Font("freesansbold.ttf", 20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def quitgame():
pygame.quit()
quit()
# pygame.mixer.stop()
game_mode_selected = False # New global variable
def main_menu():
global game_mode_selected
game_mode_selected = False
intro = True
while intro:
gameDisplay.fill(black) # Added.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.blit(backgroundMenu, [0, 0])
# gameDisplay.blit(bannerIcon,(300,4))
if not game_mode_selected:
button("SinglePlayer", 430,260, 350,100, grey, hgrey, game_type)
else:
gameDisplay.blit(backgroundGameType, [0, 0])
button("Quit", 507,400, 200,50, light_grey, hlight_grey, quitgame)
pygame.display.update()
clock.tick(15)
def game_type():
global game_mode_selected
game_mode_selected = True # Change global because button was clicked.
gameDisplay.blit(backgroundGameType, [0, 0])
print("working")
main_menu()

Buttons and text flickering

I copied most of this code from an earlier script which worked fine, but when I load up the game, pretty much all the elements are flickering.
Here is the Minimal complete verifiable example here:
import pygame
pygame.init()
displayWidth = 1280
displayHeight = 720
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
pygame.display.set_caption('Grow')
black = (0, 0, 0)
brown = (100, 100, 0)
green = (0, 200, 0)
lightGreen = (0, 255, 0)
red = (200, 0, 0)
lightRed = (255, 0, 0)
smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("comicsansms", 50)
largefont = pygame.font.SysFont("comicsansms", 80)
clock = pygame.time.Clock()
FPS = 60
def gameIntro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(brown)
message_to_screen('Welcome to Tanks', green, -100, 'large')
message_to_screen('The objective is to shoot and destroy', black, -30)
message_to_screen('Shoot and destroy the enemy tank before they destroy you', black, 10)
message_to_screen('The more enemies you destroy, the harder they get', black, 50)
button('quit', 500, 500, 100, 50, red, lightRed, action = 'quit')
button('play', 200, 500, 100, 50, green, lightGreen, action = 'play')
pygame.display.update()
clock.tick(0)
def gameLoop():
pygame.quit()
quit()
def button(text, x, y, width, height, inactive_color, active_color, action = None):
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
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 == 'quit':
pygame.quit()
quit()
if action == 'play':
gameLoop()
else:
pygame.draw.rect(gameDisplay, inactive_color, (x, y, width, height))
text_to_button(text, black, x, y, width, height)
def text_to_button(msg, colour, buttonx, buttony, buttonwidth, buttonheight, size = 'small'):
textSurf, textRect = text_objects (msg, colour, size)
textRect.center = ((buttonx + (buttonwidth/2)), buttony + (buttonheight/2))
gameDisplay.blit(textSurf, textRect)
pygame.display.update()
def message_to_screen(msg, colour, y_displace = 0, size = 'small'):
textSurf, textRect = text_objects (msg, colour, size)
textRect.center = (displayWidth / 2), (displayHeight / 2) + y_displace
gameDisplay.blit(textSurf, textRect)
pygame.display.update()
def text_objects(text, colour, size):
if size == 'small':
textSurface = smallfont.render (text, True, colour)
elif size == 'medium':
textSurface = medfont.render (text, True, colour)
elif size == 'large':
textSurface = largefont.render (text, True, colour)
return textSurface, textSurface.get_rect()
gameIntro()
For some reason, in the gameIntro function, when I call the message_to_screen and button functions, they all start flickering (everything except the first function called). Changing the order of the functions changes which one will stop flickering. Everything else works fine. The buttons change colour when the cursor is above them and they can still be clicked and have functionality
Don't call pygame.display.update() multiple times in each iteration of your game loop. It will lead to the screen flickering you see.
Simply remove the pygame.display.update() calls in the message_to_screen and text_to_button functions.

Categories