一個簡單的遊戲

匯入並初始化

每個模組都需要匯入,pygame 也不例外。雖然我們需要為 pygame 中的所有匯入模組呼叫函式 pygame.init() 來正確初始化。如果我們忘記這一點,一些模組將無法工作。該函式還返回所有成功和失敗的初始化的元組(如果模組初始化失敗,則不會引發錯誤)。

import pygame
successes, failures = pygame.init()
print("{0} successes and {1} failures".format(successes, failures))

創造必需品

我們還需要建立一個顯示器。Pygame 已經建立了一個(隱藏)顯示,所以我們需要做的就是設定顯示模式(在這個例子中我們只設定解析度)。建立一個時鐘以確保我們的程式以固定的速度更新也是一個好主意(否則它會以不同的速度執行,具體取決於計算機的速度)。

screen = pygame.display.set_mode((720, 480))  # Notice the tuple! It's not 2 arguments.
clock = pygame.time.Clock()
FPS = 60  # This variable will define how many frames we update per second.

為了稍後在我們的程式碼中可讀性,我們將建立兩個顏色常量,它們代表紅色,綠色和藍色(RGB)的元組。值從 0(無光)到 255(全光)。

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

在 pygame 中,我們通常使用 Surface 來表示物件的外觀,使用 Rect (矩形)來表示物件的位置。甲表面是像的一張白紙含有顏色或影象。如果你正在建立一個類,你應該將屬性命名為 image 和 *rect,*因為許多函式將查詢並使用這些屬性。這些類可以通過繼承 pygame.sprite.Sprite 類而受益,原因可以在這裡閱讀。

rect = pygame.Rect((0, 0), (32, 32))  # First tuple is position, second is size.
image = pygame.Surface((32, 32))  # The tuple represent size.
image.fill(WHITE)  # We fill our surface with a nice white color (by default black).

遊戲迴圈

現在我們為遊戲迴圈設定了所有內容。這是一個為整個遊戲執行的迴圈,我們處理事件並更新螢幕和物件的位置。

首先,我們將確保我們的迴圈在給定的 FPS 下執行。我們定義了 FPS 並在程式開始時建立了我們的時鐘。以下程式碼將確保我們的程式有足夠的時間來使迴圈重複我們定義 FPS 的量。在這個例子中,每秒 60 次。

clock.tick(FPS)

然後我們將處理事件。事件基本上是使用者操作,例如移動滑鼠或按鍵。Pygame 會將所有這些事件註冊到我們通過呼叫 pygame.event.get() 得到的佇列中。我們可以迭代這個並檢查是否有我們想要處理的事件。事件有一個 type 屬性,我們可以檢查 pygame 模組中的常量來確定它是什麼型別的事件。

for event in pygame.event.get():
    if event.type == pygame.QUIT:  # The user pressed the close button in the top corner of the window.
        quit()
        # Close the program. Other methods like 'raise SystemExit' or 'sys.exit()'.
        # Calling 'pygame.quit()' won't close the program! It will just uninitialize the modules.

我們還可以檢查 if event.type == pygame.KEYDOWN 以檢視使用者是否按下了按鍵。在這種情況下,事件有一個屬性,我們可以檢查它以檢視它代表的鍵。

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        quit()
    elif event.type == pygame.KEYDOWN:
        if event.key == pygame.K_w:
            rect.move_ip(0, -2)  # Changes the rect's position.
        elif event.key == pygame.K_s:
            rect.move_ip(0, 2)
        elif event.key == pygame.K_a:
            rect.move_ip(-2, 0)
        elif event.key == pygame.K_d:
            rect.move_ip(2, 0)

現在我們需要顯示我們的影象。首先,我們可能希望從之前的渲染中清除螢幕。我們通過用黑色填充整個螢幕來做到這一點(刪除程式碼以瞭解我們為什麼要清除它)。然後,我們需要的 blit 我們的影象在螢幕上。Blitting 實際上意味著將影象複製到另一個表面(在我們的例子中是螢幕)。最後我們翻轉更新螢幕。

當我們進行 blitting 時,我們實際上並沒有向使用者顯示任何內容。想象一下它是一邊的計算機而另一邊是使用者。計算機在螢幕的一側繪製( blits ),將其翻轉向使用者,然後重複。

screen.fill(BLACK)
screen.blit(image, rect)
pygame.display.update()  # Or 'pygame.display.flip()'.

現在我們有一個基本的遊戲! 非常無聊,是的,但必需品在那裡! 結合你當前的 Python 知識,你應該能夠建立出色的東西。

完整的程式碼

import pygame
successes, failures = pygame.init()
print("{0} successes and {1} failures".format(successes, failures))

screen = pygame.display.set_mode((720, 480))
clock = pygame.time.Clock()
FPS = 60  # Frames per second.

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# RED = (255, 0, 0), GREEN = (0, 255, 0), BLUE = (0, 0, 255).

rect = pygame.Rect((0, 0), (32, 32))
image = pygame.Surface((32, 32))
image .fill(WHITE)  

while True:
    clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                rect.move_ip(0, -2)
            elif event.key == pygame.K_s:
                rect.move_ip(0, 2)
            elif event.key == pygame.K_a:
                rect.move_ip(-2, 0)
            elif event.key == pygame.K_d:
                rect.move_ip(2, 0)

    screen.fill(BLACK)
    screen.blit(image, rect)
    pygame.display.update()  # Or pygame.display.flip()

稍微改進了遊戲機制

請注意,程式會檢查我們何時按下按鍵,而不是當我們按住按鍵時。為了解決這個問題,我們可以引入速度變數。我們可以建立一個播放器類來保持它更有條理。為了避免與幀相關的移動(如果我們將 FPS 更改為 30,物件將以一半的速度移動),我們通過將時間間隔傳遞給可移動物件來引入時間相關的移動。

import pygame

successes, failures = pygame.init()
print("Initializing pygame: {0} successes and {1} failures.".format(successes, failures))

screen = pygame.display.set_mode((720, 480))
clock = pygame.time.Clock()
FPS = 60

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((32, 32))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()  # Get rect of some size as 'image'.
        self.velocity = [0, 0]

    def update(self):
        self.rect.move_ip(*self.velocity)

player = Player()
running = True
while running:
    dt = clock.tick(FPS) / 1000  # Returns milliseconds between each call to 'tick'. The convert time to seconds.
    screen.fill(BLACK)  # Fill the screen with background color.

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                player.velocity[1] = -200 * dt  # 200 pixels per second
            elif event.key == pygame.K_s:
                player.velocity[1] = 200 * dt
            elif event.key == pygame.K_a:
                player.velocity[0] = -200 * dt
            elif event.key == pygame.K_d:
                player.velocity[0] = 200 * dt
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_w or event.key == pygame.K_s:
                player.velocity[1] = 0
            elif event.key == pygame.K_a or event.key == pygame.K_d:
                player.velocity[0] = 0

    player.update()

    screen.blit(player.image, player.rect)
    pygame.display.update()  # Or pygame.display.flip()

print("Exited the game loop. Game will quit...")
quit()  # Not actually necessary since the script will exit anyway.

關於此程式碼,仍有許多事情需要改進。我建議你閱讀 pygame 教程和理查德瓊斯的演講,以獲得更深入的內容。