【发布时间】:2022-11-06 18:08:47
【问题描述】:
我正在创建一个小行星游戏。该游戏旨在长时间使用。
启动时(使用 pycharms 调试工具)我使用了大约 30.1 MB 的系统内存。但是我注意到,在运行时,它每秒增加大约 0.1 MB(固定 fps 为 60)。在测试并将 fps 设置为无限制时,我注意到内存使用量分别随着 fps 的增加而增加。
import pygame
import math
import random
import threading
class Main:
def __init__(self):
self.image = None
self.Dimensions = 1000
self.display = pygame.display.set_mode((self.Dimensions, self.Dimensions))
self.fps = 60
self.MainPage = True
self.Game = False
self.clock = pygame.time.Clock()
pygame.init()
def start(self):
self.running = True
self.character = Player()
self.handler = EventHandler()
self.display = pygame.display.set_mode((self.Dimensions, self.Dimensions))
while self.running:
self.event_list = pygame.event.get()
for self.event in self.event_list:
if self.event.type == pygame.QUIT:
self.running = False
pygame.display.quit()
pygame.quit()
quit()
white = [255, 255, 255]
self.display.fill(white)
self.Dimensions = 1000
self.clock.tick(self.fps)
self.handler.spawn()
self.handler.update()
pygame.display.flip()
class Player:
def __init__(self):
self.Dimensions = Game.Dimensions
self.x = self.Dimensions / 2
self.y = self.Dimensions / 2
self.looking_directions = 0
self.velocity = 0
self.image = "Pictures/Player.png"
class Asteroids():
def __init__(self):
self.size = 100
self.x = random.choice(list(set([x for x in range(0, 9)]) - set(range(int(Game.Dimensions/5), int(Game.Dimensions*(4/5))))))
self.y = random.choice(list(set([x for x in range(0, 9)]) - set(range(int(Game.Dimensions/5), int(Game.Dimensions*(4/5))))))
self.velocity = random.uniform(1, 2)
self.looking_direction = random.randrange(0, 360)
self.picture = "Pictures/Asteroids.png"
size = 75
self.image = pygame.image.load(self.picture)
self.image = pygame.transform.scale(self.image, (size, size))
self.image = pygame.transform.rotate(self.image, self.looking_direction)
def Update(self):
Game.display.blit(self.image, (self.x, self.y))
class EventHandler():
def __init__(self):
self.asteroid_list = []
self.tick = 0
self.asteroid_cap = 15
def spawn(self):
self.tick += 1
if len(self.asteroid_list) >= self.asteroid_cap:
pass
elif self.tick >= 60:
temp_asteroid = Asteroids()
self.asteroid_list.append(temp_asteroid)
print("Asteroid created: " + str(len(self.asteroid_list)) + " currently alive")
self.tick = 0
def update(self):
for current in self.asteroid_list:
x = threading.Thread(target=current.Update)
x.start()
try:
x.join()
except:
pass
if __name__ == "__main__":
Game = Main()
Game.start()
编辑:内存增加来自这个函数。但是现在我想知道如何改变这个改变这个函数,这样我就可以在不增加内存的情况下保持线程
def update(self):
for current in self.asteroid_list:
x = threading.Thread(target=current.Update)
y = threading.Thread(target=current.Drift)
x.start()
y.start()
try:
x.join()
y.join()
except:
pass
我想保持线程(或高效的东西),因为根据我的经验,pygame 一次对多个图像进行 blitting 有点慢,所以使用循环,我可以尽快开始对它们进行 blitting 的过程,然后一旦它们都开始了,我调用 x.join() 所以无论如何,线程不会落后于导致视觉错误等的框架。
提前致谢
【问题讨论】:
-
请edit您的问题创建minimal reproducible example。如果最小示例没有内存泄漏,恭喜!您可以通过逐步添加代码并修复泄漏位来解决您自己的问题。如果没有,社区可能会为您提供帮助。
-
@importrandom 谢谢你的建议。我不明白为什么我被否决了。我现在已经上传了包含内存泄漏的代码。不久前有人告诉我永远不要包含我的整个代码,因为它阻塞了帖子,人们不想通过整个代码来进行小内存泄漏
-
您的事件处理程序在每次游戏循环迭代时为每个小行星创建一个线程,这可能是您增加内存使用的原因。我怀疑这是必要的。您还在每个循环中加载和转换图像,这是次优的。您应该在创建对象时加载一次图像。请查看pygame sprites 和groups,它们让你做你想做的事变得更容易。
-
顺便说一句:每个
Asteroid中的每个update()都在重新加载、重新缩放和重新旋转位图。这是在浪费一个巨大的CPU 数量。加载位图一次,预缩放它。然后制作包含 /N/ 位图旋转的列表,如果您需要度数精度,甚至 360。然后Asteroid对象只需要从列表中绘制适当的位图。更新将变为:window.blit( asteroid_images[ int( self.angle) ], ( self.x, self.y ) ) -
你能解释一下你建议的列表部分吗?我已将位图加载移动到 Asteroids.__init__() 所以它只加载一次。我不明白你的意思
by /N/ rotations of the bitmap
标签: python python-3.x memory-leaks pygame python-multithreading