Random generated platforms seems to be hollow (Python - pygame) [duplicate] - python

This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
The random generated platforms are displayed yet the character still goes through the platforms as if they weren't there.
I'm a complete newbie at pygame (im just watching a bunch of random tutorials on youtube)
Here's the main script:
import pygame as pg
import random
from settings import *
from sprites import *
class Game:
def __init__(self):
# initialize game window, etc.
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((width, height), pg.FULLSCREEN)
pg.display.set_caption(title)
self.clock = pg.time.Clock()
self.running = True
self.game_over = False
self.font_name = pg.font.match_font(font_name)
self.score = 0
self.orig_pos = 0
self.sequence = []
self.newPlatform = 90 + height
self.newPlatformInterval = 100
def new(self):
# starting a new game
self.score = 0
self.all_sprites = pg.sprite.Group()
self.platforms = pg.sprite.Group()
for platform in platform_list:
p = Platform(*platform)
self.all_sprites.add(p)
self.platforms.add(p)
self.player = Player(self)
self.all_sprites.add(self.player)
self.run()
def run(self):
# Game loop
while self.running:
self.clock.tick(fps)
self.events()
self.update()
self.draw()
def update(self):
# game loop update
# Plan here was to spawn platforms with specific number of gaps
# The platforms has to be aligned, and has to have enough room for the ball to fall and navigate through
# ISSUE: Platforms are hollow after the initial pre-placed platforms. Still looking into this issue
# Open for suggestions
self.player.update()
# self.platforms.update()
self.timePoint = pg.time.get_ticks()
# check if player hits a platform - only if falling!
for platform in self.platforms:
platform.rect.y -= 2
if platform.rect.top <= -30:
platform.kill()
if self.player.vel.y > 0:
hits = pg.sprite.spritecollide(self.player, self.platforms, False)
self.score += 1
if hits:
self.player.pos.y = hits[0].rect.top - 2
self.player.vel.y = 0
# if player reaches top 1/4 of the screen
"""if self.player.rect.top <= height / 4:
self.player.pos.y += abs(self.player.vel.y)"""
if self.player.rect.bottom > (height / 4) * 3:
for sprite in self.all_sprites:
sprite.rect.y -= max(self.player.vel.y, 10)
"""if sprite.rect.bottom < 10:
sprite.kill()"""
for sprite in self.platforms:
if sprite.rect.bottom < 0:
sprite.kill()
if self.player.rect.top < 0:
self.game_over = True
if len(self.platforms) < 12:
gaps = random.randint(1, 5)
gaps_1 = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
gaps_2 = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
gaps_3 = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
gaps_4 = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
if gaps == 1:
random.shuffle(gaps_1)
self.sequence = gaps_1
elif gaps == 2:
random.shuffle(gaps_2)
self.sequence = gaps_2
elif gaps == 3:
random.shuffle(gaps_3)
self.sequence = gaps_3
elif gaps == 4:
random.shuffle(gaps_4)
self.sequence = gaps_4
else:
random.shuffle(gaps_2)
self.sequence = gaps_2
for x in self.sequence:
if x == 1:
p = Platform(self.orig_pos, self.newPlatform, width / 12, 20)
self.platforms.add(p)
self.all_sprites.add(p)
self.platforms.update()
self.orig_pos += width / 12
else:
self.orig_pos += width / 12
# Initial plan was to spawn new platforms to keep same average number
# wide = width / 8
# p = Platform(random.randrange(0, width - wide), random.randrange(120 + height, 350 + width), wide, 20)
"""p = Platform(random.randrange(0, width / 4), 120 + height, wide, 20)
p1 = Platform(random.randrange(100 + width / 4, width), 120 + height, wide, 20)
self.platforms.add(p)
self.platforms.add(p1)
self.all_sprites.add(p)
self.all_sprites.add(p1)"""
def events(self):
# Game loop - EVENTS
for event in pg.event.get():
# check for closing window
if event.type == pg.QUIT:
self.running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
self.running = False
elif event.key == pg.K_r:
self.game_over = False
self.new()
keys = pg.key.get_pressed()
if keys[pg.K_ESCAPE]:
self.running = False
if keys[pg.K_r]:
self.game_over = False
self.new()
def draw(self):
# Game loop for drawing graphics
if not self.game_over:
self.screen.fill(gray)
self.all_sprites.draw(self.screen)
self.draw_text(str(self.score), 22, white, width / 2, 50)
else:
self.screen.fill(dark_red)
self.draw_text('GAME OVER', 26, white, width / 2, height / 2 - 30)
self.draw_text('Press ESC to exit the game.', 24, white, width / 2, height / 2)
self.draw_text('Press \'r\' to restart the game.', 24, white, width / 2, height / 2 + 30)
# *after* drawing everything, flip the display
pg.display.flip()
def show_start_screen(self):
# show splash / start screen
pass
def show_go_screen(self):
# show game over / continue
pass
def draw_text(self, text, size, color, x, y):
# function for drawing the text on the screen
font = pg.font.Font(self.font_name, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
self.screen.blit(text_surface, text_rect)
g = Game()
g.show_start_screen()
while g.running:
if not g.game_over:
g.new()
g.show_go_screen()
pg.quit()
I have no idea what I did wrong.
(im also open for suggestions :D )
EDIT: I edited the code a little bit (i added a limit where it shouldnt spawn platforms if there are already 24 platforms displayed. But now the platforms are no longer showing up.

Related

How to make a scoreboard for the flappy bird?

I'm making a game for Flappy Bird, I need to make a score counter, it's there, but it's crooked. It counts a whole bunch of points after the first pipe and does not reset them after death. Below I will attach the code itself and the code of the points.
If you can write the code as it will be correct.
import pygame#импортирование модуля pygame
import random#Добавляет возможность спавнить разные трубы
pygame.init()
WIDTH, HEIGHT = 800, 600#FPS и размеры окна
FPS = 60
window = pygame.display.set_mode((WIDTH, HEIGHT))#Создание окна
clock = pygame.time.Clock()
font1 = pygame.font.Font(None, 35)#шрифты
font2 = pygame.font.Font(None, 80)
imgBG = pygame.image.load('images/fon.png')#Добавление картинок
imgBIRD = pygame.image.load('images/bird.png')
imgPB = pygame.image.load('images/PB.png')
imgPT = pygame.image.load('images/PT.png')
py, sy, ay = HEIGHT // 2, 0, 0 #Значение по py, sy, ay
player = pygame.Rect(HEIGHT // 3, py, 50, 50) #расположение игрока по центру
state = 'start'#состояние старта
timer = 10 #Задержка
pipes = [] #Список труб
bges = [] #Список заднего фона
bges.append(pygame.Rect(0, 0, 288, 600)) #Отображение заднего фона
lives = 3 #Жизни
scores = 0 #Очки
play = True
while play:
for event in pygame.event.get():
if event.type == pygame.QUIT:
play = False
press = pygame.mouse.get_pressed() #Нажатие мыши
keys = pygame.key.get_pressed() #Нажатие пробела
click = press[0] or keys[pygame.K_SPACE]
if timer > 0:
timer -= 1
for i in range(len(bges)-1, -1, -1): #Проверка на удаление и добавление фона
fon = bges[i]
fon.x -= 1
if fon.right < 0:
bges.remove(fon)
if bges[len(bges)-1].right <= WIDTH:
bges.append(pygame.Rect(bges[len(bges)-1].right, 0, 288, 512))##########
for i in range(len(pipes)-1, -1, -1): #Добавление и удаление труб
pipe = pipes[i]
pipe.x -= 3
if pipe.right < 0:
pipes.remove(pipe)###################
if state == 'start':#Состояние статического
if click and timer == 0 and len(pipes) == 0:
state = 'play'
py += (HEIGHT // 2 - py) * 0.1
player.y = py
elif state == 'play': #Состояние если игрок нажимает на кнопку то оно переходит в состояние игры
if click:
ay = -2
else:
ay = 0
py += sy
sy = (sy + ay + 1) * 0.98
player.y = py
if len(pipes) == 0 or pipes[len(pipes)-1].x < WIDTH - 200: #отображение труб
pipes.append(pygame.Rect(WIDTH, 0, 52, 200))
pipes.append(pygame.Rect(WIDTH, 400, 52, 200))
if player.top < 0 or player.bottom > HEIGHT:#Проверка столкновение с трубами
state = 'fall'
for pipe in pipes:
if player.colliderect(pipe):
state = 'fall'
for pipe in pipes:
if player > pipe:
scores += 1
elif state == 'fall':####Состояние когда игрок не может ничего делать
sy, ay = 0, 0
state = 'start'
timer = 60
else:
pass
for fon in bges: #Отображение заднего фона
window.blit(imgBG, fon)##########
for pipe in pipes:#Рисовка труб
if pipe.y == 0:
rect = imgPB.get_rect(bottomleft = pipe.bottomleft)
window.blit(imgPB, rect)
else:
rect = imgPT.get_rect(topleft = pipe.topleft)
window.blit(imgPT, rect)##########
window.blit(imgBIRD, player)#Рисовка игрока
text = font1.render('Очки: ' + str(scores), 1, pygame.Color('White')) #Текст очки
window.blit(text, (10, 10))
text = font1.render('Жизни: ' + str(lives), 1, pygame.Color('White'))#Текст жизни
window.blit(text, (110, 10))
pygame.display.update()#Обновление экрана
clock.tick(FPS)
pygame.quit()
Code scores
for pipe in pipes:
if player > pipe:
scores += 1
You should replace if player > pipe: with if pipe.x < player <= (pipe.x + 3): to fix the game adding a bunch of points (instead of adding 1 to the score for each pipe passed so far, it adds 1 if you're in a pipe).
Change the 3 of pipe + 3 by the speed of your pipes (in case of your program it's 3 so I put 3).
For the score not resetting, I suggest replacing this
elif state == 'fall'
sy, ay = 0, 0
state = 'start'
timer = 60
by this
elif state == 'fall'
sy, ay = 0, 0
state = 'start'
timer = 60
scores = 0
assuming this is the part that does stuff upon 'death'.
Not sure it'll work, but it may.
EDIT:
For any problems like TypeError, replace the pipe by pipe.x in the previous test (if pipe < player <= (pipe + 3):) so it gives if pipe.x < player <= (pipe.x + 3):. It should work now...

Pygame - Fix issue with pause menu? [duplicate]

I've developed a Python code and am looking for improvements and how to add a pause option.
I repeat the exact same lines one after another although I don't know an easier way to do it.
import math, pygame, random, sys, turtle
from itertools import cycle
from datetime import datetime
from pygame import gfxdraw
from pygame.locals import *
def print_text(surface, font, text, surf_rect, x = 0, y = 0, center = False, color = (255,215,0)):
if not center:
textimage = font.render(text, True, color)
surface.blit(textimage, (x, y))
else:
textimage = font.render(text, True, color)
text_rect = textimage.get_rect()
x = (surf_rect.width // 2) - (text_rect.width // 2 )
surface.blit(textimage, (x, y))
def game_is_over(surface, font, ticks):
timer = ticks
surf_rect = surface.get_rect()
surf_height = surf_rect.height
surf_width = surf_rect.width
print_text(screen, font, "Y O U G O T Y E E T E D (Game Over)", surf_rect, y = 260,\
center = True)
pygame.display.update()
while True:
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if ticks > timer + 3000:
break
def next_level(level):
level += 1
if level > 6:
level = 6
return level
#The Level Creator
def load_level(level):
invaders, colors = [], []
start_intx, end_intx, increment_intx = 85, 725, 40
start_inty, end_inty, increment_inty = 60, 60, 30
end_inty = end_inty + level * 30 # 30 being the number of rows / intruders
color_val = 256 / end_inty #For Colour Repetition
for x in range(start_intx, end_intx, increment_intx):
for y in range(start_inty, end_inty, increment_inty):
invaders.append(pygame.Rect(x, y, 30, 15))
colors.append(((x * 0.35) % 256, (y * color_val) % 256))
return invaders, colors, len(invaders)
def draw_title_invader():
rect = Rect(285,247,230,115)#INVATOR
rect2 = Rect(0,0,230,115)
rect3 = Rect(340,120,120,128)#TOP OF HAT
rect4 = Rect(300,200,200,48)#BOT OF HAT
rect5 = Rect(340,182,120,18)#LINE IN HAT
rect_width = 230
a = 175
b = 55
pygame.draw.rect(backbuffer, MGOLD,rect)
#The Left Eye in Title Screen
pygame.draw.circle(backbuffer,(0,255,255), (rect.x+46,rect.y+30), 23)
#The Right Eye in Title Screen
pygame.draw.circle(backbuffer,(0,255,255),(rect.x+rect_width-46,rect.y+30)\
,23)
#The Left Side Mouth in Title Screen
pygame.draw.line(backbuffer, RED, (rect.x+46, rect.y+92),\
(rect.x + 115, rect.y + 61), 2)
#The Right Side Mouth in Title Screen
pygame.draw.line(backbuffer, RED, (rect.x+rect_width-46,\
rect.y+92), (rect.x+rect_width-115,\
rect.y+61), 2)
#The Right Eye
pygame.draw.circle(backbuffer,RED,(rect.x+rect_width-115,rect.y+65)\
,23)
#The Hat
pygame.draw.rect(backbuffer, DIMGRAY,(340,120,120,128))
pygame.draw.rect(backbuffer, DIMGRAY,(300,200,200,48))
pygame.draw.rect(backbuffer, WHITE,(340,182,120,18))
def draw_bonus_invader(i, bonus_color, bx, bonus_x):
x, y = bonus_invader.x, bonus_invader.y
pygame.draw.circle(backbuffer, bonus_color, (x+bx, y+7), 2)
if i == 0:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 1:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 2:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 3:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 4:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 5:
bx = next(bonus_x)
def draw_invader(backbuffer, rect, a, b, animate_invaders, ticks,\
animation_time):
invader_width = 30
#THe Intruder In Game
pygame.draw.rect(backbuffer, MGOLD, rect)
#CONSOLE GRAY
pygame.draw.rect(backbuffer, DIMGRAY,(0,510,800,110))
#Left Eye in game
pygame.gfxdraw.filled_circle(backbuffer, rect.x + 6, rect.y + 4, 3, \
RED)
#Right EYe in game
pygame.gfxdraw.filled_circle(backbuffer, rect.x + invader_width - 7,\
rect.y + 4, 3, RED)
#The draw animation (if needed)
if animate_invaders:
pygame.gfxdraw.filled_trigon(backbuffer, rect.x+6, rect.y + 12,\
rect.x + 14, rect.y + 4, rect.x +\
invader_width - 7, rect.y + 12, RED)
else:
#The Left Side of the mouth
pygame.gfxdraw.line(backbuffer, rect.x + 6, rect.y + 12,\
rect.x + 15, rect.y + 8, RED)
#The Right Side of the mouth
pygame.gfxdraw.line(backbuffer, rect.x + invader_width - 7,\
rect.y + 12, rect.x + invader_width - 15,\
rect.y + 8, RED)
if ticks > animation_time + 200:
animate_invaders = False
return animate_invaders
pygame.init()
pygame.mixer.init() # not always called by pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Yeet The Intruders")
fpsclock = pygame.time.Clock()
#get screen metrics
the_screen = screen.get_rect()
screen_width = the_screen.width
screen_height = the_screen.height
backbuffer = pygame.Surface((the_screen.width, the_screen.height))
# fonts
font1 = pygame.font.SysFont(None, 30)
font2 = pygame.font.SysFont("Impact", 54)
font3 = pygame.font.SysFont("Impact", 36)
# User event frequencies
RELOAD_SPEED = 400
MOVE_SIDEWAYS = 1000
MOVE_DOWN = 1000
BONUS_FREQ = 10000
INV_SHOOT_FREQ = 500
# create user events
move_invaders_sideways = pygame.USEREVENT + 1
move_invaders_down = pygame.USEREVENT + 2
reload = pygame.USEREVENT + 3
invader_shoot = pygame.USEREVENT + 4
bonus = pygame.USEREVENT + 5
# event timers
pygame.time.set_timer(move_invaders_down, 0)
pygame.time.set_timer(move_invaders_sideways, MOVE_SIDEWAYS)
pygame.time.set_timer(reload, RELOAD_SPEED)
pygame.time.set_timer(invader_shoot, INV_SHOOT_FREQ)
pygame.time.set_timer(bonus, BONUS_FREQ)
#List of Colours used
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
DIMGRAY = (105,105,105)
MGOLD = (212,175,55)
shots, invader_shots, inv_shot_colors, bonus_invaders = [], [], [], []
#MY Space Ship
player = Rect(380,578,42,20)
player_gun = Rect(player.x + 18,player.y - 4, 6, 4)
# make screen rect for purposes of text-centering etc
the_screen = screen.get_rect()
# invader animation variables
animation_time = 0
animate_invaders = False
invader_width = 30
invader_height = 15
# flashing text vars
the_text = cycle(["Press Enter To Play, Yeet Master...", ""])
insert = next(the_text)
flash_timer = 0
# flashing bonus item vars
y1,y2,y3,y4,y5,y6 = (255,255,0), (225,225,0), (195,195,0), (165,165,0),\
(135,135,0), (105,105,0)
bonus_colors = cycle([y1,y2,y3,y4,y5,y6])
bonus_color = next(bonus_colors)
bonus_x = cycle([4,11,18,25,32,39]) # change draw x coord
bonus_timer = 0 # used to control frequency of changes
# vars for moving invaders down
move_right, move_down, reloaded = True, True, True
vert_steps = 0
side_steps = 0
moved_down = False
invaders_paused = False
invaders = 0 # prevents error until list is created
initial_invaders = 0 # use to manage freq of inv shots as invaders removed
shoot_level = 1 # manage freq of shots
# various gameplay variables
game_over = True
score = 0
lives = 2
level = 0
playing = False
# event loop
while True:
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYUP:
if event.key == pygame.K_1 and not game_over:
print("Next level")
if event.type == invader_shoot and not game_over:
i = random.randint(0, len(invaders)-1)
shot_from = invaders[i]
a, b = colors[i]
invader_fired = True
invader_shots.append(Rect(shot_from.x, shot_from.y, 5, 7))
inv_shot_colors.append(RED)
if event.type == reload and not game_over:
reloaded = True
pygame.time.set_timer(reload, 0)
if event.type == move_invaders_sideways and not game_over:
if move_right:
for invader in invaders: invader.move_ip(10,0)
side_steps += 1
else:
for invader in invaders: invader.move_ip(-10,0)
side_steps -= 1
if side_steps == 6 or side_steps == -6:
if vert_steps <= 31: # and not moved_down
pygame.time.set_timer(move_invaders_sideways, 0)
pygame.time.set_timer(move_invaders_down, MOVE_DOWN)
# keep invaders moving horizontally after 31 down movements
else: move_right = not move_right
if event.type == move_invaders_down and not game_over:
#for i in range(20): print("down event")
move_right = not move_right
animate_invaders = True
animation_time = ticks
# reset move_sideways timer
pygame.time.set_timer(move_invaders_sideways, MOVE_SIDEWAYS)
# cancel move_down timer
pygame.time.set_timer(move_invaders_down, 0)
for invader in invaders: invader.move_ip(0,10)
vert_steps += 1
if event.type == bonus and not game_over:
#a = Rect(769,20,45,15)
bonus_invaders.append(Rect(797,20,45,15))
# keyboard polling
pressed = pygame.key.get_pressed()
if pressed[K_ESCAPE]: pygame.quit(), sys.exit()
elif pressed[K_RETURN]:
if game_over: game_over = False
elif pressed[K_d] or pressed[K_RIGHT]:player.move_ip((8, 0))
#player_gun.move_ip((8,0))
elif pressed[K_a] or pressed[K_LEFT]: player.move_ip((-8, 0))
if pressed[K_SPACE]:
if reloaded:
reloaded = False
# create timeout of RELOAD_SPEED
pygame.time.set_timer(reload, RELOAD_SPEED)
# shrink copy of player rect to imitate a missile
missile = player.copy().inflate(-38, -10)
# spawn missile higher to ensure appears missile fired from 'gun'
# when the ship is moving horizontally
missile.y -= 9
shots.append(missile)
#missile_sound.play()
backbuffer.fill(BLACK)
if not game_over:
playing = True
if level == 0:
level = next_level(level)
invaders, colors, initial_invaders = load_level(level)
move_right, move_down, reloaded = True, True, True
vert_steps = 0
side_steps = 0
moved_down = False
invaders_paused = False
pygame.time.set_timer(invader_shoot, 500)
shoot_level = 1
for shot in invader_shots:
shot.move_ip((0,random.randint(5,11)))
if not backbuffer.get_rect().contains(shot):
i = invader_shots.index(shot)
del invader_shots[i]
del inv_shot_colors[i]
if shot.colliderect(player) and shot.y < the_screen.height -10:
lives -= 1
if lives < 0:
lives = 0
game_over = True
i = invader_shots.index(shot)
del invader_shots[i]
del inv_shot_colors[i]
for shot in shots:
shot.move_ip((0, -8))
for inv_shot in invader_shots:
if inv_shot.colliderect(shot):
shots.remove(shot)
i = invader_shots.index(inv_shot)
del invader_shots[i]
del inv_shot_colors[i]
for b_invader in bonus_invaders:
if b_invader.colliderect(shot):
shots.remove(shot)
i = bonus_invaders.index(b_invader)
del bonus_invaders[i]
score += 1
if not backbuffer.get_rect().contains(shot):
shots.remove(shot)
else:
hit = False
for invader in invaders:
if invader.colliderect(shot):
score += 1
hit = True
i = invaders.index(invader)
del invaders[i]
del colors[i]
if hit: shots.remove(shot)
# move bonus invader
for bonus_invader in bonus_invaders:
bonus_invader.move_ip((-4,0 ))
## if not screen.get_rect().contains(bonus_invader):
## bonus_invaders.remove(bonus_invader)
if bonus_invader.x < -55:
bonus_invaders.remove(bonus_invader)
# check if all invaders killed, if so, move to next level
if len(invaders) == 0:
level = next_level(level)
invaders, colors, initial_invaders = load_level(level)
move_right, move_down, reloaded = True, True, True
vert_steps = 0
side_steps = 0
moved_down = False
invaders_paused = False
pygame.time.set_timer(invader_shoot, 500)
shoot_level = 1
# adjust shot freq when invader numbers decrease
if len(invaders) < initial_invaders*.75 and shoot_level == 1:
pygame.time.set_timer(invader_shoot, 750)
shoot_level = 2
elif len(invaders) < initial_invaders*.5 and shoot_level == 2:
pygame.time.set_timer(invader_shoot, 1000)
shoot_level = 3
elif len(invaders) < initial_invaders*.25 and shoot_level == 3:
pygame.time.set_timer(invader_shoot, 1500)
shoot_level = 4
# draw invaders
for rect, (a, b) in zip(invaders, colors):
animate_invaders = draw_invader(backbuffer, rect, a, b,\
animate_invaders, ticks, \
animation_time)
# draw bonus invaders
if ticks > bonus_timer + 169:
bonus_timer = ticks # change colors every 169ms approx
for bonus_invader in bonus_invaders:
pygame.draw.rect(backbuffer, (0,0,0,0), bonus_invader)
pygame.draw.ellipse(backbuffer,MGOLD,bonus_invader)
for i in range(6):
bonus_color = next(bonus_colors)
bx = next(bonus_x)
draw_bonus_invader(i, bonus_color, bx, bonus_x)
# draw space ship shots
for shot in shots:
pygame.draw.rect(backbuffer, GREEN, shot)
# draw invader shots
for shot, color in zip(invader_shots, inv_shot_colors):
pygame.draw.rect(backbuffer, color, shot)
#update 'gun' position and draw ship/gun
#player_gun = Rect(player.x, player.y, 6, 4)
player_gun.x = player.x+18
pygame.draw.rect(backbuffer, (204,0,255), player)
pygame.draw.rect(backbuffer, (0,204,255), player_gun)
player.clamp_ip(backbuffer.get_rect())
print_text(backbuffer, font1, "Intruders Rekt#: {}".format(score),\
the_screen, x=0, y=520)
print_text(backbuffer, font1, "Hearts#: {}".format(lives), the_screen,\
x=0, y=550)
print_text(backbuffer, font1, "Round#: {}".format(level), the_screen,\
x=0, y=580)
if game_over:
if playing:
game_is_over(backbuffer, font2, ticks)
playing = False
level = 0
lives = 2
score = 0
shots, invader_shots, inv_shot_colors, bonus_invaders = [], [], [], []
print_text(backbuffer, font2, "_/¯Yeet The Intruders¯\_", the_screen, y=5,\
center=True)
draw_title_invader()
if ticks > flash_timer + 800: # "press to play" flashing text
insert = next(the_text)
flash_timer = ticks
print_text(backbuffer, font3, insert, the_screen, y =\
the_screen.height-40, center=True)
screen.blit(backbuffer, (0,0))
pygame.display.update()
fpsclock.tick(30)
Your code is quite large, but to pause the game is very general task:
Add a pause state.
Toggle the pause state on an certain event, e.g. when the p key is pressed.
Skip the game processing if pauseis stated.
e,.g.
pause = False # pause state
while True:
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYUP:
if event.key == pygame.K_1 and not game_over:
print("Next level")
# toggle pause if "p" is pressed
if event.key == pygame.K_p:
pause = not pause
# [...]
if pause:
# [...] draw pause screen
pass
elif not game_over: # <--- elif is important
playing = True
# [...]
screen.blit(backbuffer, (0,0))
pygame.display.update()
fpsclock.tick(30)

Pygame bug, music will not play properly as it just loops the beginning part

I'm working on a basic shooter game in Pygame (I'm following a tutorial.) I decided to add background music to keep things nice.
Code (quite long!):
import pygame
from pygame import image as sprite
pygame.init()
dow = pygame.display.set_mode((1000, 700))
pygame.display.set_caption("PY.Touhou")
clock = pygame.time.Clock()
rightSprites = [sprite.load('ness-right1.png'),
pygame.image.load('ness-right2.png'),
pygame.image.load('ness-right3.png'),
pygame.image.load('ness-right4.png'),
pygame.image.load('ness-right5.png'),
pygame.image.load('ness-right6.png'),
pygame.image.load('ness-right7.png'),
pygame.image.load('ness-right8.png')
]
leftSprites = [
sprite.load('ness-left1.png'),
sprite.load('ness-left2.png'),
sprite.load('ness-left3.png'),
sprite.load('ness-left4.png'),
sprite.load('ness-left5.png'),
sprite.load('ness-left6.png'),
sprite.load('ness-left7.png'),
sprite.load('ness-left8.png')
]
scene = pygame.image.load('bg.png')
idle = pygame.image.load('ness-idle.png')
class Player(object):
def __init__(self, x_pos, y_pos, w, h):
self.x_pos = x_pos
self.y_pos = y_pos
self.w = w
self.h = h
self.velocity = 15
self.JUMPbool = False
self.atleft = False
self.atright = False
self.steps = 0
self.jumpheight = 12
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
self.still = True
def move(self):
if self.steps + 1 >= 24:
self.steps = 0
if not self.still:
if self.atleft:
dow.blit(leftSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
elif self.atright:
dow.blit(rightSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
else:
if self.atright:
dow.blit(rightSprites[1], (self.x_pos, self.y_pos))
else:
dow.blit(leftSprites[1], (self.x_pos, self.y_pos))
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
# pygame.draw.rect(dow, (0, 0, 255), self.hitbox, 2)
class IceBullet(object):
def __init__(self, x_pos, y_pos, radius, color, direction):
self.x_pos = x_pos
self.y_pos = y_pos
self.radius = radius
self.color = color
self.direction = direction
self.velocity = 8 * direction
def summon(self):
pygame.draw.circle(dow, self.color, (self.x_pos, self.y_pos), self.radius)
class EnemyCirno(object):
erightSprites = [sprite.load('e-right%s.png' % pic) for pic in range(1, 9)]
eleftSprites = [sprite.load('e-left%s.png' % pic) for pic in range(1, 9)]
def __init__(self, x_pos, y_pos, w, h, ending):
self.x_pos = x_pos
self.y_pos = y_pos
self.w = w
self.h = h
self.ending = ending
self.path = [self.x_pos, self.ending]
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
self.steps = 0
self.health = 20
self.isAlive = True
self.velocity = 4
def summon(self):
self.move()
if self.isAlive:
if self.steps + 1 >= 24:
self.steps = 0
if self.velocity > 0:
dow.blit(self.erightSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
else:
dow.blit(self.eleftSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
pygame.draw.rect(dow, (255, 10, 0), (100, 110, 400, 20))
pygame.draw.rect(dow, (5, 255, 10), (100, 110, 200 - (20 * (10 - self.health)), 20))
enemy_health = italicStyle.render('Enemy Health', 1, (255, 0, 0))
dow.blit(enemy_health, (100, 150))
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
# pygame.draw.rect(dow, (0, 0, 0), self.hitbox, 2)
def move(self):
if self.velocity > 0:
if self.x_pos + self.velocity < self.path[1]:
self.x_pos += self.velocity
else:
self.velocity = self.velocity * -1
self.steps = 0
else:
if self.x_pos - self.velocity > self.path[0]:
self.x_pos += self.velocity
else:
self.velocity = self.velocity * -1
self.steps = 0
def hit(self):
if self.health > 1:
self.health -= 0.50
hit = pygame.mixer.Sound('hit.wav')
hit.play()
else:
self.isAlive = False
dead = pygame.mixer.Sound('death_sound.wav')
dead.play()
# Main starting loop.
letterStyle = pygame.font.SysFont('Bookman Old Style', 50)
italicStyle = pygame.font.SysFont('Bookman Old Style', 30, False, True)
cirno = Player(300, 470, 160, 233)
score = 0
evilCirno = EnemyCirno(50, 470, 160, 233, 800)
maxShots = 0
bullets = []
running = True
while running is True:
clock.tick(24)
pygame.time.delay(10)
music = pygame.mixer.music.load('main_theme.wav') # And here is where the bug begins!
pygame.mixer.music.play()
for events in pygame.event.get():
if events.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
def update_screen():
dow.blit(scene, (0, 0))
textdisplay = letterStyle.render('Score: ' + str(score), 1, (0, 255, 255))
won = italicStyle.render("Enemy defeated!", 1, (10, 255, 19))
dow.blit(textdisplay, (50, 30))
if not evilCirno.isAlive:
dow.blit(won, (100, 150))
cirno.move()
evilCirno.summon()
for shot in bullets:
shot.summon()
pygame.display.update()
if maxShots > 0:
maxShots += 1
if maxShots > 5:
maxShots = 0
for shot in bullets:
if evilCirno.isAlive:
if shot.y_pos - shot.radius < evilCirno.hitbox[1] + evilCirno.hitbox[3] and shot.y_pos + shot.radius > \
evilCirno.hitbox[1]:
if shot.x_pos + shot.radius > evilCirno.hitbox[0] and shot.x_pos - shot.radius < evilCirno.hitbox[0] + \
evilCirno.hitbox[2]:
evilCirno.hit()
score += 50
bullets.pop(bullets.index(shot))
if 1000 > shot.x_pos > 0:
shot.x_pos += shot.velocity
else:
bullets.pop(bullets.index(shot))
if key[pygame.K_z] and maxShots == 0:
shoot = pygame.mixer.Sound('bullet.wav')
shoot.play()
if cirno.atleft:
facing = -1
else:
facing = 1
if len(bullets) < 5:
bullets.append(
IceBullet(round(cirno.x_pos + cirno.w // 2), round(cirno.y_pos + cirno.h // 1.2), 20, (0, 0, 255),
facing))
maxShots = 1
if key[pygame.K_LEFT] and cirno.x_pos > cirno.velocity: # Will stop ASAP when reached
cirno.x_pos -= cirno.velocity
cirno.atleft = True
cirno.atright = False
cirno.still = False
elif key[
pygame.K_RIGHT] and cirno.x_pos < 1000 - cirno.velocity - cirno.w: # If it goes past this, it will stop ASAP, as well
cirno.x_pos += cirno.velocity
cirno.atright = True
cirno.atleft = False
cirno.still = False
else:
cirno.steps = 0
cirno.still = True
if not cirno.JUMPbool:
if key[pygame.K_UP]:
cirno.JUMPbool = True
cirno.steps = 0
else:
if cirno.jumpheight >= -12: # What to do if pygame.K_SPACE is pressed down.
cirno.y_pos -= (cirno.jumpheight * abs(cirno.jumpheight)) * 0.5
cirno.jumpheight -= 1
else:
cirno.jumpheight = 12
cirno.JUMPbool = False
update_screen()
pygame.quit()
So far, the music actually does play, as well as the sounds. Though the problem is that it just loops the beginning part of the music over and over (which is only the first few seconds), so what you get is just something that sounds like a broken MP3 player.
(for reference the music is 1:45. Even weirder is that I've seen people use it with no issues.)
Is there any way to fix this bug? Thanks for your help :)
Do you see the bug here?
while running is True:
[...]
music = pygame.mixer.music.load('main_theme.wav')
pygame.mixer.music.play()
It's re-loading and re-playing replaying the music inside your code main loop. That is every single updated frame of game-play,
Load and play music outside your main loop:
music = pygame.mixer.music.load('main_theme.wav')
pygame.mixer.music.play()
while running is True:
[...]
Your code can then call the mixer.get_busy() function too see if the music has stopped, and do something about it.
You probably also want to investigate PyGame Sound mixer channels, so your sound effects mix in with the background music properly.

Blitting certain images to the screen is painfully slow in pygame [duplicate]

This question already has answers here:
Why my pygame game with a tiled map is lagging?
(1 answer)
How could I optimise this simple python pygame code
(1 answer)
Closed 2 years ago.
I am trying to make a game, but when I try to blit a few flowers onto the screen it slows down from 60 FPS to 12 FPS.
At first, I tried to .convert() all my images, but then they turned pink. So I used .convert_alpha() instead. using .convert_alpha() made the images not pink, but it only made the FPS go up a teeny bit.
the relevant parts of my code are
### Creates a random assortment of Flora ###
def createFlora(screenSize, cellSize):
flower1 = pygame.transform.scale(pygame.image.load("Flower1.PNG"), (64, 64))
flower1 = flower1.convert_alpha()
flower2 = pygame.transform.scale(pygame.image.load("Flower2.PNG"), (64, 64))
flower2 = flower2.convert_alpha()
flowers = [flower1, flower2]
flower1ds = pygame.transform.scale(pygame.image.load("Flower1DropShadow.PNG"), (64, 64))
flower1ds = flower1ds.convert_alpha()
flower2ds = pygame.transform.scale(pygame.image.load("Flower2DropShadow.PNG"), (64, 64))
flower2ds = flower2ds.convert_alpha()
flowersds = [flower1ds, flower2ds]
flora = []
for i in range(screenSize[0] // cellSize + 1):
floraRow = []
for j in range(screenSize[1] // cellSize + 1):
if randint(0, len(flowers) * 4) < len(flowers):
choice = randint(0, len(flowers) - 1)
floraRow.append((flowers[choice],
(i * cellSize, j * cellSize),
randint(0, 3) * 90, choice))
else: floraRow.append(False)
flora.append(floraRow)
floraFinal = []
for i in range(len(flora)):
for j in range(len(flora[0])):
if flora[i][j] != False:
if flora[i][j][3] == 0:
if flora[i][j][2] == 0: #depending on the rotation of parent plant, the shadow will be changed.
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), flora[i][j][1]))
elif flora[i][j][2] == 90:
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0], flora[i][j][1][1] + 8)))
elif flora[i][j][2] == 180:
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0] + 8, flora[i][j][1][1] + 8)))
elif flora[i][j][2] == 270:
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0] + 8, flora[i][j][1][1])))
elif flora[i][j][3] == 1:
if flora[i][j][2] == 0:
floraFinal.append((flowersds[flora[i][j][3]], flora[i][j][1]))
elif flora[i][j][2] == 90:
floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0], flora[i][j][1][1] + 4)))
elif flora[i][j][2] == 180:
floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0] + 4, flora[i][j][1][1] + 4)))
elif flora[i][j][2] == 270:
floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0] + 4, flora[i][j][1][1])))
floraFinal.append((pygame.transform.rotate(flora[i][j][0], flora[i][j][2]), flora[i][j][1]))
return floraFinal
def renderFlora(flora, screen):
for i in range(len(flora)):
screen.blit(flora[i][0], flora[i][1])
def main():
os.environ['SDL_VIDEO_CENTERED'] = '1' #center the screen
pygame.init()
screenSize = (1856, 960) #24 x 14 cells
onTop(pygame.display.get_wm_info()['window']) #move pygame window to the front
screen = pygame.display.set_mode(screenSize)
screen.fill((25, 25, 25))
""" VARS """
cellSize = 64
pygame.font.init()
myfont = pygame.font.SysFont('Comic Sans MS', 30)
path = createPath()
flora = createFlora(screenSize, cellSize)
tileMap = createTileMap(screenSize, cellSize)
tileGridOn = False
currentButton = 0
buttons = []
gridButtonImg = pygame.transform.scale(pygame.image.load("GridButton.PNG").convert_alpha(), (48, 48))
#Grid Button Toggles a grid so you can see where Tiles are easier
buttons.append(Button((20, screenSize[1] - 64), False, gridButtonImg, screen, 48))
pathSds = pygame.transform.scale(pygame.image.load("StraightPathDropShadow.PNG").convert_alpha(), (64, 64))
pathCds = pygame.transform.scale(pygame.image.load("CornerPathDropShadow.PNG").convert_alpha(), (64, 64))
#==# MAIN LOOP #==#
clock = pygame.time.Clock()
while True:
screen.fill((25, 25, 25))
for evt in pygame.event.get():
if evt.type == pygame.QUIT:
pygame.quit()
quit()
#Draw Background Tiles
renderBackground(tileMap, screen)
#Draw Midground Items/Tiles
renderFlora(flora, screen)
#Draw Foreground Items/Tiles
renderPath(path, screen, pathSds, pathCds)
textsurface = myfont.render(str(round(clock.get_fps() * 10) / 10), False, (0, 0, 0))
screen.blit(textsurface,(15, 15))
### Buttons ###
for i in range(len(buttons)):
buttons[i].update(screen)
if buttons[i].getCTF():
currentButton = i
#Toggle Grid
tileGridOn = buttons[0].getValue()
if tileGridOn: drawGrid(screenSize, cellSize, screen)
pygame.display.flip()
clock.tick(60)
main()
The flora is created before the main loop, so I'm not creating images every cycle, I'm just passing a list through the render function, which only blits the images onto the screen.
If I comment out the renderFlora() method it goes to 60 FPS, but if I leave it in it drops significantly, I don't know why, because I already blit a lot more images for the tiled background. method.
Improve performance by pre-treating the flora. Render on a surface before the application loop and blit the surface in the application loop:
def main():
# [...]
flora_surf = pygame.Surface(screen.get_size())
renderFlora(flora, flora_surf)
while True:
# [...]
#Draw Midground Items/Tiles
# renderFlora(flora, screen) <-- DELETE
screen.blit(flora_surf, (0, 0))
# [...]

pygame keeps bogging down

I read the other questions about pygame bogging down and all I could find was limit the FPS, I tried that but it's still bogging down, I've tried everything but in the end I think it's just because my code is inefficient or something, any help would be appreciated.
Here's a video of the performance since i'm sure none of you want to actually download this,
https://www.youtube.com/watch?v=vmZaxb0zQR0
when it first starts it's way slower than it should be, at 0:12 in the video is when it's running at the speed it should be, and at 0:50 it bogs down again.
I tried looking everywhere to see what it could be and i found nothing, frankly just posting this source is embarassing
main.py
import sys, pygame
import random
import time
from resources import _time_
from pygame.locals import *
debug = True
start = time.time()
pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.init()
size = width, height = 800, 600
speed = [1, 1]
ai_speed = [1, 1]
black = (0, 0, 0)
text_color = (255, 255, 255)
dad_count = 0
#values change to True if appropriate key is pressed
keys = [False, False, False, False]
#set title and screen width and height
pygame.display.set_caption("Dad Explorer v0.02")
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
screen_rect = screen.get_rect()
#set boundary variables
b_height = height - 26
b_width = width - 25
newdad = False
#load our beautiful sounds
loop = pygame.mixer.music.load("sound/loop.wav")
intro = pygame.mixer.Sound("sound/intro.wav")
alarm1 = pygame.mixer.Sound("sound/klaxon_alert1.wav")
beeps = pygame.mixer.Sound("sound/beeps.wav")
beeps.set_volume(0.1)
defeated = pygame.mixer.Sound("sound/defeatednormal.wav")
defeated.set_volume(0.5)
yell = pygame.mixer.Sound("sound/yell.wav")
yell.set_volume(0.7)
#spawn objects at random coordinates
playerspawn = (random.randrange(b_width), random.randrange(b_height))
enemyspawn = (random.randrange(b_width), random.randrange(b_height))
#player
player = pygame.image.load("images/smug.gif")
player_rect = player.get_rect()
player_rect[:2] = playerspawn
#enemy
enemy = pygame.image.load("images/dad.png")
enemy_rect = enemy.get_rect()
enemy_rect[:2] = enemyspawn
#loop music
pygame.mixer.music.set_volume(0.2)
pygame.mixer.music.play(-1)
#pre set collision to false
collision = False
#fpsCounter = text_font.render("FPS: {}".format(pygame.time.Clock()))
while 1:
respawn = (random.randrange(b_width), random.randrange(b_height))
#display text on the screen
text_font = pygame.font.SysFont("monospace", 14)
player_label = text_font.render("-- Player --", 1, text_color)
player_velocity = text_font.render("Velocity: {}".format(speed), 1, text_color)
player_position = text_font.render("Position: {}".format((player_rect.x, player_rect.y)), 1, text_color)
text_debug = text_font.render("Debug: {}".format(debug), 1, text_color)
time_label = text_font.render("Time wasted: {}".format(_time_()), 1, text_color)
dad_kills = text_font.render("{} Dads defeated".format(dad_count), 1, text_color)
enemy_label = text_font.render("-- Enemy --", 1, text_color)
enemy_velocity = text_font.render("Velocity: {}".format(ai_speed), 1, text_color)
enemy_currentpos = text_font.render("Position: {}".format(enemy_rect[:2]), 1, text_color)
#move the enemy
enemy_rect = enemy_rect.move(ai_speed)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key==K_UP:
keys[0]=True
elif event.key==K_LEFT:
keys[1]=True
elif event.key==K_DOWN:
keys[2]=True
elif event.key==K_RIGHT:
keys[3]=True
if event.key == K_r:
#press r to reset player position
if debug == True:
player_rect[:2] = [100, 100]
speed = [1, 1]
else:
pass
if event.type == pygame.KEYUP:
if event.key==pygame.K_UP:
keys[0]=False
elif event.key==pygame.K_LEFT:
keys[1]=False
elif event.key==pygame.K_DOWN:
keys[2]=False
elif event.key==pygame.K_RIGHT:
keys[3]=False
#set enemy boundaries
if enemy_rect.left < 0 or enemy_rect.right > width:
ai_speed[0] = -ai_speed[0]
if enemy_rect.top < 0 or enemy_rect.bottom > height:
ai_speed[1] = -ai_speed[1]
#set player boundaries
if not screen_rect.contains(player_rect):
if player_rect.right > screen_rect.right:
player_rect.right = screen_rect.right
if player_rect.bottom > screen_rect.bottom:
player_rect.bottom = screen_rect.bottom
if player_rect.left < screen_rect.left:
player_rect.left = screen_rect.left
if player_rect.top < screen_rect.top:
player_rect.top = screen_rect.top
#check for collision
new_collision = enemy_rect.colliderect(player_rect)
if not collision and new_collision:
print "alarm"
dad_count += 1
defeated.play()
newdad = True
if dad_count == 1:
enemy = pygame.image.load("images/maddad.png")
yell.play()
elif collision and not new_collision:
print "done colliding"
beeps.play()
collision = new_collision
screen.fill(black) #display background
screen.blit(player, player_rect) #display player object and player movement
if newdad is True:
enemy_rect[:2] = respawn
ai_speed = [random.randrange(-5, 5), random.randrange(-5, 5)]
screen.blit(enemy, enemy_rect)
newdad = False
else:
screen.blit(enemy, enemy_rect)
#player data
screen.blit(player_label, (5, 10))
screen.blit(player_velocity, (5, 30))
screen.blit(player_position, (5, 50))
screen.blit(text_debug, (5, 70))
screen.blit(time_label, (5, b_height))
screen.blit(dad_kills, (5, b_height - 30))
#AI data
screen.blit(enemy_label, (5, 120))
screen.blit(enemy_velocity, (5, 140))
screen.blit(enemy_currentpos, (5, 160))
if keys[0]:
speed[1] = -2
elif keys[2]:
speed[1] = 2
else:
speed[1] = 0
if keys[1]:
speed[0] = -2
elif keys[3]:
speed[0] = 2
else:
speed[0] = 0
player_rect.move_ip(speed[0], speed[1])
pygame.display.flip()
clock.tick(150)
resources.py (keeps track of time played)
import random
import time, datetime
from random import choice
start_datetime = datetime.datetime.now()
def _time_():
delta = datetime.datetime.now() - start_datetime
days = delta.days
hours = delta.seconds / 3600
minutes = (delta.seconds / 60) % 60
seconds = delta.seconds % 60
runningtime = []
if days > 0:
runningtime.append("{} day{}".format(days, "" if days == 1 else "s"))
if hours > 0:
runningtime.append("{} hour{}".format(hours, "" if hours == 1 else "s"))
if minutes > 0:
runningtime.append("{} minute{}".format(minutes, "" if minutes == 1 else "s"))
if seconds > 0:
runningtime.append("{} second{}".format(seconds, "" if seconds == 1 else "s"))
if len(runningtime) < 2:
time = " and ".join(runningtime)
else:
time = ", ".join(runningtime[:-1]) + ", and " + runningtime[-1]
return time
I think your problem is the font rendering. Font rendering is a very expensive operation, and you should always cache and re-use those rendered surfaces.
Also, you're loading the font every iteration of the main loop. Just load it once.
The game is quite simple, nonetheless I recommend a framerate of 60 (this is a good value based on my experience, YMMV).
An example of a cache could look like:
...
text_font = pygame.font.SysFont("monospace", 14)
cache={}
def get_msg(msg):
if not msg in cache:
cache[msg] = text_font.render(msg, 1 , text_color)
return cache[msg]
while 1:
respawn = (random.randrange(b_width), random.randrange(b_height))
player_label = get_msg("-- Player --")
player_velocity = get_msg("Velocity: {}".format(speed))
player_position = get_msg("Position: {}".format((player_rect.x, player_rect.y)))
text_debug = get_msg("Debug: {}".format(debug))
time_label = get_msg("Time wasted: {}".format(_time_()))
dad_kills = get_msg("{} Dads defeated".format(dad_count))
...
That should boost your framerate and prevent the slowdown.
As a side note, instead of:
#set player boundaries
if not screen_rect.contains(player_rect):
if player_rect.right > screen_rect.right:
player_rect.right = screen_rect.right
if player_rect.bottom > screen_rect.bottom:
player_rect.bottom = screen_rect.bottom
if player_rect.left < screen_rect.left:
player_rect.left = screen_rect.left
if player_rect.top < screen_rect.top:
player_rect.top = screen_rect.top
simply use:
#set player boundaries
player_rect.clamp_ip(screen_rect)
There are some other small issues with your code, but that's out of this question/answer.

Categories

Resources