我试图编写这个简单的游戏,它复制了小行星的一些方面并且在FPS方面遇到了一些问题。我还没有完成游戏,但我担心FPS下降,因为我有更多我希望显示的文字,但由于担心游戏会遭受如此多的帧丢失而无法显示。我只注意到这个帧丢弃,文本显示在屏幕上。我的代码可以在下面找到。
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()
答案 0 :(得分:2)
您在文字渲染方面做了两件事。
第一个(也可能是主要的)是每次要显示某些文本时反复加载字体:
def game_display_text(display_msg, display_x, display_y, text_size):
font = pygame.font.SysFont(None, text_size)
...
您应该创建一次字体对象,这样您就不会每次都从磁盘加载它。
第二个问题是文本的呈现到Surface
是一项相当昂贵的操作:
def game_display_text(display_msg, display_x, display_y, text_size):
...
text = font.render(str(display_msg), True, black)
...
更好的方法是缓存已创建的曲面,并重复使用它们。
一个非常简单的缓存可能如下所示:
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]
然后您将使用get_msg
方法创建文本表面。或者使用像lru_cache
decorator。