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.