Python和Pygame:避免两次创建显示表面

时间:2012-04-22 23:08:32

标签: python variables pygame global geometry-surface

Heyo,这是我早些时候提出的“进口内进口”问题的延伸,所以主持人可以随意合并2。

我有两个文件:A.py和B.py

#A.py
import pygame
import B
pygame.init()
tv = pygame.display.set_mode((256, 256))
tv.blit(<some surface here>)


#B.py
import pygame
pygame.init()
tv.blit()??? <--- I need to blit to tv, but how do I do it here?

我尝试制作一个名为Globe的空白文件并为其分配全局值,但大多数时候我发现它只是让我的代码看起来很笨重而且很难写。 同样..我也不想init两次pygame。 有没有'Pythonic'的方法呢?

3 个答案:

答案 0 :(得分:5)

这个问题可能真的适用于任何结构化的python应用程序。

可执行的python脚本将具有入口点。这是您调用以启动应用程序的脚本。在此脚本中,它可以导入库模块以重用扩展功能。

您的应用程序需要有一个入口点。让我们假设它是A.py B.py将是一个库模块,您将导入并使用其功能。它不应该期望全局tv变量可以运行。相反,它应该至少具有带参数的函数。甚至是一个用表面实例化的类。这种方法的好处是您的B模块现在可以重复使用,而不依赖于某个可执行的主脚本,提供一个始终称为tv的全局表面

<强> B.py

def blitSpecial(surf):
    surf.blit()

<强> A.py

import B

tv = pygame.display.set_mode((256, 256))
B.blitSpecial(tv)

这是一个很好的习惯。如果所有模块都依赖于主脚本中的全局对象,那么它们的可重用性将大大降低。

特别是对于你的pygame情况,屏幕表面的所有内容都应该在A.py中进行,它使用所有其他模块来实现自定义类和实用程序功能。

答案 1 :(得分:0)

您只需拨打pygame.init()一次,因此我认为您的代码应如下所示:

#A.py
import pygame
import B

def setup():
    pygame.init()
    tv = pygame.display.set_mode((256, 256))
    ...
    mysurface = ...
    tv.blit(mysurface)
    return tv


#B.py
import pygame
def mydraw(surface):
    ...
    surface.blit()

# In whatever file you like :)
if __name__ == '__main__':
    surface_A = B.setup() # Do this first
    mydraw(surface_A)

答案 2 :(得分:0)

您可以编写将pygame.Surface对象作为参数的函数:

class TV():
    def __init__(self):
        self.img = ... 

        ### insert code to load image here

        self.rect = self.img.get_rect()

    def draw(self, surface):
        surface.blit(self.img, self.rect.topleft)

    def erase(self, surface, background):
        surface.blit(background, self.rect)

我个人不知道这与其他基于精灵的引擎相比有多快/慢,但它是一种非常快速的方法来构建一个可以绘制/擦除自身的类。

要使用它,只需创建一个显示屏和一个电视对象。

screen = pygame.display.set_mode((256, 256))     
background = pygame.Surface((0,0),(256,256))

background.fill(pygame.Color(0,0,0))
screen.fill(pygame.Color(0,0,0))

myTVobj = TV()

每当您想要在屏幕上绘制电视副本时,请致电

myTVobj.draw(screen)

要删除对象,请使用

myTVobj.erase(screen, background)

然后,您可以稍后使用从电视课程中创建的对象来做有趣的事情,比如将它们粘贴在列表中。

tv_list = []
tv_list.append(myTVobj)

您可以将一大堆电视添加到列表中,同时绘制所有电视。

tv_list = []
tv_list.append(myTVobj)
tv_list.append(myTVobj)
tv_list.append(myTVobj)

for tv in tv_list:
    tv.draw(screen)

或者你可以通过改变一行来删除它们

for tv in tv_list:
    tv.erase(screen)

最后,您可以在电视课程中再添加一项功能,让您可以移动它。如果您将.rect成员视为“位置标记”,您所要做的就是摆弄其成员(hehe)以更改对象的屏幕更新位置。

def move(self, move_amount=(1,0):
    self.rect.move_ip(move_amount[0], move_amount[1])