pygame庫寫遊戲——入門——存儲圖像

RBG圖像,遊戲中往往使用RBGA圖像,A即Alpha,也就是表示透明度的部分(0~255),0代表完全透明。可以使用多種軟件創建含有Alpha通道的圖片

存儲圖像的方式(圖片格式),JPEG、PNG等等,python大多能支持。

使用surface對象
對於Pygame,加載圖片就是python.image.load,給定一個文件名,就還你一個surface對象。事實上屏幕也是一個surface,pygame.display.set_mode即返回了一個屏幕surface對象。
創建Surface對象的方法:1、就是pygame.image.load,這個對象有與圖像相同的尺寸和顏色;2、就是指定尺寸創建一個空的surface,
blank_surface == pygame.Surface((256,256),flags,depth)
其中第一個參數是對象的像素256*256;
第二個參數flags可以設定爲HWSURFACE – 類似於前面講的,更快!不過最好不設定,Pygmae可以自己優化。或者SRCALPHA – 有Alpha通道的surface,如果你需要透明,就要這個選項。這個選項的使用需要第三個參數爲32。
第三個參數是depth,pygame.display.set_mode中的一樣,你可以不設定,Pygame會自動設的和display一致。不過如果你使用了SRCALPHA,還是設爲32吧:

bland_alpha_surface = pygame.Surface((256, 256), flags=SRCALPHA, depth=32)

轉換Surfaces
最開始的hello world程序中有兩句轉換背景圖和鼠標圖的程序,包括第一個普通的轉換convert(),等價於display;第二個是帶有alpha通道的轉換convert_alpha()

矩形對象(Rectangle Objects)
一般來說在制定一個區域的時候,矩形是必須的,比如在屏幕的一部分畫東西。在pygame中矩形對象極爲常用,它的指定方法可以用一個四元素的元組,或者兩個二元素的元組,前兩個數爲左上座標,後兩位爲右下座標。
Pygame中有一個Rect類,用來存儲和處理矩形對象(包含在pygame.locals中,所以如果你寫了from pygame.locals import *就可以直接用這個對象了),比如:

my_rect1 = (100, 100, 200, 150)
my_rect2 = ((100, 100), (200, 150))
#上兩種爲基礎方法,表示的矩形也是一樣的
my_rect3 = Rect(100, 100, 200, 150)
my_rect4 = Rect((100, 100), (200, 150))

一旦有了Rect對象,我們就可以對其做很多操作,比如調整位置和大小,判斷一個點是否在其中等等。

剪裁(clipping)
通常的遊戲只需要繪製屏幕的一部分,如菜單欄等等。爲實現這一點,surface就有了剪裁區域(clipping area),一旦定義這個區域,那麼只有這個區域內的像素會被更改,其他位置不變。這個區域默認是所有地方,但是可以通過set_clip()來設定,通過get_clip()來獲得這個區域。

如下幾段代碼:

screen.set_clip(0,400,200,600)
draw_map()
#在左下角畫地圖

子表面(Subsurfaces)
Subsurface就是在一個Surface中再提取一個Surface,記住當你往Subsurface上畫東西的時候,同時也向父表面上操作。這可以用來繪製圖形文字,儘管pygame.font可以用來寫很不錯的字,但只是單色,遊戲可能需要更豐富的表現,這時候你可以把每個字母(中文的話有些喫力了)各自做成一個圖片,不過更好的方法是在一張圖片上畫滿所有的字母。把整張圖讀入,然後再用Subsurface把字母一個一個“摳”出來,就像下面這樣

my_font_image = Pygame.load("font.png")
letters = []
letters["a"] = my_font_image.subsurface((0,0), (80,80))
letters["b"] = my_font_image.subsurface((80,0), (80,80))

填充(fill)Surface
填充有時候能夠作爲一種清屏的操作,把整個surface填上一種顏色。

screen.fill((0,0,0))

同樣可以提供一個矩形來制定填充某個部分(也可以作爲畫矩形的方法)

設置像素
set_at方法可以做到這一點,它的參數是座標和顏色,下面的小腳本會隨機的在屏幕上畫點:

import pygame
from pygame.locals import *
from sys import exit
from random import randint

pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    rand_col = (randint(0, 255), randint(0, 255), randint(0, 255))
    #screen.lock()    #很快你就會知道這兩句lock和unlock的意思了
    for _ in range(100):
        rand_pos = (randint(0, 639), randint(0, 479))
        screen.set_at(rand_pos, rand_col)
    #screen.unlock()

    pygame.display.update()

獲得Surface上的像素
get_at()可以幫我們做到這一點,接受一個座標,返回這個座標上的顏色。但是
不過記住get_at在對hardware surface操作的時候很慢,而全屏的時候總是hardware的,所以慎用這個方法!

鎖定Surface

當Pygame往surface上畫東西的時候,首先會把surface鎖住,以保證不會有其它的進程來干擾,畫完之後再解鎖。鎖和解鎖時自動發生的,所以有時候可能不那麼有效率,比如上面的例子,每次畫100個點,那麼就得鎖解鎖100次,現在我們把兩句註釋去掉,再執行看看是不是更快了(好吧,其實我沒感覺出來,因爲現在的機器性能都不錯,這麼點的差異還不太感覺的出來。不過請相信我~複雜的情況下會影響效率的)?

當你手動加鎖的時候,一定不要忘記解鎖,否則pygame有可能會失去響應。雖然上面的例子可能沒問題,但是隱含的bug是我們一定要避免的事情。

Blitting

blit的的中文翻譯給人摸不着頭腦的感覺,可以譯爲位塊傳送(bit block transfer),其意義是將一個平面的一部分或全部圖象整塊從這個平面複製到另一個平面,下面還是直接使用英文。

blit是對錶面做的最多的操作,我們在前面的程序中已經多次用到,不多說了;blit的還有一種用法,往往用在對動畫的表現上,比如下例通過對frame_no的值的改變,我們可以把不同的幀(同一副圖的不同位置)畫到屏幕上:

screen.blit(ogre, (300, 200), (100 * frame_no, 0, 100, 100))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章