Python遊戲:PyGame(轉自韓憲平的博客)

Pygame是腳本語言Python的一個擴展包就是SDL的封裝包,是用Python C語言開發;開發人是Pete Shinners。專門用於開發各類遊戲。SDL意思是Simple Directmedia Library即“簡單媒體類庫”,這是一個跨平臺的控制多媒體的C語言類庫,類似於 DirectX。這裏說的媒體包括CDROM即光驅、鍵盤鼠標、音頻視頻、操縱桿等輸入輸出設備,Pygame寫了關於這些對象的類庫可在官方網站上找到。因爲是“面向對象”就是所謂Object-Oriented編程語言,所以我們可以繼承這些類的性質來編寫我們自己的遊戲。

Pygame的官方網站: Pygame.org PyGameLogoTiny.gif
可惜中文的Pygame文檔還沒有。因爲Pygame是面向對象腳本編程語言Python的一個擴展,所以在使用Pygame之前要求基本的Python的知識和技術。


不管在什麼平臺上開發,所有遊戲的代碼通常會有的結構包含六個部分:

  1. (一)加載Pygame的或者其他工具軟件的模塊,在Python是使用import語法完成;
  2. (二)資源處理類包括處理圖象、聲音、連接或斷開網絡等;
  3. (三)遊戲本身的對象類;
  4. (四)其他函數。包括不能歸類的必要函數,它們可以歸入遊戲的邏輯代碼塊裏但是這樣處理會增加理解代 碼的難度,所以把這類函數單獨處理;
  5. (五)初始化。包括Pygame本身對象的初始化;遊戲對象的初始化;背景、鼠標的初始化等;
  6. (六)主循環就是def main()。處理用戶輸入、更新遊戲對象和顯示區等。

實際上,遊戲的結構是個風格問題,不同的人、從不同的側重點出發會使用不同的方法組織自己的遊戲代碼。中國人學太極拳的時候有這樣的一個講究,剛剛開始學的時候要有嚴格的“架式”就是動作規範,但是等到悟到用意不用力、用意念引導動作的階段就可以隨心所欲,不必太拘泥於一招一式細節了。

例如有從完全另外的角度的方法,把代碼按照一下四個方面組織:(請查看這裏的資源作爲參考)

  1. 模塊和對象的初始化;
  2. 處理用戶輸入和事件循環;
  3. 動畫和模擬;
  4. 提交;

不管使用什麼方式組織代碼,上面例子中最主要的結構有兩個:一個是主程序即mail() loop;一個是遊戲對象的類。主程序是遊戲腳本開始時執行的,包括處理Pygame模塊本身的初始化和遊戲對象的初始化,還包括所謂事件循環就是處理遊戲玩家的輸入如鼠標、鍵盤動作和其他事件的隊列;而遊戲類對象封裝了遊戲角色的數據和邏輯。對於初學者來說,先理解這兩個結構可收提綱協領的效果。有些簡單的遊戲只有一個遊戲對象(沒辦法,我們總是要從最簡單的例子開始),可能沒有完全按照上面的格式寫,但總是包含了這樣的模式在裏面。

這裏有一個Pygame的代碼庫,各種遊戲代碼可供研究:Pygame代碼庫

第一個簡單的例程hello.py:

#Find place where Python interpretor located 讓遊戲腳本找到Python解釋器安裝的地方
#!/usr/bin/python

#Import using modules 輸入要用到的模塊
import pygame
from pygame.locals import *

def main():
#Initialise screen 初始化。初始化軟件模塊、初始化屏幕
pygame.init()
screen = pygame.display.set_mode((150, 50))
pygame.display.set_caption('Basic Pygame program')

#Fill background 添入背景
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))

#Display some text 顯示區裏顯示文本
font = pygame.font.Font(None, 36)
text = font.render("Hello There", 1, (10, 10, 10))
textpos = text.get_rect()
textpos.centerx = background.get_rect().centerx
background.blit(text, textpos)

#Blit everything to the screen 把所有東西畫到屏幕上
screen.blit(background, (0, 0))
pygame.display.flip()

#Event loop事件循環
while 1:
for event in pygame.event.get():
if event.type == QUIT:
return

screen.blit(background, (0, 0))
pygame.display.flip()

#start main() 啓動腳本時執行主循環
if __name__ == '__main__': main()

把這段代碼用自己的編輯器寫入你的一個名字叫py/的目錄裏,這個目錄裏只包含作爲測試和學習用的代碼樣例(當然你也可以有其他的安排,你肯定有自己的打算 。注意你下載這個程序時不要使用中文註釋,特別不要使用中文的#號,Python的解釋器不能識別。請只下載代碼。我這裏加中文是爲了解釋代碼的方便。注意給這個腳本一個名字hello.py。

用這個簡單的程序我們完成了一個框架,多數應用程序特別是一個遊戲就是寫在這上面的,如下圖:
圖像 “http://www.pygame.org/docs/tut/tom/basic.png” 因其本身有錯無法顯示。

不算空格,加註釋行,就是以#號開始的,以上總共31行代碼。還有其他的語言能用同樣的代碼量來完成同樣的工作嗎?也許你用可視化工具可以很容易地作出這了來,但那只是“依樣畫葫蘆”!而你用Python寫出這個簡單的框架,你學會了一種功能強大的語言!也許你會說Java的Applet能用更少的代碼完成這些工作,實際上不是這樣的,因爲Java/Applet是在用戶端的瀏覽器幫助下完成的,而這個是stand alone。Python還是一種標準的黑客工具,世界上頂極黑客正在使用她!

是很簡單嗎?但是你已經開始了!這個簡單的程序裏已經包含了遊戲的主要結構。
首先你要在計算機監視器上創建一個遊戲執行的框架區域,一般叫做screen。

***********************************************
課堂實驗一
使用命令python進入命令行模式:

>>> import pygame
>>> from pygame.locals import *
>>> screen = pygame.display.set_mode((800,400))

這樣你創建了一塊屏幕面積,寬800個像素,高400個像素,它的左上角的座標爲(0,0)這樣你就完成了屏幕初始化的工作。

********************************************

學習一種語言最好的辦法就是實驗,通過觀察軟件的行爲,輸入輸出的變化來理解代碼的功能。跟隨我的路線圖保證你能在最短時間內順利掌握語言和技術精髓,不必從基本教程開始。牛頓說過:“在科學發展上實例比理論更重要!”,我相信在學習技術上也是這樣。我們先仔細地研究這個程序樣例,深入剖析,徹底理解,舉一反三,觸類旁通。

  1. (1)pygame.init( ) ——實現模塊初始化,就是把你要輸入的模塊進行初始化,準備工作;
  2. (2)screen. = pygame.display.set_mode((150,50)) ——初始化遊戲屏幕,寬150高50個像素。
  3. (3)pygame.display.set_caption( 'Basic Pygame Program') ——在屏幕的頁眉上寫字;
  4. (4)background = pygame.Surface(screen.get_size() ) ——開始填滿背景,.get_size()表示跟屏幕一樣大。引用Surface創建的實例相當於在前面創建的screen上敷上一張畫布,所以後面的 blit( )方法實際上是在這張畫布上畫,而不是直接在screen上畫;
  5. (5)background.fill((255,255,255)) —— 把RGB格式的顏色寫入背景;
  6. (6)font = pygame.font.Font( );text = font.render("Hello There",1,(10,10,10))以及上面的screen是模塊的對象,區別於遊戲本身的對象。font創建字體對象,text創建文本對象就是框架中間的Hello There,(10,10,10)是文本字體的顏色,而中間的數字1是對字體性質的限定,這裏我們先忽略;
  7. (7)textpos = text.get_rect( ) —— 是爲font.render( )提交變量的text準備一個矩形框,讓提交的文本放在這裏;
  8. (8)background.blit ( text,textpos ) —— 可能blit ( )是最值得注意的方法,這不是一個常用詞,本copy和past是同義詞,就是拷貝和粘貼的意思,把什麼什麼拷貝/粘貼在什麼什麼上面,這裏就是把 text粘貼在textpos上的意思;
  9. (9)screen.blit(background,(0,0)) —— 接着又一次出現blit( )方法,這次是把上一步粘貼好文本的background再拷貝在screen上,(0,0)表示從座標原點開始就是從左上角開始;
  10. (10)pygame.display.flip( ) —— flip英文意思是輕拍、快速翻轉,這個方法激活各個元素,以後我們還會碰到方法update( ),這二者的作用有些相似,從字面上可以看出這個意思;
  11. (11)While 1 : —— 下面就開始事件循環,把可能的用戶輸入和其他輸入的動作隊列循環測試,給出應有的反應;
  12. (12)最後又出現了blit()、flip()方法,在每次檢測之後更新畫面;
  13. (13)if —— 語句告訴遊戲腳本執行定義的主循環程序即def main()。
第二個有動畫的例程ball.py:(可在這裏下載/拷貝/測試)

import sys, pygame
pygame.init()
size = width, height = 320, 240
speed = [2, 2]
black = 0, 0, 0

screen = pygame.display.set_mode(size)

ball = pygame.image.load("ball.bmp")
ballrect = ball.get_rect()
while 1:
for event in pygame.event.get():

if event.type == pygame.QUIT: sys.exit()

ballrect = ballrect.move(speed)

if ballrect.left < 0 or ballrect.right > width:

speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]

screen.fill(black)

screen.blit(ball, ballrect)
pygame.display.flip()

在這個例程中有了一個遊戲對象就是一個運動的球,有了處理資源的語句就是ball = pygame.image.load("ball.bmp")。資源包括圖像文件、聲音文件、互聯網接入等。Pygame能接受幾乎所有圖像音頻視頻文件格式如bmp、jpeg、mp3等。

第三個例程是更完整的chimp.py:(可在這裏下載/拷貝/測試)

"""




"""



os, pygame
pygame.locals *

pygame.font: ''
pygame.mixer: ''



(name, colorkey=None):
fullname = os.path.join('', name)
:
image = pygame.image.load(fullname)
pygame.error, message:
'', fullname
SystemExit, message
image = image.convert()
colorkey None:
colorkey -1:
colorkey = image.get_at((0,0))
image.set_colorkey(colorkey, RLEACCEL)
image, image.get_rect()

(name):
:
(self):
pygame.mixer pygame.mixer.get_init():
NoneSound()
fullname = os.path.join('', name)
:
sound = pygame.mixer.Sound(fullname)
pygame.error, message:
'', fullname
SystemExit, message
sound



(pygame.sprite.Sprite):
""""""
(self):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image('', -1)
self.punching = 0

(self):
""
pos = pygame.mouse.get_pos()
self.rect.midtop = pos
self.punching:
self.rect.move_ip(5, 10)

(self, target):
""
self.punching:
self.punching = 1
hitbox = self.rect.inflate(-5, -5)
hitbox.colliderect(target.rect)

(self):
""
self.punching = 0


(pygame.sprite.Sprite):
"""
"""
(self):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image('', -1)
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.rect.topleft = 10, 10
self.move = 9
self.di = 0

(self):
""
self.di:
self._spin()
:
self._walk()

(self):
""
newpos = self.rect.move((self.move, 0))
self.rect.left < self.area.left
self.rect.right > self.area.right:
self.move = -self.move
newpos = self.rect.move((self.move, 0))
self.image = pygame.transform.flip(self.image, 1, 0)
self.rect = newpos

(self):
""
center = self.rect.center
self.di = self.di + 12
self.di >= 360:
self.di = 0
self.image = self.original
:
rotate = pygame.transform.rotate
self.image = rotate(self.original, self.di)
self.rect = self.image.get_rect(center=center)

(self):
""
self.di:
self.di = 1
self.original = self.image

#主循環開始。當遊戲腳本開始這個函數即被調用,並初始化模塊和遊戲對象,執行事件循環直到返回
():
"""

"""

pygame.init()
screen = pygame.display.set_mode((468, 60))
pygame.display.set_caption('')
pygame.mouse.set_visible(0)


background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))


pygame.font:
font = pygame.font.Font(None, 36)
text = font.render("", 1, (10, 10, 10))
textpos = text.get_rect(centerx=background.get_width()/2)
background.blit(text, textpos)


screen.blit(background, (0, 0))
pygame.display.flip()


clock = pygame.time.Clock()
whiff_sound = load_sound('')
punch_sound = load_sound('')
chimp = Chimp()
fist = Fist()
allsprites = pygame.sprite.RenderPlain((fist, chimp))


1:
clock.tick(60)


event pygame.event.get():
event.type QUIT:

event.type KEYDOWN
event.key K_ESCAPE:

event.type MOUSEBUTTONDOWN:
fist.punch(chimp):
punch_sound.play()
chimp.punched()
:
whiff_sound.play()
event.type MOUSEBUTTONUP:
fist.unpunch()

allsprites.update()


screen.blit(background, (0, 0))
allsprites.draw(screen)
pygame.display.flip()




__name__ == '': main()
首先在代碼開始的地方有三重的雙括號""" """,括號內的叫docstring就是關於代碼的文檔說明,規範地說,每個程序代碼都應該包含這部分內容,開發者自己或開發團隊可以從這裏獲得關於代碼的功能、許可證等方面的信息。這是Python所特有的所謂“自省”功能,英語叫“Introspection”。這裏有必要加以簡單的介紹。在命令行裏使用dir(module/function),在實驗中用Python的模塊、函數、方法os、sys、 pygame等等甚至是一個數字如2來代替括號裏的斜體字,可以查看對象的性質。因爲在Python裏,一切都是對象,所以這些都可以使用dir()函數查看對象的性質,這包括對象的結構、包含的函數和方法、類的繼承關係、子類、可以接受的變量、返回的結果等詳細信息。另外有同等功能的是在命令行的符號>>>裏使用help( )函數,用法與dir( )相同,但是得到的信息有所不同。這些都內嵌在Python的解釋器裏所以叫做內省的。非常形象。

***********************************************
課堂實驗二
>>> import pygame
>>> print dir(pygame)
>>> print dir(pygame.Rect)
>>> print help(pygame.Rect)

例如:使用print dir(pygame.Rect)得到以下信息:
['__class__', '__cmp__', '__coerce__', '__copy__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__len__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__safe_for_unpickling__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'bottom', 'bottomleft', 'bottomright', 'center', 'centerx', 'centery', 'clamp', 'clamp_ip', 'clip', 'collidedict', 'collidedictall', 'collidelist', 'collidelistall', 'collidepoint', 'colliderect', 'contains', 'fit', 'h', 'height', 'inflate', 'inflate_ip', 'left', 'midbottom', 'midleft', 'midright', 'midtop', 'move', 'move_ip', 'normalize', 'right', 'size', 'top', 'topleft', 'topright', 'union', 'union_ip', 'unionall', 'unionall_ip', 'w', 'width', 'x', 'y']

信息給出了Pygame的模塊Rect包含的函數、需要的變量和子類。這樣你就知道怎樣使用這個模塊,例如由Rect創建的矩形面積有bottonleft、bottonright,就是左按鈕、右按鈕,那麼跟按鈕綁定的動作就是可引用的。面向對象包含的封裝就是把對象的性質和動作封裝在一個類裏面。

如果使用help(pygame.Rect)得到信息如下:
Help on class Rect in module pygame:

class Rect(__builtin__.object)
| The rectangle object is a useful object
| representing a rectangle area. Rectangles are
| created from the pygame.Rect() function. This routine
| is also in the locals module, so importing the locals
| into your namespace allows you to just use Rect().
|
| Rect contains helpful methods, as well as a list of
| modifiable members:
| top, bottom, left, right, topleft, topright,
| bottomleft, bottomright, size, width, height,
| center, centerx, centery, midleft, midright, midtop,
| midbottom.
| When changing these members, the rectangle
| will be moved to the given assignment. (except when
| changing the size, width, or height member, which will
| resize the rectangle from the topleft corner)
|
| The rectstyle arguments used frequently with the
| Rect object (and elsewhere in pygame) is one of
| the following things.
... ...
這些信息告訴我們庫類Rect能爲我們作些什麼工作,它創建一個矩形的面積把Sprite創建的對象就是圖像放在裏面等等。
********************************************

我們在註釋裏強調了三次出現blit( )函數,所以這個函數對於理解遊戲代碼是個關鍵!第一個blit()的語法是background.blit(text,textpos),即把文本text拷貝在text的位置textpos上,並把textpos拷貝在background上;第二個blit()的語法是screen.blit(background,(0,0)),是把有了文本的background拷貝在screen上;第三個screen.blit(background,(0,0))把上面剛創建、並拷貝在background上的遊戲模擬對象fist和chimp再拷貝到screen上;還有要注意的是,每個blit()後面都跟隨一個flip(),上面在簡單例子裏我們已經介紹了英語flip的意義,這是要更新畫面,動畫就是每一個循環給遊戲對象一個新的位置,然後用flip()使得動畫不斷翻轉,得到運動的感覺。而語句clock.tick(60)是由創建遊戲對象的部分裏的clock = pagame.time.Clock()語句對象化得到的,這個對象告訴遊戲腳本按照每秒60楨的速度更新屏幕。

PyGame的庫類介紹

Pygame的類庫:

Cdrom || Cursors || Display || Draw || Event || Font || Image || Joystick || Key || Mixer || Mouse || Movie || Music || Overlay || Pygame || Rect || Sndarray || Sprite || Surface || Surfarray || Time || Transform

這些庫類的功能可以望文生義,如Crom是處理光盤的類,Cursors是處理光標的類,Key是處理鍵盤的類,Joystick是處理遊戲操縱桿的類, Mouse是處理鼠標的,而Music顯然是處理音樂的。等大家有了一些基礎之後就應該仔細地研究這些類庫,熟練地掌握他們做起遊戲來得心應手,左右逢源。下面我們將就最常用的加以說明,在上面的樣例涉及到的就是最重要的類庫。

下面我們將以sprite、Display、Event、Image等爲例說明類庫的使用。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章