python - Pygame 运行游戏的速度非常慢

标签 python numpy 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 数组太大了。您为每个像素而不是每个单元创建一个数组。所以不要为每个单元格计算它,而是为每个像素计算它。

NextGenerationRun 方法中改变数组的大小:

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

关于python - Pygame 运行游戏的速度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69056318/

相关文章:

python - 得到 IndexError 时使数组重复

python - 如何在 python 中将 xml 文件转换为 csv 输出?

python - 是否有一种python方式从列表或numpy数组中采样N个连续元素

python - 属性错误: 'class' object has no attribute 'rect'

python - scikit学习中的线性回归

python - 如何匹配引号之间字符串中的精确字符串

python - 如何将 numpy 中的表插入 Mysql

基于查找表的 Numpy 整数到字符串

python - 如何在 python 3.7 中修复 'No module named vidcap'

python - 如何有效地 blit 72 图像