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

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

Pygame游戲開發(fā) 之三

Pygame游戲開發(fā)之三

初出茅廬

         Pygame中除了Sprite,還有一個DirtySprite,它是由Sprite派生出來的繪制效率更高的精靈,較之Sprite多了以下幾個屬性:
dirty = 1
     如果設(shè)為1,則進(jìn)行重繪,并且重置為0

        如果設(shè)為2,則一直重繪,并且永遠(yuǎn)不設(shè)為0
        如果設(shè)為0表示不需要繪制

blendmode = 0

       混合模式,參見blit函數(shù)的最后一個參數(shù)

source_rect = None

       原圖的裁剪矩形,等同于我們之前定義的(self.offset, self.size)

    相對于self.image的左上角坐標(biāo)永遠(yuǎn)是(0,0)

visible = 1

    是否需要被繪制

我們可以發(fā)現(xiàn),source_rect和我們之前定義的(self.offset, self.size)的表示的意義是一樣的,于是可以將原來的RenderObject類加以改進(jìn),如下:

class RenderObject(pygame.sprite.DirtySprite) :

    framewait = 50

    images = []

    def __init__(self, selfdata) :

        pygame.sprite.DirtySprite.__init__(self)

        self.dirty        = 2

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

        self.rect         = self.image.get_rect()

        self.source_rect   = self.image.get_rect()

        self.blendmode   = 0

        self.visible       = 1

        self.speed        = [0.0,0.0]

        self.frame        = 0

    def move(self, xgo, ygo) :

        if xgo or ygo :

            self.rect.move_ip(self.speed[0] * xgo, self.speed[1] * ygo)

    def update(self) :

        pygame.sprite.DirtySprite.update(self)

        self.frame += 1

并且讓RenderObject繼承pygame.sprite.DirtySprite,移除self.offsetself.size,而改用self.source_rect來代替,而且position變量也改用Sprite的成員變量rect來代替,這樣一來有個好處就是繪制函數(shù)不用我們?nèi)ゲ傩牧耍灰峁?/span>image(源Surface),source_rect(源Surface中需要繪制的區(qū)域),rect(目標(biāo)繪制在屏幕的矩形區(qū)域)以及一些輔助變量,繪制工作就由DirtySprite去做了。

       這里有必要重新解釋一下Sprite的工作原理(如何被繪制以及如何進(jìn)行更新),Sprite有一個容器類Grouppygame.sprite.Group是承載了很多Sprite的容器,它有以下一些方法供調(diào)用:

Group.sprites()

       返回所有該容器包含的Sprite的列表

Group.copy()

       返回一個包含當(dāng)前Group內(nèi)相同的SpriteGroup的新的實(shí)例。

Group.add(*sprites)

       添加任意數(shù)量的Sprite到這個Group內(nèi)。

Group.remove(*sprites)

移除任意數(shù)量的Sprite從這個Group內(nèi)。

Group.has(*sprites)

       如果給定的sprites都存在那么返回True,否則返回Flase,這個和in操作類似(“if sprite in group: …”)。

Group.update()

       調(diào)用所有在當(dāng)前Group內(nèi)的Spriteupdate()函數(shù),注意每個Sprite都有一個update()函數(shù),如果某個類繼承了Sprite,可以覆蓋這個函數(shù)進(jìn)行相應(yīng)的更新操作。

Group.draw(Surface)

       將當(dāng)前Group內(nèi)的所有的Sprite繪制到Surface上來,注意這里需要用到Sprite.image來確定源SurfaceSprite.rect來確定繪制的位置(當(dāng)然,如果是DirtySprite還需要知道source_rect的值)。

Group.clear(Surface_dest, bgd)

       bgd繪制到Surface_dest上來。一般用于原窗口的背景繪制。

Group.empty()

       將所有的Sprite從這個Group中移除。

如果有了Group,當(dāng)我們需要更新操作的時候,只需要將所有的Sprite都加到這個Group中,然后調(diào)用Group.update()就可以將所有在這個Group中的Sprite全部更新了,而不需要一個一個去調(diào)用Sprite.update(),這個操作大大便利了我們編程。

       我們可以在RenderObject中添加一個update函數(shù)來覆蓋DirtySpriteupdate函數(shù),并且做一些我們需要做的工作,可以設(shè)定一個幀數(shù)self.frame,每次調(diào)用update函數(shù),幀數(shù)自增1,方便日后動畫的播放。

       舉個最簡單的例子,我們通過pygame.sprite.Group()來創(chuàng)建一個Sprite的容器類,然后往里面添加我們的Sprite對象,并且不斷更新Sprite,將其繪制到屏幕上:

       myGroup = pygame.sprite.Group()

       myGroup.add( RenderObject([0]) )

       myGroup.add( RenderObject([1]) )

       while True :

              myGroup.update()

              myGroup.draw(screen)

              pygame.display.update()

       當(dāng)然Group的性質(zhì)是遞歸的,每個Group可以有多個子Group,形成一棵樹或者是一個森林,當(dāng)調(diào)用根Group的函數(shù)時,它會將所有它的子孫的函數(shù)全部訪問到,這樣一來只要我們原先將所有的游戲元素的關(guān)系用一棵樹的形式建立起來,這樣每次更新或者渲染都只需要對根結(jié)點(diǎn)進(jìn)行操作了。

       繼續(xù)舉例說明:

       Root = pygame.sprite.Group()

       Son1 = pygame.sprite.Group()

       Son2 = pygame.sprite.Group()

       Son1.add(RenderObject([0]))

       Son1.add(RenderObject([1]))

       Son2.add(Player([13]))

       Son2.add(Animation([2,12]))

       Root.add(Son1)

       Root.add(Son2)

      

       while True :

              Root.update()

              Root.draw(screen)

              pygame.display.update()

       這段代碼將所有的游戲元素(兩個普通物體和兩個Player)組織成一棵樹,并且通過Root這個Group來管理所有的游戲元素的更新以及繪制(為了描述方便,主循環(huán)中將事件處理這一部分暫時去掉了)。

       這樣就又帶來了一個問題,游戲中的元素往往是很多的,比如有100只野怪,那么上面的代碼必然會出現(xiàn)至少100個類似XXX.add(Monster([num]))的代碼,一來看起來很別扭,二來不好維護(hù),一旦需要變更一些關(guān)系就要大幅度修改代碼,這個是不可取的。

于是我們還是學(xué)習(xí)上一節(jié)講到的將數(shù)據(jù)寫到文件中,因?yàn)檫@里的數(shù)據(jù)是以樹狀結(jié)構(gòu)呈現(xiàn)的,所以數(shù)據(jù)的組織我借用了XML的文件格式(語法稍微有些不同,這樣寫是為了省去一些不必要的操作),以下是其中一段元素的組織形式:

<Group name=gameMgr selfdata=(-1,-1) pos=(0,0)>

       <Group name=loginWnd selfdata=(-1,-1) pos=(0,0)>

              <Animation name=cloud selfdata=(3,12) pos=(0,0)>

              </Animation>

              <Picture   name=title selfdata=(0,0)  pos=(20,80)>

              </Picture>

              <Menu      name=menu  selfdata=(1,1)  pos=(50,120)>

              </Menu>

       </Group>

</Group>

每一對<>之間表示一個游戲元素,第一個字段是當(dāng)前元素的類名,便于創(chuàng)建的時候根據(jù)類名來聲明類的實(shí)例;第二個字段name是當(dāng)前實(shí)例的唯一標(biāo)識;第三個字段imageidx記錄了當(dāng)前元素的SurfaceRenderObject.images[]中的始末索引;第四個字段pos表示在創(chuàng)建這個類的實(shí)例的時候該image在屏幕的左上角坐標(biāo)。每一對<></>之間的元素是當(dāng)前元素的兒子,這樣一來,最外層的表示的就是Root根結(jié)點(diǎn),層層之間建立父子關(guān)系就成了一棵樹。

       接下來就是需要寫一個Python模塊用于對當(dāng)前的文件進(jìn)行解析,將所有的游戲元素從文件中讀取并且保存到一個遞歸的列表中。

       所謂遞歸的列表其實(shí)就是樹形列表,我們需要自定義一個這樣的類,每個類的實(shí)例表示的是樹形列表的一個結(jié)點(diǎn),那么每個結(jié)點(diǎn)保存的信息有當(dāng)前結(jié)點(diǎn)的數(shù)據(jù)域data,當(dāng)前結(jié)點(diǎn)的孩子結(jié)點(diǎn)的集合sonlist,它又是一個列表,并且保存當(dāng)前結(jié)點(diǎn)的父親結(jié)點(diǎn)的指針以便回溯。并且分別給它們一個默認(rèn)值,每個結(jié)點(diǎn)的父親結(jié)點(diǎn)默認(rèn)為None,也就是C語言中的NULL,表示的是空指針。類的實(shí)現(xiàn)如下:

class myTree :

    def __init__(self, data) :

        self.data    = data

        self.sonlist = []

        self.parent  = None

    def add(self, mytree) :

        mytree.parent = self

        self.sonlist.append(mytree)

 

    def output(self) :

        print self.data

        for xp in self.sonlist :

            xp.output()

添加兩個成員函數(shù)addoutput,add是為了添加兒子結(jié)點(diǎn),output是用來測試用的。

       有了以上的樹形列表,我們就可以寫自己的文件讀取器了,我把它取名為sXMLReadersimilar with XML),原因是和XML還是不盡相同的。

class sXMLReader :

def __init__(self, filename) :

       do_init()

def parse(self, string) :

       do_parse()

def next(self, nowline) :

       next_line()

do_init()主要做三件事情,讀取文件并把所有的行保存到self.filelist中,然后對每一行進(jìn)行一個預(yù)處理(主要是去掉串前后的空格和Tab還有回車等沒用的字符),最后進(jìn)行遞歸的訪問next函數(shù)進(jìn)行讀行并且建立關(guān)系樹。

self.root = myTree([])

self.nowroot = self.root

self.next(0)

首先建立一個空的根結(jié)點(diǎn)root,然后將當(dāng)前結(jié)點(diǎn)指針nowroot指向它,self.next(0)表示當(dāng)前訪問第0行,next函數(shù)的操作比較簡單,如下:

def next(self, nowline) :

if nowline == len(self.filelist) :

return

       process_this_line()

if matchPre :

self.nowroot = self.nowroot.parent

self.next(nowline+1)

else :

son = myTree(nownode)

self.nowroot.add(son)

self.nowroot = son

self.next(nowline+1)

       首先判斷當(dāng)前行是不是越界,如果越界說明無需訪問。否則處理這一行的文字內(nèi)容,這是由process_this_line()來完成的,要根據(jù)你自己設(shè)定的語法來處理,就不再累述了。最后一部分才是關(guān)鍵,matchPre用于判斷當(dāng)前這一行是不是和前面某一行進(jìn)行匹配,如果匹配成功(也就是說當(dāng)前行是類似</XXX>的形式),那么nowroot的指針指向它的parent,然后繼續(xù)訪問下一行;否則,生成一個新的結(jié)點(diǎn),并且把這個結(jié)點(diǎn)添加到當(dāng)前的nowroot結(jié)點(diǎn)中,然后更新nowroot為這個新加入的結(jié)點(diǎn),繼續(xù)訪問下一行。其實(shí)整個過程就是一個棧,遇到<>好比入棧,遇到</>就好比出棧。

       文件讀取寫完后,我們只需要調(diào)用:

gameItem = sXMLReader('ctrl_config.sxml')

       gameItem.root 就保存了游戲元素樹的根結(jié)點(diǎn),通過遞歸訪問就可以得到所有的游戲?qū)傩?,利?/span>GroupSprite將所有游戲元素構(gòu)造出來即可,具體參見以下代碼:

def CreateGameItem(node) :

    group = None

    if node.classname() == 'Group':

        group = pygame.sprite.Group()

    else :

        classname = node.classname()

        selflist = node.find('selfdata')

        render = renderobj.CreateClassByName(classname, selflist)

        render.setpos(int(node.find('pos')[0]), int(node.find('pos')[1]))

        return render

    for son in node.sonlist :

        group.add( CreateGameItem(son) )

return group

       根據(jù)node.classname()得到當(dāng)前結(jié)點(diǎn)是容器類還是普通的Sprite類,如果不是容器那么設(shè)置相關(guān)屬性,然后返回當(dāng)前結(jié)點(diǎn)信息;如果是容器類則創(chuàng)建一個Group并且遍歷它的子結(jié)點(diǎn),將所有子結(jié)點(diǎn)加入到當(dāng)前容器中。遍歷完畢后這棵樹就創(chuàng)建完畢了。(未完待續(xù))

posted on 2011-04-26 01:07 英雄哪里出來 閱讀(3793) 評論(0)  編輯 收藏 引用 所屬分類: Pygame

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            午夜精品理论片| 久久久久一区二区三区四区| 欧美国产精品日韩| 亚洲国产精品www| 亚洲高清在线观看| 蜜桃av久久久亚洲精品| 亚洲精品麻豆| 一区二区国产日产| 国产亚洲欧美aaaa| 欧美成人精品1314www| 欧美成人精品1314www| 一区二区三区三区在线| 国产精品99久久99久久久二8 | 久久久中精品2020中文| 亚洲第一页中文字幕| 亚洲欧洲在线一区| 国产精品黄页免费高清在线观看| 亚洲欧美制服另类日韩| 欧美在线观看你懂的| 亚洲精品乱码久久久久久蜜桃91| 亚洲精品美女久久久久| 国产精品网站在线播放| 欧美成人免费全部观看天天性色| 欧美日韩免费看| 久久久久久亚洲精品中文字幕| 久久躁日日躁aaaaxxxx| 亚洲天堂av综合网| 久久久久综合网| 亚洲一二三级电影| 久热精品视频在线免费观看| 亚洲一区国产精品| 久久综合色8888| 欧美一区二区| 欧美精品97| 久久性色av| 国产精品福利网| 欧美激情第1页| 国产日韩一级二级三级| 亚洲精品自在久久| 一区久久精品| 性欧美videos另类喷潮| 亚洲乱码一区二区| 久久中文精品| 久久久激情视频| 国产精品乱码久久久久久| 亚洲国产精品成人va在线观看| 国产午夜亚洲精品不卡| 一本色道久久综合狠狠躁的推荐| 亚洲激情视频在线观看| 午夜精品av| 午夜在线成人av| 国产精品国产三级国产普通话蜜臀| 欧美成人精品在线观看| 国模叶桐国产精品一区| 亚洲一级特黄| 亚洲欧美精品伊人久久| 欧美日本在线视频| 亚洲黄色视屏| 亚洲人成人一区二区三区| 久久综合伊人| 欧美jizz19hd性欧美| 伊人久久成人| 老司机67194精品线观看| 久久人人爽人人| 国产主播一区二区三区| 性欧美xxxx大乳国产app| 久久精品1区| 国产一二三精品| 欧美一区免费视频| 久久亚洲综合网| 精品电影一区| 蜜桃久久av一区| 亚洲第一偷拍| 一本大道久久精品懂色aⅴ | 午夜精品www| 欧美在线观看视频| 国产伊人精品| 久久亚洲高清| 亚洲经典在线| 亚洲影视综合| 国产日韩在线看片| 久久久综合网| 亚洲国产视频一区| 亚洲一级在线| 国产一区二区三区四区五区美女 | 亚洲福利视频在线| 一本色道久久综合亚洲精品小说| 欧美日韩国产bt| 亚洲一区二区三区四区五区午夜 | 亚洲国产成人久久综合| 欧美久久影院| 亚洲一区视频在线| 久久久久久亚洲精品杨幂换脸| 精品69视频一区二区三区| 欧美aⅴ一区二区三区视频| 亚洲巨乳在线| 久久久久9999亚洲精品| 亚洲第一网站免费视频| 欧美日韩一区二| 久久精品国产欧美亚洲人人爽| 亚洲激情国产精品| 香蕉久久夜色精品国产| 亚洲国产女人aaa毛片在线| 欧美日韩在线观看一区二区三区| 午夜综合激情| 亚洲精品中文字幕在线观看| 久久九九有精品国产23| 999亚洲国产精| 国产一区二区福利| 欧美日韩中文字幕日韩欧美| 久久精品国产久精国产爱| 99re6这里只有精品视频在线观看| 久久精品国产久精国产思思| 99国内精品久久| 黄色一区二区在线| 国产精品视频yy9099| 欧美激情久久久久久| 欧美在线一二三| 中文一区字幕| 亚洲日本乱码在线观看| 免费欧美高清视频| 久久精品国产精品亚洲精品| 夜夜嗨av一区二区三区网页| 136国产福利精品导航| 国产精自产拍久久久久久| 欧美日韩一级大片网址| 欧美α欧美αv大片| 久久久久久一区| 欧美一区二区私人影院日本| 99精品视频一区| 亚洲日本在线视频观看| 欧美激情一区二区三区在线| 欧美中日韩免费视频| 亚洲欧美激情四射在线日 | 在线一区二区三区做爰视频网站| 亚洲成人在线免费| 国产综合色一区二区三区 | 欧美不卡高清| 牛夜精品久久久久久久99黑人| 久久精品五月| 欧美一区二区免费视频| 午夜一级久久| 午夜精品美女自拍福到在线| 亚洲一区二区三区色| 亚洲一区三区电影在线观看| 亚洲视频一二三| 亚洲香蕉视频| 亚洲欧美日韩国产成人精品影院| 亚洲神马久久| 亚洲欧美日韩成人| 欧美中文在线免费| 久久综合伊人77777尤物| 久久亚洲欧洲| 欧美高潮视频| 欧美午夜视频网站| 国产精品麻豆va在线播放| 国产精品入口66mio| 国产欧美精品日韩精品| 激情成人在线视频| 亚洲欧洲一区二区天堂久久 | 亚洲日产国产精品| 这里只有精品视频| 亚洲一区二区在线免费观看视频| 午夜精品久久久久久久久久久久| 欧美一区二区三区视频| 久久久久久久成人| 亚洲福利视频一区二区| 99精品视频一区| 性欧美暴力猛交另类hd| 久久久久综合网| 欧美伦理91| 国产午夜精品视频| 亚洲欧洲综合另类| 一区二区三区四区蜜桃| 欧美在线一级va免费观看| 免费在线观看一区二区| 亚洲精品日韩在线| 亚洲欧美日韩爽爽影院| 蜜桃av久久久亚洲精品| 国产精品成人观看视频国产奇米| 国产亚洲aⅴaaaaaa毛片| 亚洲精品一区久久久久久| 欧美一区二区三区免费大片| 久久综合伊人77777麻豆| 亚洲毛片在线看| 欧美怡红院视频| 欧美日韩激情小视频| 韩国精品在线观看| 亚洲一二三区精品| 欧美韩国日本一区| 亚洲欧美资源在线| 欧美韩日高清| 激情亚洲一区二区三区四区| 一区二区三区高清视频在线观看| 欧美自拍偷拍| 正在播放亚洲一区| 欧美大片免费观看| 在线精品在线| 久久免费偷拍视频| 亚洲影音先锋|