因此,和我的朋友们一起在Pygame制作游戏,我就开始为主角编写动画。
我认为可能有几种方法可以做到这一点。制作图像列表并在列表上循环,或者在精灵表上制作包含图片坐标的字典。
我选择了第二个选项,现在我决定要检查哪一个更快。因此,我以非常简单的方式对它们进行编程,以便快速检查它们的表现。
结果彼此非常接近(字典为0.41,没有字典时为0.40)。然后我决定我想尝试一下如果我选择第一个选项会发生什么,除了我会在一个单独的文件中调用pygame.image.load
并将动画帧存储为全局变量而不是导入到主文件中。
我虽然它会非常慢,因为我在某处读到python导入非常慢......但令人惊讶的是我得到了0.021秒的结果!
这是对性能的巨大改变,这可能对我的游戏至关重要,所以我想知道是否有人碰巧知道为什么这个方法这么快,并且只是因为某些x或y为什么它是在这种情况下更快,在另一种情况下会非常慢。
以下代码类似于我游戏的当前状态:
import pygame
import time
start_time = time.time()
playerSpriteSize = 192
img = (0, 0)
class SpriteSheet():
def __init__(self, filename):
self.sheet = pygame.image.load(filename).convert()
def get_image(self, coords, size, flip=False):
surf = pygame.Surface(size).convert()
surf.blit(self.sheet, (0, 0), (coords[0], coords[1], size[0], size[1]))
pygame.transform.flip(surf, False, True)
surf.set_colorkey((0, 0, 0))
surf = pygame.transform.flip(surf, flip, False)
return surf
pygame.init()
displaySurface = pygame.display.set_mode((400, 400))
x = SpriteSheet("playerAnimation.png")
animationList = {0: (0, playerSpriteSize*0), 1: (0, playerSpriteSize*1), 2: (0, playerSpriteSize*2),
3: (0, playerSpriteSize*3), 4: (0, playerSpriteSize*4), 5: (0, playerSpriteSize*5),
6: (0, playerSpriteSize*6)}
rounda = 0
for i in animationList:
a1 = x.get_image(animationList[rounda], (playerSpriteSize, playerSpriteSize))
displaySurface.blit(a1, (30, 30))
rounda += 1
pygame.display.update()
print("--- %s seconds ---" %(time.time() - start_time))
现在这是使用在主游戏循环之前加载的图像的代码:
import pygame
import time
start_time = time.time()
imageSize = 192
img = (0, 0)
class SpriteSheet():
def __init__(self, filename):
self.sheet = pygame.image.load(filename).convert()
def get_image(self, coords, size, flip=False):
surf = pygame.Surface(size).convert()
surf.blit(self.sheet, (0, 0), (coords[0], coords[1], size[0], size[1]))
pygame.transform.flip(surf, False, True)
surf.set_colorkey((0, 0, 0))
surf = pygame.transform.flip(surf, flip, False)
return surf
pygame.init()
displaySurface = pygame.display.set_mode((400, 400))
x = SpriteSheet("playerAnimation.png")
a1 = x.get_image((0, 0), (imageSize, imageSize))
a2 = x.get_image((0, 192), (imageSize, imageSize))
a3 = x.get_image((0, 384), (imageSize, imageSize))
a4 = x.get_image((0, 576), (imageSize, imageSize))
a5 = x.get_image((0, 768), (imageSize, imageSize))
a6 = x.get_image((0, 960), (imageSize, imageSize))
a7 = x.get_image((0, 1152), (imageSize, imageSize))
animationList = [a1, a2, a3, a4, a5, a6, a7]
for i in animationList:
displaySurface.blit(i, (30, 30))
pygame.display.update()
print("--- %s seconds ---" %(time.time() - start_time))
这是在大约0.021秒内运行的代码(拆分为2个文件): 文件1(主文件)
import pygame
import time
from mainDifferentExtern import a1, a2, a3, a4, a5, a6, a7
start_time = time.time()
imageSize = 192
img = (0, 0)
class SpriteSheet():
def __init__(self, filename):
self.sheet = pygame.image.load(filename).convert()
def get_image(self, coords, size, flip=False):
surf = pygame.Surface(size).convert()
surf.blit(self.sheet, (0, 0), (coords[0], coords[1], size[0], size[1]))
pygame.transform.flip(surf, False, True)
surf.set_colorkey((0, 0, 0))
surf = pygame.transform.flip(surf, flip, False)
return surf
pygame.init()
displaySurface = pygame.display.set_mode((400, 400))
x = SpriteSheet("playerAnimation.png")
animationList = [a1, a2, a3, a4, a5, a6, a7]
for i in animationList:
displaySurface.blit(i, (30, 30))
pygame.display.update()
print("--- %s seconds ---" %(time.time() - start_time))
以及从中导入的文件:
import pygame
imageSize = 192
class SpriteSheet():
def __init__(self, filename):
self.sheet = pygame.image.load(filename).convert()
def get_image(self, coords, size, flip=False):
surf = pygame.Surface(size).convert()
surf.blit(self.sheet, (0, 0), (coords[0], coords[1], size[0], size[1]))
pygame.transform.flip(surf, False, True)
surf.set_colorkey((0, 0, 0))
surf = pygame.transform.flip(surf, flip, False)
return surf
pygame.init()
pygame.display.set_mode((1, 1))
x = SpriteSheet("playerAnimation.png")
a1 = x.get_image((0, 0), (imageSize, imageSize))
a2 = x.get_image((0, 192), (imageSize, imageSize))
a3 = x.get_image((0, 384), (imageSize, imageSize))
a4 = x.get_image((0, 576), (imageSize, imageSize))
a5 = x.get_image((0, 768), (imageSize, imageSize))
a6 = x.get_image((0, 960), (imageSize, imageSize))
a7 = x.get_image((0, 1152), (imageSize, imageSize))
编辑:正如匹配所示,我已经改变了测量时间的方法,而是使用python profiling(使用cProfile),但我获得了大致相同的结果,除了前两种方法的出现次数再长一点
答案 0 :(得分:0)
使用单独的文件,首次导入文件时会发生所有getImage
次调用。你没有计算导入的时间,所以你忽略了文件所做的一切的成本。
答案 1 :(得分:0)
我认为这里的区别是由于python为任何导入的模块编译字节码。这反过来将加快导入的加载/执行。您可以在原始代码旁边的目录中将这些文件视为.pyc
文件。
我怀疑如果您执行以下操作,您的结果将再次平衡:
rm *.pyc
PYTHONDONTWRITEBYTECODE=1 python mygame.py
还要记住,0.02秒的几率完全在任何系统的正常“漂移”范围内 - 这就是像timeit
这样的工具运行相同代码数千次并平均结果的原因。
在这个注意事项上 - 考虑代码中可能出现的运行缓慢操作次数 - 如果您只加载一次图像,并且通过不同的方式获得的性能提升为0.02秒 - 而游戏预计会运行几分钟或者几个小时,然后这看起来像是一个过早的优化。