青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 97, 文章 - 22, 評論 - 81, 引用 - 0
數(shù)據(jù)加載中……

Pygame游戲開發(fā) 之二

Pygame游戲開發(fā)之二

初窺門徑

游戲中需要用到很多對象,比如人物、野怪、建筑物、UI控件等等,他們的行為不盡相同,但是總有那么些共同點,如果將所有的東西都封裝成各自的類難免會寫上很多重復的代碼,因為兩個對象如果具有相同的行為(比如人物和野怪都可以行走)如果寫兩個move()函數(shù),以后改起來就要修改兩個地方,不容易維護而且擴展很麻煩,但是人物和野怪又有其它不相同的行為,比如技能之類的不同。所以比較好的處理方法是抽象出一個生物類,然后讓人物和野怪去繼承它,舉個例子:

class RenderObject(pygame.sprite.Sprite) :

    # 靜態(tài)變量

    images = []

    def __init__(self, selfdata) :

        self.image       = self.images[ int(selfdata[0])  ]

        self.size         = [self.image.get_width(), self.image.get_height()]

        self.offset       = [0,0]

        self.position     = [0,0]

        self.speed       = [0.0,0.0]

    def move(self, xgo, ygo) :

        do_move()

    def draw(self, screen) :

        do_draw()

以上這個類RenderObject是自己定義的用于渲染的類的基類,它繼承自pygame.sprite.Sprite,這里有必要先介紹一下pygame.sprite,這個模塊在pygame中是選擇性使用的,他可以作為游戲中很多對象的基類,并且將它擁有的東西繪制到Surface上,還有一個Group類是Sprite類的容器類,可以包含很多Sprite

       RenderObject有三個類函數(shù),__init__Python中的特殊函數(shù),類似C語言中的構(gòu)造函數(shù),當類實例被創(chuàng)建的時候,這個函數(shù)會被自動執(zhí)行,它的目的是執(zhí)行一些該對象的必要的初始化工作(我在這個函數(shù)中加入了一個selfdata的列表,以便于不同類型的控件添加初始化信息)。move函數(shù)是執(zhí)行移動操作,而draw函數(shù)則負責渲染。

       首先來看下__init__函數(shù),在Python中使用變量不需要提前聲明,所以要用到的變量我把它放在了__init__函數(shù)中進行初始化,注意到每個函數(shù)都有一個self參數(shù),這個就好比C語言中的this指針,但是它是顯式聲明,隱式調(diào)用的。在使用類內(nèi)部變量的時候需要加self做修飾,我們可以看到該類的一些成員變量:

self.image      # 該渲染對象對應(yīng)的Surface

self.size        # 該渲染對象在Surface的矩形區(qū)域的寬高

self.offset       # 該渲染對象在Surface的左上角坐標

self.position     # 該渲染對象將被繪制到屏幕的位置

self.speed       # 該渲染對象的速度

       之所以要用到offsetsize,是因為該Surface不是完全被用來顯示的,我們只取某一張Surface的某一部分用于顯示,如果不是很明白,那么參看Player類的相關(guān)描述就知道為什么了。

       對于move(self, xgo, ygo)函數(shù),我們暫時可以這樣實現(xiàn):

if xgo :

self.position[0] += self.speed[0] * xgo

if ygo :

self.position[1] += self.speed[1] * ygo

xgoygo都是三值變量(1,0,-1),分別表示在兩個坐標軸方向是否發(fā)生了位移,并且這個位移是正向的還是逆向的。于是我們可以通過鍵盤輸入來傳遞對應(yīng)的參數(shù),position的值就會隨之變化了。注意如果這里速度為0,則表示靜態(tài)物體,position不會做任何變化。

對于draw(self, screen)函數(shù),用于將當前對象繪制到屏幕上,screen參數(shù)是上一節(jié)中提到的屏幕Surface,我們調(diào)用Surfaceblit函數(shù)就可以在屏幕上繪制當前對象了,像這樣:

screen.blit( self.image, self.position, (self.offset, self.size))

(self.offset, self.size)表示self.image這個Surface上對應(yīng)的矩形區(qū)域。

基類完成后,我們需要派生出一些子類,例如:

class Player(RenderObject) :

    actionwait = 50

    def __init__(self, selfdata) :

        RenderObject.__init__(self, selfdata)

        self.size[0] /= 4

        self.size[1] /= 4

        self.speed = [0.1,0.1]

        self.direction=3

        self.action=0

    def move(self, xgo, ygo) :

        RenderObject.move(self, xgo, ygo)

        if xgo or ygo :

            self.action = (self.action + 1) % (self.actionwait * 4)

        self.offset[0] = (self.action / self.actionwait) * self.size[0]

        self.offset[1] = self.direction * self.size[1]

 Player類作為游戲中的操作玩家,繼承自RenderObject,并且重寫它的__init__move函數(shù),引入directionaction變量分別表示當前Player的方向和動作,如圖2-1(資源來自66RPG,一個基于RPG Maker xp業(yè)余游戲制作的交流、合作、分享的網(wǎng)站,在此感謝66RPG為我們游戲開發(fā)者提供這么多的資源下載,淚流滿面啊||*_*||)。

2-1

該圖是游戲人物的四方向行走圖,每一行代表一個方向,每一列代表一個動作,我們只需要通過鍵盤或者鼠標的輸入事件不斷改變offset的值,就可以順利得進行人物動畫的切換。這就是為什么之前要引入offsetsize的原因了,因為這個對象只取當前圖片的某一部分用于顯示,而且每次是根據(jù)人物不同的狀態(tài)進行切換的,還可以發(fā)現(xiàn)Player類中引入了一個actionwait的靜態(tài)變量,之所以用到它是因為現(xiàn)在的電腦的處理速度實在是太快了,每次move調(diào)用,我們會將self.action的值+1,并且循環(huán)往復,如果沒有一個延時操作,人物的動作切換會非??欤@得十分不自然。

同時可以根據(jù)自己的喜好派生出很多不同類型的游戲元素,比如野怪、按鈕、菜單等等。

 

說到這里,還沒講到images這個靜態(tài)變量。RenderObject中定義了一個靜態(tài)列表,表示所有圖片的Surface對象的集合,我們可以在游戲載入的時候?qū)⑺械膱D片都轉(zhuǎn)化成Surface,然后每次調(diào)用的時候直接在images中尋找對應(yīng)的Surface即可,這樣就不用每次都調(diào)用load_image函數(shù)了。

但是還有個問題,比如我現(xiàn)在有以下幾張圖片:hero.pnggo.png、title.png、menu.png,那么不免要寫下面這段代碼:

Imgs = []

Imgs.append( load_image( ‘hero.png’) )

Imgs.append( load_image( ‘go.png’) )

Imgs.append( load_image( ‘title.png’) )

Imgs.append( load_image( ‘menu.png’) )

RenderObject.images = Imgs

append是列表的函數(shù),表示在已有列表中加入一個新的成員。這樣就可以把所有圖片預(yù)先載入到RenderObject.images列表中,以后訪問的時候只需要用下標索引即可。這也就是問題所在,因為現(xiàn)在圖片只有四張,這個代碼沒什么大的問題,但是如果圖片的數(shù)量增加到四十張、乃至四百張,那么問題也就隨之而來了,你將不斷地添加同一段代碼Imgs.append( load_image( ‘XXX’) ),這會使程序日漸冗長,而且每次新增一張圖片就需要添加一段代碼,某張圖片不需要了,有需要找到那段代碼將其刪除,維護會變得越來越繁瑣。

圖片的文件名其實是一系列的字符串數(shù)據(jù),我們大可以把它放到配置文件中,然后利用Python的文件讀取接口來將它們讀入,這樣以后需要添加一張圖片的時候只需要在配置文件中加入一個文件名即可,方便了許多。

我把所有的圖片的文件名放到了一個叫image_config.txt的文件中,具體的結(jié)構(gòu)組織可以看個人喜好,以下是我的組織形式:

 

/Control

title 1

menu 1

/Player

hero 1

monster 0

/Animation

cloud 10

 

’/’開頭的表示文件夾,比如/Control表示在Control文件夾下有兩種類型的文件(titlemenu),否則是某個文件的前綴加上當前類型文件的數(shù)量,比如title 2表示的其實是title-0.pngtitle-1.png這兩個文件,cloud 4則是cloud-0.pngcloud-1.png、cloud-2.png、cloud-3.png這四個文件。之所以要用編號的形式,是因為這些圖片有可能是一個動畫,又或許是一類相同的對象,這樣一來添加新圖片的時候會方便許多。

       然后就是按照你自己定的配置文件格式進行解析,從而將圖片進行載入。以下是我的圖片載入過程,我把它放在了InitializeImage函數(shù)中:

def InitializeImage() :

    config = open('image_config.txt', 'r')

    config.seek(0)

    filelist = config.readlines()

    config.close()

    nowfolder = ''

    imgs      = []

    for filename in filelist :

        if len(filename) < 2:

            continue

        if filename[0] == '/' :

            nowfolder = filename[1:-1]

        else :

            idx = filename.find(' ')

            pre = filename[:idx]

            for x in range(  int(filename[idx+1:-1])  ) :

                pfile = nowfolder + '\\' + pre + '-' + str(x) + '.png'

                print pfile

                imgs.append( data.load_image(pfile) )

    RenderObject.images = imgs

       open函數(shù)是Python中的文件讀取接口,類似C語言中的fopen,參數(shù)也是一樣的,返回的則是一個文件對象,我們首先調(diào)用seek(0)將文件頭指針定位到文件開頭,然后將該文件中所有的行通過readlines()讀入到filelist列表中,并且關(guān)閉文件。這時候filelist就儲存了該配置文件中所有的圖片文件信息,接下來的步驟是對它進行解析。

       通過遍歷filelist的每個成員,判斷當前的這一行表示的是文件夾信息還是圖片文件信息。如果是文件夾則更新nowfolder,nowfolder表示當前文件夾。filename[1:-1]表示不包含第一個字符和最后一個字符的子串(-1是最后一個字符的索引),之所以不要最后一個字符是因為讀入的時候是通過讀行的,所以最后一個字符在Win32下是\n也就是換行;如果是圖片文件信息,那么必定是類似 XXX num 的串,那么我們首先要找到這個串中的空格(這里需要保證文件名中不包含空格),通過字符串內(nèi)置的find(‘ ‘)函數(shù)可以找到第一個出現(xiàn)空格的字符的下標,然后我們就可以把這個串分成兩部分了,將第二個部分也就是找到的下標到結(jié)尾的子串,將它轉(zhuǎn)換成int類型,這就是當前類型圖片的數(shù)量,最后用一個for循環(huán)將所有當前類型的圖片創(chuàng)建出來。一個個appendimgs上去即可。

       再回頭來看RenderObject.__init__(self, selfdata)函數(shù),該函數(shù)中還有selfdata變量,我把它定義成一個列表,不同的子類將會擁有各自不同的列表元素和個數(shù),就好比對于動畫Animation類來說,它的值就是[st, en],表示當前動畫需要表示的始末圖片在images中的索引編號。

       Smpl = Animation([3, 12])

       可以簡單得通過以上的語句,就構(gòu)造出一個Animation的對象,并且可以通過Smpl訪問它所有的成員變量來進行初始化對象的起始位置以及其它信息。這里的動畫指的是最普通的動畫,是通過不同圖片的循環(huán)播放來實現(xiàn)的,以上的實例就是一個擁有10張圖片的動畫。(未完待續(xù))

    以上內(nèi)容均為原創(chuàng) 轉(zhuǎn)載請注明出處

 

posted on 2011-04-24 19:55 英雄哪里出來 閱讀(6185) 評論(3)  編輯 收藏 引用 所屬分類: Pygame

評論

# re: Pygame游戲開發(fā) 之二  回復  更多評論   

留爪,持續(xù)關(guān)注
2011-04-24 23:11 | zhaoyg

# re: Pygame游戲開發(fā) 之二  回復  更多評論   

@zhaoyg
閣下在學Pygame嗎?
2011-04-25 10:12 | 英雄哪里出來

# re: Pygame游戲開發(fā) 之二  回復  更多評論   

不錯不錯,期待更新
2011-04-27 00:44 | 賊寇在何方
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲无线观看| 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲大胆女人| 久久久久久久久久久一区| 久久一区二区三区av| 中国女人久久久| 国产乱码精品一区二区三区不卡 | 午夜久久久久久| 狠狠色伊人亚洲综合成人| 蜜臀av性久久久久蜜臀aⅴ| 久久中文字幕一区| 99av国产精品欲麻豆| 亚洲在线视频一区| 亚洲国产婷婷综合在线精品| 国内成人精品一区| 美日韩在线观看| 欧美视频日韩视频| 免费高清在线一区| 国产精品自拍一区| 亚洲国产精品专区久久| 国产美女精品视频| 99riav1国产精品视频| 在线观看视频欧美| 亚洲男女毛片无遮挡| 亚洲毛片在线免费观看| 久久精品国产一区二区三| 亚洲私人影院在线观看| 久久一日本道色综合久久| 亚洲欧美日韩一区在线| 欧美a级理论片| 亚洲第一区色| 亚洲精品一区在线观看| 久久久一区二区三区| 久久九九国产精品| 在线观看成人av电影| 欧美一区二区三区在线观看视频| 一区二区黄色| 国产精品一区免费在线观看| 亚洲精品国精品久久99热| 亚洲欧洲日韩综合二区| 久久av一区二区| 欧美成人在线免费视频| 亚洲片在线资源| 欧美精品一区二区蜜臀亚洲| 免费在线观看成人av| 亚洲电影专区| 欧美小视频在线| 日韩视频亚洲视频| 国产精品一区二区在线| 久久大逼视频| 99视频精品免费观看| 欧美在线精品一区| 亚洲第一二三四五区| 欧美性一二三区| 久久亚洲精品一区二区| 99re6这里只有精品视频在线观看| 亚洲专区在线| 激情综合网址| 国产精品久久久久久久久久直播| 欧美在线啊v| 亚洲国内自拍| 欧美69wwwcom| 久久精品国产99精品国产亚洲性色| 亚洲国产精品久久人人爱蜜臀| 欧美少妇一区| 欧美伦理91i| 蜜臀va亚洲va欧美va天堂| 亚洲性xxxx| 亚洲午夜av在线| 一区二区三区精品| 亚洲日本成人| 亚洲黄色影院| 91久久线看在观草草青青| 久久综合色8888| 久久精品视频免费播放| 久久国产夜色精品鲁鲁99| 亚洲欧美日韩精品久久久| 一区二区三区四区国产| 在线视频亚洲| 欧美自拍偷拍| 久久久水蜜桃av免费网站| 欧美一级片一区| 欧美特黄一级大片| 欧美精品偷拍| 国产精品久久一区二区三区| 欧美日韩一区二区三区免费看| 欧美v国产在线一区二区三区| 久久在线免费| 欧美日韩精品在线| 国产精品视频一| 国产午夜精品一区理论片飘花| 国产亚洲永久域名| 91久久国产综合久久| 夜夜夜精品看看| 久久精品成人欧美大片古装| 久久综合网hezyo| av成人免费观看| 久久精品二区| 国产精品一区二区视频| 狠狠色狠狠色综合日日91app| 亚洲裸体在线观看| 久久国产一区二区三区| 亚洲激情电影在线| 久久久久久69| 国产午夜精品视频免费不卡69堂| 亚洲国产清纯| 久久亚洲精品欧美| 亚洲自拍偷拍福利| 欧美三级特黄| 在线视频日韩精品| 亚洲国产精品女人久久久| 午夜性色一区二区三区免费视频| 欧美国产日韩一区二区在线观看| 国产日韩欧美精品一区| 性色一区二区三区| 一区二区高清在线观看| 欧美精品一区在线发布| 亚洲第一中文字幕| 欧美va亚洲va日韩∨a综合色| 黑人极品videos精品欧美裸| 亚洲专区在线| 亚洲欧美日韩国产一区| 国产精品男gay被猛男狂揉视频| 亚洲精品乱码久久久久| 亚洲激情电影在线| 欧美日韩国产综合视频在线观看中文| 亚洲第一精品影视| 亚洲国产成人在线视频| 欧美激情视频在线免费观看 欧美视频免费一| 国产一二精品视频| 欧美激情欧美狂野欧美精品| 欧美成人亚洲| 亚洲小说欧美另类社区| 午夜精品一区二区三区在线视| 国产一区二区三区在线观看网站 | 欧美午夜电影完整版| 宅男精品导航| 欧美一区二区三区另类| 亚洲精品国偷自产在线99热| 99香蕉国产精品偷在线观看| 欧美视频在线视频| 美女露胸一区二区三区| 欧美成人国产| 久久精品2019中文字幕| 欧美精选在线| 欧美不卡视频| 国产精品一二一区| 亚洲精品中文字幕在线| 伊人精品在线| 亚洲自拍偷拍一区| 日韩午夜免费| 欧美成人精品| 欧美日韩一级大片网址| 久久综合色8888| 国产亚洲午夜| 99国产精品国产精品久久 | 在线日本成人| 久久av红桃一区二区小说| 亚洲一区二区三区精品在线| 欧美福利视频在线| 欧美高清影院| 亚洲免费观看| 在线一区免费观看| 欧美精品久久天天躁| 亚洲国产一区二区三区a毛片| 在线免费观看视频一区| 久久亚洲视频| 日韩视频免费| 亚洲欧美电影在线观看| 国产精品久久777777毛茸茸| 亚洲深夜福利视频| 久久久久久久综合狠狠综合| 国产欧美日韩视频一区二区三区 | 欧美jizzhd精品欧美喷水 | 亚洲国产精品成人va在线观看| 欧美一区国产在线| 亚洲成人资源| 亚洲女女女同性video| 国产性猛交xxxx免费看久久| 欧美一区二区三区成人| 欧美激情视频一区二区三区在线播放| 亚洲国产欧美不卡在线观看| 欧美屁股在线| 久久精品亚洲精品国产欧美kt∨| 亚洲福利专区| 久久免费视频在线| 亚洲午夜视频在线| 亚洲国产视频直播| 国产视频在线观看一区二区| 欧美 日韩 国产一区二区在线视频| 亚洲日韩欧美视频一区| 久久久久久久网| 久久精品亚洲一区二区| 在线中文字幕一区| 99热免费精品| 亚洲黄色在线看| 亚洲国产成人久久综合一区| 韩国免费一区| 在线观看视频一区二区| 国产欧美日韩一区|