Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在我的PyGame模拟中,性能非常差_Python_Pygame_Pygame Surface - Fatal编程技术网

Python 在我的PyGame模拟中,性能非常差

Python 在我的PyGame模拟中,性能非常差,python,pygame,pygame-surface,Python,Pygame,Pygame Surface,我在学校的一个项目中学习了基于PyGame tile的教程,但我从未打算制作一个游戏,而是一个生态系统的模拟。不幸的是,当我运行我的程序时,性能非常差,它只运行了几秒钟,然后windows停止应答 目前我唯一想做的就是在一片草的能量达到80的时候,放置一片新的草 怎么办?所有东西都在更新方法中是不是很糟糕?我可以使用事件或其他方法使检查间隔更长吗?我知道每一帧都有很多数学题,但我不知道如何用另一种方法来做 这是我的密码: main.py: #!/usr/bin/python3 #Importi

我在学校的一个项目中学习了基于PyGame tile的教程,但我从未打算制作一个游戏,而是一个生态系统的模拟。不幸的是,当我运行我的程序时,性能非常差,它只运行了几秒钟,然后windows停止应答

目前我唯一想做的就是在一片草的能量达到80的时候,放置一片新的草

怎么办?所有东西都在更新方法中是不是很糟糕?我可以使用事件或其他方法使检查间隔更长吗?我知道每一帧都有很多数学题,但我不知道如何用另一种方法来做

这是我的密码:

main.py:

#!/usr/bin/python3

#Importing necessary libraries
import pygame as pg, sys, random
from settings import *
from sprites import *

class Sim:
    #Initialize the game window, etc.
    def __init__(self):
        pg.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()

        self.running = True

    def new_grass(self, pos):
        for g in self.grass:
            if pos != g.pos:
                Grass(self, pos)

    #Start a new generation
    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.grass = pg.sprite.Group()
        Grass(self, (10, 15))
        self.run()

    #Main loop
    def run(self):
        self.simulating = True
        while self.simulating:
            self.clock.tick(FPS)
            self.events()
            self.update()
            self.draw()

    #Update things on screen
    def update(self):
        self.all_sprites.update()

    #Draw a grid on screen
    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, BLACK, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, BLACK, (0, y), (WIDTH, y))

    #Draw things on screen
    def draw(self):
        pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
        self.screen.fill(DARK_GREEN)
        self.draw_grid()
        self.all_sprites.draw(self.screen)
        #After drawing everything, flip the display
        pg.display.flip()

    #Events that might happen
    def events(self):
        for event in pg.event.get():
            #Check for the user closing the window
            if event.type == pg.QUIT:
                if self.simulating:
                    self.simulating = False
                self.running = False

s = Sim()
while s.running:
    s.new()
pg.quit()
sprites.py:

#!/usr/bin/python3

import pygame as pg, random
from settings import *
vec = pg.math.Vector2

class Grass(pg.sprite.Sprite):
    def __init__(self, sim, cord):
        self.groups = sim.all_sprites, sim.grass
        pg.sprite.Sprite.__init__(self, self.groups)
        self.sim = sim
        self.image = pg.Surface((TILESIZE/2, TILESIZE/2))
        self.image.fill(GREEN)
        self.cord = cord
        self.rect = self.image.get_rect()
        self.pos = vec(cord) * TILESIZE / 2
        self.rect.topleft = self.pos
        self.spread = vec(random.randint(-1, 1), random.randint(-1, 1))
        self.energy = 20

    def update(self):
        if self.energy <= 80:
            self.energy += 10

        if self.energy >= 80:
            self.sim.new_grass((self.cord + self.spread))

主要问题是方法
Sim.new\u grass

class-Sim:
# [...]
def新草(自身,位置):
对于self.grass中的g:
如果位置!=g、 pos:
草地(自我,位置)
该方法生成的
Grass
对象比预期多得多。It事件在同一位置生成多个草地对象。对于每个对象(
g
),其中
pos!=g、 pos
构建了
Grass
的新实例

如果所需位置中没有
Grass
对象,则需要创建
Grass
的新实例:

class-Sim:
# [...]
def新草(自身,位置):
如果没有(pos==g.pos表示self.grass中的g):
草地(自我,位置)
问题在于:

def new_grass(self, pos):
    for g in self.grass:
        if pos != g.pos:
            Grass(self, pos)
这是因为每次在另一个位置上已经存在草时,您都会添加一个
Grass
对象。我想如果这个职位根本不存在的话,你是想增加一个

您的程序中有一些bug,主要是上面提到的bug,但是参数
pos
实际上应该是
coord
。我强调了您的代码,并提出了一些改进意见:

#!/usr/bin/python3

import pygame as pg, random

TITLE = "EcoSim"
WIDTH = 480
HEIGHT = 600
FPS = 30
TILESIZE = 32
GRID_WIDTH = WIDTH / TILESIZE
GRID_HEIGHT = HEIGHT / TILESIZE

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
DARK_GREEN = (0, 100, 0)
BROWN = (150,75,0)

vec = pg.math.Vector2

class Grass(pg.sprite.Sprite):
    # This creates the image just once!
    IMAGE = pg.Surface((TILESIZE/2, TILESIZE/2))
    IMAGE.fill(GREEN)

    def __init__(self, cord):  # Remove 'sim'.
        # self.groups = sim.all_sprites, sim.grass
        # pg.sprite.Sprite.__init__(self, self.groups)
        # self.sim = sim
        super().__init__()
        self.image = Grass.IMAGE  # All reference the same image.
        self.cord = cord
        self.rect = self.image.get_rect()
        self.pos = vec(cord) * TILESIZE / 2
        self.rect.topleft = self.pos
        self.energy = 20
        self.spread = vec(random.randint(-1, 1), random.randint(-1, 1))

    def update(self):
        if self.energy <= 80:
            self.energy += 10

        # Make Sim check for this.
        # if self.energy >= 80:
        #     self.sim.new_grass((self.cord + self.spread))


class Sim:
    def __init__(self):
        pg.init()
        pg.display.set_caption(TITLE)
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        self.clock = pg.time.Clock()
        self.all_sprites = pg.sprite.Group()  # Create *ALL* attributes in `__init__`
        self.grass = pg.sprite.Group()
        self.running = True
        self.simulating = False

    # You're passing coord here, not pos! And you also want to add
    # the grass only if the coord is not already present in the list.
    def new_grass(self, coord):
        if coord not in (x.cord for x in self.grass):
            grass = Grass(coord)
            self.grass.add(grass)
            self.all_sprites.add(grass)

    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.grass = pg.sprite.Group()
        grass = Grass((10, 15))  # Grass is now pure and doesn't have any side-effects, which makes the code much clearer.
        self.grass.add(grass)
        self.all_sprites.add(grass)
        self.run()

    def run(self):
        self.simulating = True
        while self.simulating:
            self.clock.tick(FPS)
            self.events()
            self.update()
            self.draw()

    def update(self):
        self.all_sprites.update()
        # Let Sim decide the fate of the grass. Don't let Grass add
        # itself.
        for grass in self.grass:
            if grass.energy >= 80:
                self.new_grass((grass.cord + grass.spread))

    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, BLACK, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, BLACK, (0, y), (WIDTH, y))

    def draw(self):
        pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
        self.screen.fill(DARK_GREEN)
        self.draw_grid()
        self.all_sprites.draw(self.screen)
        pg.display.flip()

    def events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.simulating = False  # There was an unnecessary if here.
                self.running = False

s = Sim()
while s.running:
    s.new()
pg.quit()
#/usr/bin/python3
将pygame导入为pg,随机
TITLE=“EcoSim”
宽度=480
高度=600
FPS=30
TILESIZE=32
网格宽度=宽度/瓷砖尺寸
网格高度=高度/平铺尺寸
白色=(255,255,255)
黑色=(0,0,0)
绿色=(0,255,0)
深绿色=(0,100,0)
布朗=(150,75,0)
向量=pg.math.Vector2
类草(第页雪碧、雪碧):
#这只会创建一次图像!
图像=pg.Surface((瓷砖大小/2,瓷砖大小/2))
图像填充(绿色)
定义初始(自身、线缆):#移除“sim”。
#self.groups=sim.all\u精灵,sim.grass
#pg.sprite.sprite.\uuuu init\uuuu(self,self.groups)
#self.sim=sim
super()。\uuuu init\uuuuu()
self.image=Grass.image#所有引用的图像都相同。
self.cord=cord
self.rect=self.image.get_rect()
self.pos=vec(线缆)*瓷砖尺寸/2
self.rect.topleft=self.pos
自我能量=20
self.spread=vec(random.randint(-1,1),random.randint(-1,1))
def更新(自我):
如果self.energy=80:
#self.sim.new_grass((self.cord+self.spread))
类别识别码:
定义初始化(自):
第init页()
pg.display.set_标题(标题)
self.screen=pg.display.set_模式((宽度、高度))
self.clock=pg.time.clock()
self.all_sprites=pg.sprite.Group()#在`u init中创建*all*属性__`
self.grass=pg.sprite.Group()
self.running=True
自我模拟=错误
#你在这里经过coord,不是pos!您还想添加
#只有当坐标尚未出现在列表中时,才可以使用草。
def new_grass(自我、合作):
如果坐标不在(x线表示x在自草中):
草=草(坐标)
self.grass.add(grass)
自我。所有精灵。添加(草)
def新(自我):
self.all_sprite=pg.sprite.Group()
self.grass=pg.sprite.Group()
grass=grass((10,15))#grass现在是纯的,没有任何副作用,这使得代码更加清晰。
self.grass.add(grass)
自我。所有精灵。添加(草)
self.run()
def运行(自):
自模拟=真
自模拟时:
自我时钟滴答声(FPS)
self.events()
self.update()
self.draw()
def更新(自我):
self.all_sprites.update()
#让辛来决定草的命运。别让草增加了
#本身。
对于self.grass中的grass:
如果grass.energy>=80:
自我。新草((草。绳+草。蔓延))
def绘制网格(自):
对于范围内的x(0,宽度,平铺):
pg.绘制线(自屏幕,黑色,(x,0),(x,高度))
对于范围内的y(0,高度,平铺):
pg.绘制线(自屏幕,黑色,(0,y),(宽度,y))
def牵引(自):
pg.display.set_caption(“{.2f}.”格式(self.clock.get_fps())
self.screen.fill(深绿色)
self.draw_grid()
self.all_sprite.draw(self.screen)
pg.display.flip()
def事件(自):
对于pg.event.get()中的事件:
如果event.type==pg.QUIT:
self.simulating=False#这里有一个不必要的if。
self.running=False
s=Sim()
在s.运行时:
s、 新的()
第页退出

可能会有很多问题,但只要快速浏览一下,就好像您正在为每片草创建一个新的
pygame.Surface
。这是不必要的,而且占用大量内存/计算。只创建一个曲面,让所有的草块都引用它。因此,很难理解代码的流程。有几条建议可以让事情变得更简单:1。确保在
\uuuu init\uuuu
中定义了所有属性。2.没有从
Grass
返回到
Sim
的引用。这使得很难确定项目的所有权和流程。让
Sim
类和草进入正确的组,并检查能量是否足够高,以便更换新的草瓷砖
#!/usr/bin/python3

import pygame as pg, random

TITLE = "EcoSim"
WIDTH = 480
HEIGHT = 600
FPS = 30
TILESIZE = 32
GRID_WIDTH = WIDTH / TILESIZE
GRID_HEIGHT = HEIGHT / TILESIZE

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
DARK_GREEN = (0, 100, 0)
BROWN = (150,75,0)

vec = pg.math.Vector2

class Grass(pg.sprite.Sprite):
    # This creates the image just once!
    IMAGE = pg.Surface((TILESIZE/2, TILESIZE/2))
    IMAGE.fill(GREEN)

    def __init__(self, cord):  # Remove 'sim'.
        # self.groups = sim.all_sprites, sim.grass
        # pg.sprite.Sprite.__init__(self, self.groups)
        # self.sim = sim
        super().__init__()
        self.image = Grass.IMAGE  # All reference the same image.
        self.cord = cord
        self.rect = self.image.get_rect()
        self.pos = vec(cord) * TILESIZE / 2
        self.rect.topleft = self.pos
        self.energy = 20
        self.spread = vec(random.randint(-1, 1), random.randint(-1, 1))

    def update(self):
        if self.energy <= 80:
            self.energy += 10

        # Make Sim check for this.
        # if self.energy >= 80:
        #     self.sim.new_grass((self.cord + self.spread))


class Sim:
    def __init__(self):
        pg.init()
        pg.display.set_caption(TITLE)
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        self.clock = pg.time.Clock()
        self.all_sprites = pg.sprite.Group()  # Create *ALL* attributes in `__init__`
        self.grass = pg.sprite.Group()
        self.running = True
        self.simulating = False

    # You're passing coord here, not pos! And you also want to add
    # the grass only if the coord is not already present in the list.
    def new_grass(self, coord):
        if coord not in (x.cord for x in self.grass):
            grass = Grass(coord)
            self.grass.add(grass)
            self.all_sprites.add(grass)

    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.grass = pg.sprite.Group()
        grass = Grass((10, 15))  # Grass is now pure and doesn't have any side-effects, which makes the code much clearer.
        self.grass.add(grass)
        self.all_sprites.add(grass)
        self.run()

    def run(self):
        self.simulating = True
        while self.simulating:
            self.clock.tick(FPS)
            self.events()
            self.update()
            self.draw()

    def update(self):
        self.all_sprites.update()
        # Let Sim decide the fate of the grass. Don't let Grass add
        # itself.
        for grass in self.grass:
            if grass.energy >= 80:
                self.new_grass((grass.cord + grass.spread))

    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, BLACK, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, BLACK, (0, y), (WIDTH, y))

    def draw(self):
        pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
        self.screen.fill(DARK_GREEN)
        self.draw_grid()
        self.all_sprites.draw(self.screen)
        pg.display.flip()

    def events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.simulating = False  # There was an unnecessary if here.
                self.running = False

s = Sim()
while s.running:
    s.new()
pg.quit()