PyGame正在以非常慢的速度运行生命的游戏

Pygame is running game of life very slowly(PyGame正在以非常慢的速度运行生命的游戏)

本文介绍了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

这篇关于PyGame正在以非常慢的速度运行生命的游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:PyGame正在以非常慢的速度运行生命的游戏