pygame不断陷入困境

时间:2014-03-11 14:30:42

标签: python performance python-2.7 pygame

我读到了关于pygame陷入困境的其他问题,我所能找到的只是限制FPS,我试过但是它仍然在停滞不前,我已经尝试了一切,但最后我认为这只是因为我的代码效率低或者什么,任何帮助将不胜感激。

这是一个性能视频,因为我确定你们都不想真正下载这个,

https://www.youtube.com/watch?v=vmZaxb0zQR0

当它第一次启动它的速度比它应该的慢时,视频中的0:12是它应该以它应该的速度运行,并且在0:50它再次陷入停滞。

我试着到处寻找它可能是什么,我一无所获,坦率地说,发布这个来源是尴尬的

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 (跟踪播放的时间)

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

1 个答案:

答案 0 :(得分:3)

我认为你的问题是字体渲染。字体渲染是一项非常昂贵的操作,您应该始终缓存并重新使用这些渲染表面。

此外,您在主循环的每次迭代中都会加载字体。只需加载一次。

游戏非常简单,但我建议帧率为60(根据我的经验,这是一个很好的价值,YMMV)。

缓存的示例可能如下所示:

...
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))
...

这应该提高你的帧率并防止减速。


作为旁注,而不是:

#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

只需使用:

#set player boundaries
player_rect.clamp_ip(screen_rect)

您的代码还存在其他一些小问题,但这个问题/答案已经出了问题。