Why does the display of text decrease my pygame FPS? - python-3.x

I'm trying to write this simple game that replicates a few aspects of Asteroids and have had some problems with the FPS. I have not finished the game yet, but was concerned about the FPS drop as I have a lot more text that I wish to display, but am unable to display for fear the game will suffer so much frame drop. I have only noticed this frame drop with text being displayed on screen. My code can be found below.
import os
import pickle
import pygame
from pygame.locals import *
import random
import sys
import time
pygame.init()
pygame.display.init()
common_drops = ['Janus', 'Peace of Mind', 'Second Chance']
rare_drops = ['Invincibility', 'Shield', 'Bonus Credits', 'Weapon']
ultra_rare_drops = []
janus_count = 0
peace_of_mind_count = 0
bonus_lives_count = 0 #Second Chance
invincibility_count = 0
shield_count = 0
weapon_count = 0
credit_count = 30
high_score = 0
def save():
loot_out = open('./nec_files/user_data/player.pickle', 'wb')
pickle.dump(player_loot_data, loot_out)
loot_out.close()
if os.path.isfile('./nec_files/user_data/player.pickle') == True:
loot_in = open('./nec_files/user_data/player.pickle', 'rb')
loot_dict = pickle.load(loot_in)
player_loot_data = {
'janus_count' : loot_dict['janus_count'],
'peace_of_mind_count' : loot_dict['peace_of_mind_count'],
'bonus_lives_count' : loot_dict['bonus_lives_count'], #Second Chance
'invincibility_count' : loot_dict['invincibility_count'],
'shield_count' : loot_dict['shield_count'],
'weapon_count' : loot_dict['weapon_count'],
'credit_count' : loot_dict['credit_count'],
'high_score' : loot_dict['high_score']
}
loot_in.close()
save()
else:
player_loot_data = {
'janus_count' : janus_count,
'peace_of_mind_count' : peace_of_mind_count,
'bonus_lives_count' : bonus_lives_count, #Second Chance
'invincibility_count' : invincibility_count,
'shield_count' : shield_count,
'weapon_count' : weapon_count,
'credit_count' : credit_count,
'high_score' : high_score
}
save()
display_width = 1280
display_height = 720
black = (0,0,0)
white = (255,255,255)
blue = (0, 102, 204)
bright_blue = (102, 178, 255)
red = (204, 0, 0)
bright_red = (255, 51, 51)
yellow = (204, 204, 0)
bright_yellow = (255, 255, 102)
gray = (169, 169, 169)
game_title = 'Asteroids: Reimagined'
paused = False
alpha = True
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption(game_title)
print(pygame.display.get_driver())
clock = pygame.time.Clock()
playerImg = pygame.image.load('./nec_files/graphics/player_image.png')
asteroidImg = pygame.image.load('./nec_files/graphics/asteroid_image.png')
current_drops = []
def open_common_drop():
global current_drops
current_drops.clear()
if player_loot_data['credit_count'] >= 5:
player_loot_data['credit_count'] -= 5
for x in range(3):
rand_num = random.randint(0, 50)
if rand_num < 49:
drops = random.choice(common_drops)
elif rand_num >= 49:
drops = random.choice(rare_drops)
if drops == 'Janus':
player_loot_data['janus_count'] += 1
elif drops == 'Peace of Mind':
player_loot_data['peace_of_mind_count'] += 1
elif drops == 'Second Chance':
player_loot_data['bonus_lives_count'] += 1
elif drops == 'Bonus Credits':
bonus_credits = random.randint(1, 50)
player_loot_data['credit_count'] += bonus_credits
elif drops == 'Invincibility':
player_loot_data['invincibility_count'] += 1
elif drops == 'Shield':
player_loot_data['shield_count'] += 1
elif drops == 'Weapon':
player_loot_data['weapon_count'] += 1
current_drops.append(drops)
save()
def open_rare_drop():
global current_drops
current_drops.clear()
if player_loot_data['credit_count'] >= 10:
player_loot_data['credit_count'] -= 10
for x in range(3):
rand_num = random.randint(0, 50)
if rand_num < 36:
drops = random.choice(common_drops)
elif rand_num >= 36:
drops = random.choice(rare_drops)
if drops == 'Janus':
player_loot_data['janus_count'] += 1
elif drops == 'Peace of Mind':
player_loot_data['peace_of_mind_count'] += 1
elif drops == 'Second Chance':
player_loot_data['bonus_lives_count'] += 1
elif drops == 'Bonus Credits':
bonus_credits = random.randint(1, 50)
player_loot_data['credit_count'] += bonus_credits
elif drops == 'Invincibility':
player_loot_data['invincibility_count'] += 1
elif drops == 'Shield':
player_loot_data['shield_count'] += 1
elif drops == 'Weapon':
player_loot_data['weapon_count'] += 1
current_drops.append(drops)
save()
def player(player_x, player_y):
gameDisplay.blit(playerImg, (player_x, player_y))
def asteroid(thingx, thingy):
gameDisplay.blit(asteroidImg, (thingx, thingy))
def game_display_text(display_msg, display_x, display_y, text_size):
font = pygame.font.SysFont(None, text_size)
text = font.render(str(display_msg), True, black)
gameDisplay.blit(text, (display_x, display_y))
def title(msg):
largeText = pygame.font.SysFont(None, 75)
TextSurf, TextRect = text_objects(msg, largeText)
TextRect.center = ((display_width / 2), (display_height * 0.10))
gameDisplay.blit(TextSurf, TextRect)
def button(x, y, w, h, ic, ac, action = None):
global paused
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 == Game:
Game()
if click[0] == 1 and action == quitgame:
sys.exit()
if click[0] == 1 and action == None:
paused = False
if click[0] == 1 and action == StartScreen:
save()
StartScreen()
if click[0] == 1 and action == LootScreen:
LootScreen()
if click[0] == 1 and action == open_common_drop:
open_common_drop()
if click[0] == 1 and action == open_rare_drop:
open_rare_drop()
else:
pygame.draw.rect(gameDisplay, ic, (x, y, w, h))
def things(thingx, thingy, thingw, thingh, color):
pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
def things2(thingx, thingy, thingw, thingh, color):
pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
def text_box(box_x, box_y, box_w, box_h, color):
pygame.draw.rect(gameDisplay, color, [box_x, box_y, box_w, box_h])
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', 50)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
def reset():
message_display('Out of Bounds: Player Location Reset')
def quitgame():
pygame.quit()
sys.exit()
def StartScreen():
intro = True
settings_x = 1230
settings_y = 670
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
save()
pygame.quit()
sys.exit()
gameDisplay.fill(gray)
title(game_title)
button(420, 250, 125, 50, blue, bright_blue, Game)
button(720, 250, 125, 50, red, bright_red, quitgame)
button(570, 250, 125, 50, yellow, bright_yellow, LootScreen)
game_display_text('Start', 450, 260, 40)
game_display_text('Quit', 750, 260, 40)
game_display_text('Loot', 600, 260, 40)
game_display_text('Licensed by: #1024MBStudio', 925, 690, 35)
pygame.display.update()
clock.tick(30)
def LootScreen():
global current_drops
loot = True
while loot:
for event in pygame.event.get():
if event.type == pygame.QUIT:
save()
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_t:
open_common_drop()
elif event.key == pygame.K_y:
open_rare_drop()
if event.key == pygame.K_ESCAPE:
StartScreen()
gameDisplay.fill(gray)
title('Loot Chests!')
button(400, 150, 260, 50, blue, bright_blue, None)
button(695, 150, 260, 50, red, bright_red, None)
button(display_width * 0.42, display_height / 1.15, 255, 50, red, bright_red, StartScreen)
game_display_text('Open Common Chest (T)', 407, 165, 30)
game_display_text('Open Rare Chest (Y)', 725, 165, 30)
game_display_text('You Got: %s' % current_drops, 50, display_height / 2, 35)
game_display_text('Credits: %.2f' % player_loot_data['credit_count'], 15, 15, 35)
game_display_text('Main Menu', display_width * 0.47, display_height / 1.13, 35)
game_display_text('Janus\': %.2f' % player_loot_data['janus_count'] , 1025, 500, 35)
game_display_text('Peace of Minds: %.2f' % player_loot_data['peace_of_mind_count'], 1025, 535, 35)
pygame.display.update()
clock.tick(30)
def PauseScreen():
global paused
paused = True
pausebox_x = 0
pausebox_y = 625
pausebox_width = display_width
pausebox_height = display_height - 625
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
save()
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = False
gameDisplay.fill(gray)
title('Paused')
button(560, 130, 173, 50, blue, bright_blue, None)
button(560, 205, 173, 50, red, bright_red, StartScreen)
game_display_text('Resume', 590, 140, 40)
game_display_text('Quit', 615, 218, 40)
text_box(pausebox_x, pausebox_y, pausebox_width, pausebox_height, blue)
game_display_text('Janus\': %s' % player_loot_data['janus_count'] , 5, 630, 35)
game_display_text('Peace of Minds: %s' % player_loot_data['peace_of_mind_count'], 5, 665, 35)
game_display_text('Bonus Lives: %s' % player_loot_data['bonus_lives_count'], 250, 630, 35)
pygame.display.update()
clock.tick(30)
def DeadScreen():
current_score = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
save()
pygame.quit()
sys.exit()
gameDisplay.fill(gray)
title('You Died')
game_display_text('You earned %s' % credit_gain + ' credits that game!', display_width * 0.33, display_height * 0.40, 40)
button(520, 120, 250, 55, blue, bright_blue, Game)
button(520, 190, 250, 55, red, bright_red, StartScreen)
game_display_text('Play Again?', 560, 132, 40)
game_display_text('Main Menu', 569, 205, 40)
pygame.display.update()
clock.tick(30)
def Game():
global death_counter, attempt_counter, credit_gain
player_x = (display_width * 0.5)
player_y = (display_height * 0.5)
player_speed = 5.5
playerHeight = 50
x_change = 0
y_change = 0
enemyWidth = 165
thing_startx = 1500
thing2_startx = 1500
thing_speed = -6
thing2_speed = -5.5
thing_starty = random.randrange(75, display_height - enemyWidth)
thing2_starty = random.randrange(75, display_height - enemyWidth)
dead = False
janus = False
peace_of_mind = False
invincibility = False
full_screen = False
earnable_credits = 0.125
current_score = 0
credit_gain = 0
current_lives = 0
RESETEVENT = pygame.USEREVENT + 1
DISABLEJANUS = pygame.USEREVENT + 5
textbox_x = 0
textbox_y = 0
textbox_width = 1280
textbox_height = 60
while not dead:
if pygame.display.get_active() == True:
for event in pygame.event.get():
pygame.time.set_timer(RESETEVENT, 275)
if peace_of_mind == True:
thing_original_speed = thing_speed
thing2_original_speed = thing2_speed
if event.type == RESETEVENT:
current_score += 1
pygame.time.set_timer(RESETEVENT, 275)
if event.type == DISABLEJANUS:
janus = False
if event.type == pygame.QUIT:
save()
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if janus == True:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x_change = -player_speed
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x_change = player_speed
if event.key == pygame.K_UP or event.key == pygame.K_w:
y_change = -player_speed
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y_change = player_speed
if event.key == pygame.K_u and player_loot_data['janus_count'] > 0 and janus == False:
pygame.time.set_timer(DISABLEJANUS, 15000)
player_loot_data['janus_count'] -= 1
janus = True
elif event.key == pygame.K_i and player_loot_data['peace_of_mind_count'] > 0 and peace_of_mind == False:
player_loot_data['peace_of_mind_count'] -= 1
peace_of_mind = True
elif event.key == pygame.K_o and player_loot_data['bonus_lives_count'] > 0:
player_loot_data['bonus_lives_count'] -= 1
current_lives += 1
if event.key == pygame.K_ESCAPE:
PauseScreen()
elif event.key == pygame.K_F4:
sys.exit()
elif event.key == pygame.K_F11:
if full_screen == False:
pygame.display.set_mode((display_width, display_height), pygame.FULLSCREEN)
full_screen = True
PauseScreen()
elif full_screen == True:
pygame.display.set_mode((display_width, display_height))
PauseScreen()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_a or event.key == pygame.K_d:
x_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_w or event.key == pygame.K_s:
y_change = 0
elif event.key == pygame.K_SPACE:
y_change = 0
if thing_startx < 0 - enemyWidth:
thing_startx = 1500
thing_starty = random.randrange(75, display_height - enemyWidth)
thing_speed += -0.05
player_loot_data['credit_count'] += earnable_credits
credit_gain += earnable_credits
if thing2_startx < 0 - enemyWidth:
thing2_startx = 1500
thing2_starty = random.randrange(75, display_height - enemyWidth)
thing2_speed += -0.1
player_loot_data['credit_count'] += earnable_credits
credit_gain += earnable_credits
player_x += x_change
player_y += y_change
thing_startx += thing_speed
thing2_startx += thing2_speed
if player_loot_data['high_score'] < current_score:
player_loot_data['high_score'] = current_score
if player_y > display_height:
player_y = textbox_height
if player_y < 10:
player_y = display_height - playerHeight
if player_x < 0 - playerHeight:
player_x = (display_width * 0.5)
if player_x > display_width:
player_x = (display_width * 0.5)
if player_y < thing_starty + enemyWidth and player_y + playerHeight > thing_starty:
if player_x > thing_startx and player_x < thing_startx + enemyWidth or player_x + playerHeight > thing_startx and player_x + playerHeight < thing_startx + enemyWidth:
if current_lives > 0:
current_lives -= 1
player_x = (display_width * 0.5)
player_y = (display_height * 0.5)
thing_startx = 1500
thing2_startx = 1500
else:
dead = True
if player_y < thing2_starty + enemyWidth and player_y + playerHeight > thing2_starty:
if player_x > thing2_startx and player_x < thing2_startx + enemyWidth or player_x + playerHeight > thing2_startx and player_x + playerHeight < thing2_startx + enemyWidth:
if current_lives > 0:
current_lives -= 1
player_x = (display_width * 0.5)
player_y = (display_height * 0.5)
thing_startx = 1500
thing2_startx = 1500
else:
dead = True
else:
crossover = 'null'
gameDisplay.fill(gray)
player(player_x, player_y)
asteroid(thing_startx, thing_starty)
asteroid(thing2_startx, thing2_starty)
text_box(textbox_x, textbox_y, textbox_width, textbox_height, blue)
game_display_text('High Score: %s' % player_loot_data['high_score'], 5, 5, 30)
game_display_text('Current Score: %s' % current_score, 5, 35, 30)
game_display_text('Current Chances: %s' % current_lives, 200, 5, 30)
if janus == True:
game_display_text('Janus Enabled', 850, 5, 30)
if peace_of_mind == True:
game_display_text('Peace of Mind Enabled', 850, 35, 30)
if invincibility == True:
game_display_text('Invincibility Enabled', 950, 5, 30)
if alpha == True:
game_display_text('FPS: %s' % clock.get_fps(), 5, 635, 30)
pygame.display.update()
clock.tick()
else:
PauseScreen()
DeadScreen()
if __name__ == '__main__':
StartScreen()
sys.exit()

You're doing two things wrong with your text rendering.
The first (and probably major) one is that you load the font again and again every time you want to display some text:
def game_display_text(display_msg, display_x, display_y, text_size):
font = pygame.font.SysFont(None, text_size)
...
You should create the font object once, so you don't load it every time from disk.
The second issue is that the rendering of the text to a Surface is a rather expensive operation:
def game_display_text(display_msg, display_x, display_y, text_size):
...
text = font.render(str(display_msg), True, black)
...
A better method is to cache the already created surfaces, and reuse them.
A very simple cache could look like this:
text_font = pygame.font.SysFont("whatever", 14)
cache={}
def get_msg(msg):
if not msg in cache:
cache[msg] = text_font.render(msg, 1 , text_color)
return cache[msg]
and then you would use the get_msg method to create your text surfaces. Or use something like e.g. the lru_cache decorator.

Related

Im having trouble creating a zoom ability for my vtt

The main problem right now is that the player sprites disappear as soon as I zoom in or out the qrid scales correctly though. I had it working with the player sprites on screen then their movement stopped working. Got a little frustrated, then deleted the zoom altogether. Restarted, and now I'm here so I figured posting my first question because the internet didn't have the answers readily available.
import pygame as pg
class game():
def __init__(self):
self.WIDTH, self.HEIGHT = 1000, 700
self.win = pg.display.set_mode((self.WIDTH, self.HEIGHT), pg.RESIZABLE)
self.mapsurface = pg.surface.Surface((10000, 10000))
self.walls = pg.sprite.Group()
self.all_sprites = pg.sprite.Group()
self.player = Player("map assets/tokens/firegenasiwizard.png", self, 5, 5, self.mapsurface)
self.jplayer = Player("map assets/tokens/goliathbarbarian.png", self, 4, 4, self.mapsurface)
self.players = [self.player, self.jplayer]
def event_tracker(self):
global cellsize, spritesize
for event in pg.event.get():
if event.type is pg.QUIT:
pg.display.quit()
pg.quit()
sys.exit()
if event.type == pg.MOUSEBUTTONDOWN:
pos = pg.mouse.get_pos()
for play in self.players:
if play.rect.x <= pos[0] <= play.rect.x + spritesize and \
play.rect.y <= pos[1] <= play.rect.y + spritesize and play.selected is False:
play.selected = True
elif play.rect.x <= pos[0] <= play.rect.x + spritesize and \
play.rect.y <= pos[1] <= play.rect.y + spritesize and play.selected is True:
play.selected = False
if event.type == pg.KEYDOWN:
for play in self.players:
if event.key == pg.K_UP and play.selected is True:
play.move(dx=0, dy=-1)
if event.key == pg.K_DOWN and play.selected is True:
play.move(dx=0, dy=1)
if event.key == pg.K_LEFT and play.selected is True:
play.move(dx=-1, dy=0)
if event.key == pg.K_RIGHT and play.selected is True:
play.move(dx=1, dy=0)
if event.type == pg.MOUSEWHEEL:
if event.y > 0:
self.mapsurface = pg.transform.scale(self.mapsurface, (self.mapsurface.get_width() + 10,
self.mapsurface.get_height() + 10))
cellsize += 10
spritesize += 10
for play in self.players:
play.scale(10)
if event.y < 0:
self.mapsurface = pg.transform.scale(self.mapsurface, (self.mapsurface.get_width() - 10,
self.mapsurface.get_height() - 10))
cellsize -= 10
spritesize -= 10
for play in self.players:
play.scale(-10)
def draw_grid(self):
self.mapsurface.fill(white)
for x in range(0, self.mapsurface.get_width(), cellsize):
pg.draw.line(self.mapsurface, black, (x, 0), (x, 10000), 1)
for y in range(0, self.mapsurface.get_height(), cellsize):
pg.draw.line(self.mapsurface, black, (0, y), (10000, y), 1)
def draw_window(self):
self.draw_grid()
for play in self.players:
play.draw()
self.win.blit(self.mapsurface, (0, 0))
pg.display.update()

executable file imediatly closes with "NotImplementedError"

I'm trying to use pyinstaller to turn a project into an executable. Pyinstaller creates the directories with sucess, but when I try to run the executable, It gives the following Error.
./main
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "main.py", line 51, in <module>
font = pygame.font.Font("freesansbold.ttf", 30)
File "pygame/pkgdata.py", line 50, in getResource
File "setuptools-40.8.0-py3.6.egg/pkg_resources/__init__.py", line 1134, in resource_exists
File "setuptools-40.8.0-py3.6.egg/pkg_resources/__init__.py", line 1404, in has_resource
File "setuptools-40.8.0-py3.6.egg/pkg_resources/__init__.py", line 1457, in _has
NotImplementedError: Can't perform this operation for unregistered loader type
[8482] Failed to execute script main
This is the main code:
import pygame
from pygame.locals import *
from board import Board
from button import Button
# Initialization and screen surface loading
pygame.init()
screen = pygame.display.set_mode()
screenSize = pygame.display.get_surface().get_size()
width = screenSize[0]
height = screenSize[1]
pygame.display.set_caption("Sudokey: Sudoku's Solver")
# Image and music loading
bgMenu = pygame.image.load("background/sudokey2Menu.png")
bgMenu = pygame.transform.scale(bgMenu, (width, height - 30))
bgStart = pygame.image.load("background/sudokeyCustom.png")
bgStart = pygame.transform.scale(bgStart, (width - 40, height - 55))
pygame.mixer.pre_init()
pygame.mixer.init()
pygame.mixer.music.load("musica/lullabyGhostInYourPiano.mp3")
pygame.mixer.music.play(-1)
click = pygame.mixer.Sound("sons/click.ogg")
# Default screen and game state
running = 1
menu = 1
start = 0
credit = 0
# Mouse logic to detect click
currentSquare = (9, 9)
clickedCell = None
# Creating board using class "Board"
tabuleiro = Board()
# Creating menu buttons using class "Button"
buttonStart = Button(400, 186, 530, 90)
buttonTutorial = Button(400, 325, 530, 90)
buttonOptions = Button(400, 464, 530, 90)
buttonCredits = Button(400, 603, 530, 90)
# Creating start buttons using class "Button"
buttonSolve = Button(898, 40, 380, 80)
buttonReset = Button(898, 159, 380, 80)
buttonGoBack = Button(898, 279, 380, 80)
buttonOptionsStart = Button(898, 398, 380, 80)
# Font loading
font = pygame.font.Font("freesansbold.ttf", 30)
# Visually updates the board
def drawGrid(board):
for i in range(9):
for j in range(9):
if (board[i][j]):
text = font.render(str(board[i][j]), True, (0, 0, 0))
textRect = text.get_rect()
textRect.center = (j * 90 + 45, i * 80 + 45)
screen.blit(text, textRect)
# Plays music based on input
def jukebox(number):
if number == 0:
pygame.mixer.music.stop()
elif number == 1:
pygame.mixer.music.load("musica/lullabyGhostInYourPiano.mp3")
pygame.mixer.music.play(-1)
elif number == 2:
pygame.mixer.music.load("musica/adventureGhostInYourPiano.mp3")
pygame.mixer.music.play(-1)
elif number == 3:
pygame.mixer.music.load("musica/liebestrau.mp3")
pygame.mixer.music.play(-1)
elif number == 4:
pygame.mixer.music.load("musica/Kiss_the_Sky.mp3")
pygame.mixer.music.play(-1)
elif number == 5:
pygame.mixer.music.load("musica/Lullaby.mp3")
pygame.mixer.music.play(-1)
elif number == 6:
pygame.mixer.music.load("musica/Gentle_Breeze.mp3")
pygame.mixer.music.play(-1)
elif number == 7:
pygame.mixer.music.load("musica/Eternal_Hope.mp3")
pygame.mixer.music.play(-1)
elif number == 8:
pygame.mixer.music.load("musica/Pressure.mp3")
pygame.mixer.music.play(-1)
elif number == 9:
pygame.mixer.music.load("musica/01 To the Moon - Main Theme.mp3")
pygame.mixer.music.play(-1)
while running:
while menu:
pygame.display.flip()
screen.blit(bgMenu, (0, 0))
for event in pygame.event.get():
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
menu = 0
elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
start = 1
menu = 0
if event.type == pygame.MOUSEBUTTONUP:
x, y = pygame.mouse.get_pos()
if buttonStart.isOn(x, y):
#click.play()
#click.stop()
print(x, y)
menu = 0
start = 1
elif buttonTutorial.isOn(x, y):
print(x, y)
print('tutorial')
menu = 0
start = 1
elif buttonOptions.isOn(x, y):
print(x, y)
print('Options')
menu = 0
start = 1
elif buttonCredits.isOn(x, y):
print(x, y)
print('Credits')
menu = 0
start = 1
if (event.type == pygame.KEYDOWN):
if (pygame.K_0 <= event.key <= pygame.K_9):
number = int(event.unicode)
jukebox(number)
while start:
pygame.display.flip()
screen.blit(bgStart, (0, 0))
drawGrid(tabuleiro.tabuleiro)
for event in pygame.event.get():
if event.type == pygame.QUIT:
print('stopping')
running = 0
start = 0
elif event.type == pygame.KEYDOWN and (event.key == pygame.K_m or event.key == pygame.K_ESCAPE):
start = 0
menu = 1
if (event.type == pygame.MOUSEBUTTONUP):
coords = pygame.mouse.get_pos()
col = coords[1] // 80
line = coords[0] // 90
clickedCell = (line, col)
if (event.type == pygame.KEYDOWN):
if (clickedCell != None):
if (pygame.K_0 <= event.key <= pygame.K_9):
line = clickedCell[1]
col = clickedCell[0]
number = int(event.unicode)
if 0 <= line <= 8 and 0 <= col <= 8:
tabuleiro.setCell(line, col, number)
clickedCell = None
if (event.type == pygame.KEYDOWN):
if event.key == pygame.K_s:
tabuleiro.findFirst()
tabuleiro.solve()
elif event.key == pygame.K_r:
tabuleiro.reset()
if event.type == pygame.MOUSEBUTTONUP:
x, y = pygame.mouse.get_pos()
print(x, y)
if buttonSolve.isOn(x, y):
print('solving')
tabuleiro.solve()
elif buttonReset.isOn(x, y):
tabuleiro.reset()
tabuleiro.show()
elif buttonGoBack.isOn(x, y):
start = 0
menu = 1
elif buttonOptionsStart.isOn(x, y):
start = 0
menu = 1
pygame.quit()
Thanks in advance. I tried to search for the error on the internet, but didn't had any luck. I'll be grateful if someone can help :)

I made a game where blocks fall and you have to dodge it but can't get the hitboxes right

The hitbox seems to be on the left side of the cube, so it feels like the game is ending without me even hitting anything. I want to make it that the hitbox is exactly on the red rectangle, so that it's obvious that the black rectangle had hit you.
the up and down controls are just for future movement option if needed.
here's the code
import pygame as pg,pygame
import random
import sys
pygame.init()
WIDTH = 1000
HEIGHT = 800
# Positions, sizes
SPEED = 10
MIDDLE = [500, 400]
score = 0
player_size = 90
player_pos = [WIDTH/2, HEIGHT-2*player_size]
playerX_move = 0
playerY_move = 0
enemy_size = 50
enemy_pos = [random.randint(0,WIDTH - enemy_size), 30]
enemy_list = [enemy_pos]
# Colors
WHITE = [255, 255, 255]
GREY = [25, 25, 25]
BLUE = [65,105,225]
BLACK = [0,0,0]
GREEN = [65,255,105]
RED = [255,0,0]
# -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
screen = pygame.display.set_mode((WIDTH,HEIGHT))
game_over = False
clock = pygame.time.Clock()
def drop_enemies(enemy_list):
delay = random.random()
if len(enemy_list) < 10 and delay < 0.1:
x_pos = random.randint(0,WIDTH-enemy_size)
y_pos = 30
enemy_list.append([x_pos, y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,BLACK, (enemy_pos[0], enemy_pos[1], enemy_size, enemy_size))
def update_enemy_positions(enemy_list, score):
for idx, enemy_pos in enumerate(enemy_list):
if enemy_pos[1] >= 0 and enemy_pos[1] < HEIGHT:
enemy_pos[1] += SPEED
else:
enemy_list.pop(idx)
score += 1
return score
def collision_check(enemy_list, player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos, player_pos):
return True
return False
def detect_collision(player_pos, enemy_pos):
p_x = player_pos[0]
p_y = player_pos[1]
e_x = enemy_pos[0]
e_y = enemy_pos[1]
if (e_x >= p_x and e_x < (p_x + player_size)) or (p_x >= e_x and p_x < (e_x+enemy_size)):
if (e_y >= p_y and e_y < (p_y + player_size)) or (p_y >= e_y and p_y < (e_y+enemy_size)):
return True
return False
while not game_over:
player_pos[0] += playerX_move
player_pos[1] += playerY_move
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_move = -5
if event.key == pygame.K_RIGHT:
playerX_move = 5
# if event.key == pygame.K_UP:
# playerY_move = -5
# if event.key == pygame.K_DOWN:
# playerY_move = 5
if event.key == pygame.K_a:
playerX_move = -15
if event.key == pygame.K_d:
playerX_move = 15
# if event.key == pygame.K_w:
# playerY_move = -15
# if event.key == pygame.K_s:
# playerY_move = 15
if event.key == pg.K_SPACE:
print("SPACE")
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d or event.key == pygame.K_s or event.key == pygame.K_w:
playerX_move = 0
playerY_move = 0
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN or event.key == pygame.K_UP:
playerX_move = 0
playerY_move = 0
screen.fill(BLACK)
drop_enemies(enemy_list)
score = update_enemy_positions(enemy_list,score)
if collision_check(enemy_list, player_pos):
game_over = True
draw_enemies(enemy_list)
pygame.draw.rect(screen, RED, (player_pos[0], player_pos[1], 90, 90))
clock.tick(30)
pygame.display.update()
I would recommend using a list of pygame.Rects instead of a List with the positions of your enemies. This would also allow you to use pygame.Rect.colliderect() instead of your detect_collision function.
I've also linked the Pygame Docs.

New to Pygame, trying to rotate a png image but it it freezing the window

This is my program ive been working on with pygame, its a snake-like game where you collect apples to extend your snake and gain score, simple. But my problem atm is i am trying rotate my .png file snake head so it rotates with the snake as it moves, but whenever i try to the window freezes. The code that is freezing the window is just one extra line of code on (python) line 112, the line of code is simply:
return direction
This is the working code below:
import pygame
import time
import random
pygame.init()
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Snake')
img_snake_head = pygame.image.load('C:/Users/Pc/Desktop/School Stuff/Programs/Python Programs/Large Projects & Home Projects/Snake Pygame/snake_head.png')
clock = pygame.time.Clock()
direction = "right"
font = pygame.font.SysFont(None, 45)
def snake(block_size, snakelist):
if direction == "right":
head = pygame.transform.rotate(img_snake_head, 270)
if direction == "left":
head = pygame.transform.rotate(img_snake_head, 90)
if direction == "up":
head = img_snake_head
if direction == "down":
head = pygame.transform.rotate(img_snake_head, 180)
gameDisplay.blit(img_snake_head, (snakelist[-1][0],snakelist[-1][1]))
for XnY in snakelist[:-1]:
pygame.draw.rect(gameDisplay, green, [XnY[0], XnY[1], block_size, block_size])
def message_to_screen(msg,colour):
screen_text = font.render(msg, True, colour)
gameDisplay.blit(screen_text, [display_width/2 - screen_text.get_width()/2, display_height/2 - screen_text.get_height()/2])
def gameLoop():
global direction
PlayerScore = 0
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
direction = "left"
lead_x_change = -block_size
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
direction = "right"
lead_x_change = block_size
lead_y_change = 0
elif event.key == pygame.K_UP:
direction = "up"
lead_y_change = -block_size
lead_x_change = 0
elif event.key == pygame.K_DOWN:
direction = "down"
lead_y_change = block_size
lead_x_change = 0
#This is where the 'return direction' goes, as i mentioned which was the code freezing the window...
if lead_x >= display_width or lead_x <= 0 or lead_y >= display_height or lead_y <= 0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(blue)
pygame.draw.rect(gameDisplay, red, [randAppleX,randAppleY,AppleThickness,AppleThickness])
snakehead = []
snakehead.append(lead_x)
snakehead.append(lead_y)
snakelist.append(snakehead)
snake(block_size, snakelist)
if len(snakelist) > snakelength:
del snakelist[0]
if snakeMoving == True:
if snakehead in snakelist[:-1]:
gameOver = True
snake(block_size, snakelist)
scoretext = font.render("Score: "+str(PlayerScore), 0, (10,10,10))
gameDisplay.blit(scoretext, (5, 10))
pygame.display.update()
if lead_x >= randAppleX and lead_x < randAppleX + AppleThickness or lead_x + block_size > randAppleX and lead_x + block_size < randAppleX + AppleThickness:
if lead_y >= randAppleY and lead_y < randAppleY + AppleThickness or lead_y + block_size > randAppleY and lead_y + block_size < randAppleY + AppleThickness:
randAppleX = round(random.randrange(10, display_width-AppleThickness)/10.0)*10.0
randAppleY = round(random.randrange(10, display_height-AppleThickness)/10.0)*10.0
snakelength += 1
PlayerScore += 10
clock.tick(FPS)
pygame.quit()
quit()
gameLoop()
I hope someone can tell me why this is freezing as soon as possible! Thanks in advance!
The problem was that you assigned the rotated image to a variable head but blitted img_snake_head. In your snake function change:
gameDisplay.blit(img_snake_head, (snakelist[-1][0],snakelist[-1][1]))
to
gameDisplay.blit(head, (snakelist[-1][0],snakelist[-1][1]))
and it should fix the problem.

TypeError, having issues defining certain things

Ok So, I'm making a simple game in python and pygame, where you're a spaceship and have to dodge meteors. But after adding in the meteor and writing the code to get it to spawn randomly and move down the screen. I had issues using the code tags as well, I'd do Ctrl + K and post my code inside the space provided and it gave me the code error. Sorry about that, here's my links (not the best way to do it I know, I couldn't get the code tags to work.)
My Error:
Traceback (most recent call last):
File "C:\Users\fredd_000\Desktop\Pygame_Script.py", line 127, in <module>
game_loop()
File "C:\Users\fredd_000\Desktop\Pygame_Script.py", line 98, in game_loop
things(thing_startx, thing_starty, thing_width, thing_height, black)
File "C:\Users\fredd_000\Desktop\Pygame_Script.py", line 28, in things
pygame.draw.circle(gameDisplay, color,[thingx, thingy, thingw, thingh])
TypeError: function takes at least 4 arguments (3 given)
My code where the error occurs:
def things(thingx, thingy, thingw, thingh, color):
pygame.draw.circle(gameDisplay, color,[thingx, thingy, thingw, thingh])
Full code:
import pygame
import time
import random
pygame.init()
display_width = 1200
display_height = 800
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('A Game By Freddie')
black = (0,0,0)
white = (255,255,255)
blue = (25,0,255)
red = (255,0,0)
car_width = 195
car_height = 1
clock = pygame.time.Clock()
gameExit = False
shipImg = pygame.image.load('ship.png')
def things(thingx, thingy, thingw, thingh, color):
pygame.draw.circle(gameDisplay, color,[thingx, thingy, thingw, thingh])
def ship(x,y):
gameDisplay.blit(shipImg, (x,y))
def text_objects(text, font):
textSurface = font.render(text, True, red)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',120)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
game_loop()
def crash():
message_display('You Died')
def game_loop():
x = (display_width * 0.375)
y = (display_height * 0.65)
x_change = 0
y_change = 0
thing_startx = random.randrange(0, display_width)
thing_starty = -600
thing_speed = 7
thing_width = 100
thing_height = 100
gameExit = False
while not gameExit:
gameDisplay.fill(blue)
shipImg = pygame.image.load('ship.png')
ship(x,y)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
things(thing_startx, thing_starty, thing_width, thing_height, black)
thing_starty += thing_speed
if x > display_width - car_width or x < 0:
crash()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
y += y_change
if y > display_height - car_height or y < 0:
crash()
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
The problem with your code is that your using pygame.draw.circle() wrong. The syntax for using the function is: pygame.draw.circle(screen, color, (x, y), diameter). As you can probably tell, the way you did it was pygame.draw.circle(screen, color, [x, y, w, h]). This is incorrect, a circle does not have a width and height. Change your code to: pygame.draw.circle(gameDisplay, color, (thingx, thingy), thingw). thingw will be the diameter of your circle.
You should also change your function paramters to def things(thingx, thingy, thingw, color).
If your still new to Pygame or confused on how to draw shapes to the screen, i highly suggest reading the Pygame documentation on drawing, as Idos linked to in the comments.

Resources