PyGame正在以非常慢的速度运行生命的游戏
问题描述
与此相关的两个其他问题已通过将绘制事件移出不应该在其中的循环来解决。不过,我没有这个问题。如有任何帮助,我们将不胜感激!
Python:3.8
PyGame:1.9.6
如果您需要测试播放:
运行游戏。在屏幕上绘制以放置活动单元格。单击"R"开始。您也可以在开始停止并重新绘制后单击"S",但您需要在单击几代之后才能真正停止(因为我假设是由于相同的延迟)。
import pygame
import numpy
class Game():
def __init__(self):
self.Run()
def GetAdj(self, x, y):
nb = 0
for c in range (-1, 2):
for r in range (-1, 2):
if r == 0 and c == 0:
pass
else:
nposx = x + r
nposy = y + c
if nposx < len(self.pixels):
if nposy < len(self.pixels[nposx]):
if self.pixels[nposx][nposy] == 1:
nb += 1
return nb
def NextGeneration(self):
newGeneration = numpy.zeros(self.ScreenWidth//2, self.ScreenHeight//2, dtype=int)
for x, c in enumerate(self.pixels):
for y, cell in enumerate(c):
nbrs = self.GetAdj(x, y)
if cell == 1:
if nbrs in [2, 3]:
newGeneration[x][y] = 1
else:
if nbrs == 3:
newGeneration[x][y] = 1
self.pixels = newGeneration
def DrawBG(self):
black = (0,0,0)
white = (255,255,255)
self.bg.fill(black)
for c in range(self.ScreenWidth // self.cellsize):
for r in range(self.ScreenHeight // self.cellsize):
if self.pixels[c][r] == 1:
pygame.draw.rect(self.bg, white, (c*self.cellsize, r*self.cellsize, self.cellsize, self.cellsize))
def Run(self):
pygame.init()
self.ScreenHeight = 720
self.ScreenWidth = 1280
self.ScreenSize = (self.ScreenWidth, self.ScreenHeight)
screen = pygame.display.set_mode(self.ScreenSize)
self.bg = pygame.Surface(self.ScreenSize)
clock = pygame.time.Clock()
mousedown = False
self.pixels = numpy.zeros(self.ScreenWidth//2, self.ScreenHeight//2, dtype=int)
self.cellsize = 10
stage = 'Draw'
running = True
while running:
clock.tick(60)
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
running = False
if stage == 'Draw':
for event in events:
if event.type == pygame.MOUSEBUTTONUP and mousedown:
mousedown = False
elif event.type == pygame.MOUSEBUTTONDOWN:
mousedown = True
elif event.type == pygame.MOUSEMOTION and mousedown and stage == 'Draw':
mposx, mposy = pygame.mouse.get_pos()
self.pixels[mposx//self.cellsize][mposy//self.cellsize] = 1
elif event.type == pygame.KEYDOWN and event.key == pygame.K_r:
stage = 'Run'
self.NextGeneration()
elif stage == 'Run':
for event in events:
if event.type == pygame.KEYDOWN and event.key == pygame.K_s:
stage = 'Draw'
self.NextGeneration()
self.DrawBG()
screen.blit(self.bg, (0,0))
pygame.display.flip()
if __name__ == "__main__":
Game()
解决方案
Numpy数组太大。您可以为每个像素(而不是每个单元格)创建一个数组。所以不要计算每个单元格,而要计算每个像素。
更改NextGeneration
和Run
方法中的数组大小:
newGeneration = numpy.zeros(self.ScreenWidth//2, self.ScreenHeight//2, dtype=int)
newGeneration = numpy.zeros((self.ScreenWidth//self.cellsize, self.ScreenHeight//self.cellsize), dtype=int)
self.pixels = numpy.zeros(self.ScreenWidth//2, self.ScreenHeight//2, dtype=int)
self.cellsize = 10
self.pixels = numpy.zeros((self.ScreenWidth//self.cellsize, self.ScreenHeight//self.cellsize), dtype=int)
GetAdj
方法可以通过numpy.sum
:
class Game():
# [...]
def GetAdj(self, x, y):
x0, y0 = max(0, x-1), max(0, y-1)
nb = numpy.sum(self.pixels[x0 : x+2, y0 : y+2]) - self.pixels[x, y]
return nb
使用scipy.ndimage.convolve
和查找表(参见Indexing Multi-dimensional arrays)可以进一步提高性能:
import numpy
from scipy.ndimage import convolve
class Game():
def __init__(self):
self.kernel = numpy.array([[1,1,1], [1,0,1], [1,1,1]])
self.lookup = numpy.array([0,0,0,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,0])
self.Run()
def NextGeneration(self):
adjacent = convolve(self.pixels, self.kernel, mode='constant')
newGeneration = self.lookup[self.pixels * 9 + adjacent]
self.pixels = newGeneration
相关文章