2012-04-22 24 views
1

Heyo,這是一個位「進口內進口」問題,早些時候我問,所以主持人隨意合併2Python和pygame的:避免產生顯示器表面兩次

我有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? 

我試圖使被稱爲地球並把它分配全局值的空白文件,但大部分我發現的時候,它只是讓我的代碼看起來笨重,很難寫。 以及..我不想init pygame兩次。 有沒有'Pythonic'的方法來做到這一點?

回答

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中發生,它將所有其他模塊用於自定義類和實用程序功能。

+0

很好的答案。但它真的很煩人做像這樣的東西: dostuff(電視,主要,房屋,建築物,人,瓷磚) – SuperDisk 2012-04-23 00:42:25

+1

@SuperDisk:我同意。這就是爲什麼你會嘗試編寫使用屬性實例化的類。這些方法適用於這些屬性。這是如何編寫模塊的一個非常基本的例子。正如你可以在很多pygame例子中看到的那樣,人們對現有的類進行子類化以實現自定義的東西。做對了,你不應該用10個參數來調用一個函數。 – jdi 2012-04-23 00:44:23

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) 
+0

我想你在這裏混淆了一些標籤? 'setup()'在你的'A'模塊中。另外,文檔說'init'可以安全地多次調用。 – jdi 2012-04-23 00:26:39

+0

這是/安全/多次調用,但沒有必要這樣做。 – snim2 2012-04-23 00:35:02

+0

就'setup'應該在'A'還是'B'方面來說,我認爲你的答案是有點整齊。當OP在他的'A.py'中有'display.set_mode'時,我把它放在'A'中。 – snim2 2012-04-23 00:46:10

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的引擎相比有多快/多慢,但它是構建一個可以繪製/擦除自己的類的非常快速的方法。

要使用它,只需創建一個顯示屏幕和一個電視對象。

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])