Skip to content

pygame 簡介

LanKuDot edited this page Aug 13, 2020 · 3 revisions

MLGame 專案的遊戲都是使用 pygame 套件撰寫的,因此有 pygame 的知識有助於遊戲開發,本篇會概略介紹 pygame 常用的部分。

安裝套件

$ python -m pip install pygame==1.9.4

座標系統

在 pygame 中,場景原點位在畫面的左上方,往右為 X 正方向,往下為 Y 正方向。用來指定或取得的物件的 xy 座標也是在物件的左上角。

Imgur

常用物件

以下大略介紹在開發遊戲中常用到的 pygame 物件。記得物件的用途即可,使用方式可以等到在後面的教學中遇到時再回來查詢,或是直接到 pygame 的 API 文件查詢。另外標註的常用函式中,可能會省略一些預設參數,如果需要完整的使用說明,請參考 pygame 的 API 文件。

pygame 的視窗,用來設置要顯示的內容。常用函式:

  • init():初始化視窗
  • set_caption(title):設置視窗的標題名稱
  • set_mode(size = (0, 0)) -> Surface:設置視窗的大小,會回傳一個 Surface 物件,為視窗的畫布
  • flip():將繪製在視窗畫布上的內容顯示到視窗上

Surface 是 pygame 用來表示圖片的物件,同時可以是畫布。一個 surface 可以畫到另一個 surface 上。常用函式:

  • Surface((width, height)):建立一個新的 surface
  • surface.blit(source, dest) -> Rect:將 source surface 畫到這個 surface 上。dest(x, y) tuple,用來指定 source 要畫在這個 surface 的哪個位置,要注意座標都是指物件的左上角。回傳的 Rect 標記的是這個 surface 受影響的像素區域
  • surface.fill(color, rect = None) -> Rect:在 rect 指定的區域填滿顏色color 是一個 (r, g, b) tuple,值為 0 ~ 255。如果沒有指定 rect,則填滿整個 surface。回傳的 Rect 一樣是標記受影響的像素區域
  • surface.convert() -> Surface:將 surface 的像素格式轉換成與視窗畫布一樣,會加快繪製到 display 的速度。回傳被轉換過的 surface,注意原本的 surface 並不會改變
    • 使用 pygame.image.load(filename) 讀取圖片檔案會回傳一個 surface,再使用 convert() 轉換成符合視窗畫布的格式,就可以加快繪製的速度

MLGame 專案中的遊戲經常使用 Rect 來定義遊戲物件的位置及大小。Rect 的四個屬性為 lefttopwidthheightlefttop 即為該物件的左上角座標,同時也是物件的 xy 座標,widthheight 則可以定義出矩形的大小。例如:

>>> from pygame import Rect
>>> rect = Rect(0, 0, 5, 3)
>>> rect
<rect(0, 0, 5, 3)>
>>> print(rect.x, rect.y, rect.width, rect.height)
0 0 5 3

對應的矩形樣貌:

Imgur

Rect 也提供虛擬屬性或是函式來方便取得或控制矩形的位置與大小:

>>> rect.bottomright
(5, 3)
>>> rect.center
(2, 1)
>>> rect.x = 2
>>> rect
<rect(2, 0, 5, 3)>
>>> rect.move_ip(5, 5)
>>> rect
<rect(7, 5, 5, 3)

另外 pygame.Rect 還有一系列檢測碰撞的函式,如:containscolliderect

MLGame 專案中的可視遊戲物件都會繼承自 Sprite,主要是為了利用 Group 來將可視物件一次畫到 surface 上,不需個別呼叫 surface.blit()。常用函式:

  • pygame.sprite.Group() -> Group:建立一個新的 group
  • group.add(*sprites):將多個 sprite 加到 group 中。sprites 指定一系列的 sprite,例如:group.add(sprite_1, sprite_2, ...)。只有尚未存在於該 group 中的 sprite 才會被加入
  • group.remove(*sprites):將多個 sprite 從 group 中移除
  • group.empty():清除所有在 group 中的 sprite
  • group.draw(surface):將 group 內的 sprite 畫到指定的 surface 上,繪製 sprite 沒有先後順序。
    • 使用 draw() 被繪製 sprite 需要擁有兩個屬性:rectimagerect 是一個 rect,代表該物件的位置,而 image 是一個 surface,代表該物件的外觀

一個簡單的 sprite 例子:

class Ball(pygame.sprite.Sprite):
    def __init__(self, color, init_pos_x, init_pox_y):
        super().__init__()

        self.rect = pygame.rect.Rect(init_pos_x, init_pos_y, 5, 5)
        
        self.image = pygame.surface.Surface(self.rect.w, self.rect.h)
        self.image.fill(color)

pygame.sprite 提供檢測碰撞的函式:

  • pygame.sprite.spritecollide(sprite, group, dokill, collided = None) -> Sprite_list:偵測 sprite 有沒有與 group 中的 sprite 碰撞。如果 dokillTrue 則被碰撞的 sprite 會從 group 中移除。collided 可指定函式用來檢測兩個 sprite 有沒有碰撞。回傳的 Sprite_list 是一個 list,存放 group 中被碰撞的 sprite。
    • 使用此函式的的 spritegroup 中的 sprite 都必須有 rect 屬性。
  • pygame.sprite.collide_rect(left, right) -> bool:檢測 leftright 兩個 sprite 是否碰撞,兩個 sprite 必須有 rect 屬性。

pygame 用來繪製文字的模組。常用函式:

  • pygame.font.init():初始化文字模組
  • pygame.font.Font(filename, size) -> Font:建立一個新的文字物件。filename 指定文字檔案,如果為 None 則使用預設字體。size 是字體的高度,單位為 pixel。
  • font.render(text, antialias, color, background = None) -> Surface:建立已有指定文字的 surface。text 為繪製的文字內容,antialiasTrue 則文字會較為平滑,color 為文字顏色,background 為文字背景顏色。

繪製文字到螢幕的例子:

import pygame

pygame.display.init()
pygame.font.init()

display_surface = pygame.display.set_mode((100, 100))

font = pygame.font.Font(None, 20)
font_surface = font.render("Hello", True, (255, 255, 255))

display_surface.blit(font_surface, (10, 10))
pygame.display.flip()