1

嘿嘿,这是我之前提出的“导入中的导入”问题的扩展,所以版主可以随意合并 2。

我有 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 的空白文件并为其分配全局值,但大多数时候我发现它只会让我的代码看起来笨重且难以编写。以及.. 我也不想initpygame 两次。有什么“Pythonic”的方法吗?

4

3 回答 3

5

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

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

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

py

def blitSpecial(surf):
    surf.blit()

py

import B

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

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

特别是对于您的 pygame 情况,屏幕表面的一切都应该发生,A.py其中使用所有其他模块来实现自定义类和实用程序功能。

于 2012-04-23T00:19:23.790 回答
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)
于 2012-04-23T00:22:45.307 回答
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)

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

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

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 类创建的对象做一些有趣的事情,例如将它们粘贴到列表中。

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)

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

def move(self, move_amount=(1,0):
    self.rect.move_ip(move_amount[0], move_amount[1])
于 2012-04-23T00:45:34.573 回答