游戲發(fā)展早期,C甚至匯編當(dāng)?shù)?;?fù)雜的游戲邏輯(玩家操作,、攻擊技能、傷害判定,、各種特殊的技能/狀態(tài)邏輯,,等等等等)想要有條不紊的管理起來(lái)、隨時(shí)間流逝均勻可控的運(yùn)作,、同時(shí)又要盡量?jī)?yōu)化性能(比如其它答案談到的“圖形顯示優(yōu)化”)…… 這難度,,飛上天了吧? 因此,,就有了“精靈”抽象:游戲里一切能感知時(shí)間流逝,、具有坐標(biāo)位置的,都是精靈,。 你看,,一下子抓住了兩個(gè)根本:一、有坐標(biāo)信息,;二,、能感知時(shí)間流逝。 一旦抓住這兩個(gè)根本,,事情就容易起來(lái)了,。 我們可以設(shè)計(jì)一個(gè)定時(shí)器,周期性的調(diào)用和精靈綁定的處理函數(shù)(相當(dāng)于C++的虛函數(shù),,接受的傳入?yún)?shù)是interval)——實(shí)際上,,這個(gè)處理函數(shù)是一個(gè)dispatcher,它負(fù)責(zé)轉(zhuǎn)調(diào)用我們寫(xiě)的一切動(dòng)畫(huà)以及碰撞判定等邏輯的處理函數(shù),。 所有這些函數(shù)都要接受interval參數(shù),,比如讓精靈按貝塞爾曲線(xiàn)運(yùn)動(dòng)的函數(shù)就是用interval乘以運(yùn)行速率、然后改寫(xiě)精靈的坐標(biāo)信息,;同樣的,,動(dòng)畫(huà)呢,就是按照interval的節(jié)律縮放扭曲圖片或者改變它的顏色(或者基于interval把一組圖片換來(lái)?yè)Q去,,從而實(shí)現(xiàn)走路,、放大招等效果)。 注意精靈是可以沒(méi)有對(duì)應(yīng)的圖片的,,比如我們要在進(jìn)門(mén)處放個(gè)陷阱,,那就是一個(gè)和門(mén)口坐標(biāo)重疊的、不可見(jiàn)的“觸發(fā)器trigger”,當(dāng)碰撞檢測(cè)發(fā)現(xiàn)游戲物體和這個(gè)“觸發(fā)器精靈”坐標(biāo)重合時(shí),,就會(huì)調(diào)用對(duì)應(yīng)的trigger,。 換句話(huà)說(shuō),這是用C甚至匯編實(shí)現(xiàn)的一個(gè)原始而精巧的繼承體系,;它的根是“精靈”這個(gè)基類(lèi),,提供坐標(biāo)這個(gè)公開(kāi)數(shù)據(jù)成員和dispatcher時(shí)鐘信息的接口;然后是“支持碰撞檢測(cè)以及提供接受碰撞事件并加以處理的接口”的繼承類(lèi),,和“支持動(dòng)畫(huà)”的繼承類(lèi)以及其它各種繼承類(lèi),。 至于為什么叫“精靈”,大概是因?yàn)樗皇悄堋案兄庇形恢?,卻未必有實(shí)體吧——在西方傳說(shuō)里,,“精靈sprite”本來(lái)就是有魔力的、介于虛實(shí)之間的幻想角色,,如火之精靈,、光之精靈之類(lèi),。 一旦有了這個(gè)抽象,,那么無(wú)論聲音還是圖像,無(wú)論是軟件還是硬件優(yōu)化,,就都要以精靈為中心了:負(fù)責(zé)游戲性循著精靈這條線(xiàn)更改角色位置,、檢測(cè)碰撞、觸發(fā)相關(guān)處理邏輯,;負(fù)責(zé)畫(huà)面的也循著精靈這條線(xiàn),,更新屏幕顯示、優(yōu)化圖形性能,;負(fù)責(zé)聲音的呢,,同樣循著精靈這條線(xiàn),根據(jù)距離畫(huà)面焦點(diǎn)的遠(yuǎn)近改變不同聲源的聲音大小,、以及考慮是否應(yīng)該添加濾波/回音等效果,;負(fù)責(zé)劇情的同樣可以把文字/過(guò)場(chǎng)動(dòng)畫(huà)/事件觸發(fā)等綁到精靈上,設(shè)定觸發(fā)條件即可,,等等等等,。 總之,每個(gè)人只關(guān)注自己需要關(guān)注的那個(gè)側(cè)面,,完全可以忽視其它東西的存在,。這樣不管游戲多么復(fù)雜、世界多么宏大,,一切都可以井井有條的解決,。 注意這個(gè)先后順序:程序員設(shè)計(jì)的東西,肯定是以便利程序員自己為最優(yōu)先,。 先有了一個(gè)最合理最高效的架構(gòu),,然后一切就可以基于這個(gè)架構(gòu)提供方便,。 就好像是計(jì)算機(jī)3D圖形先把3D真實(shí)感圖形渲染以面片為中心、然后硬件設(shè)計(jì)(顯卡/GPU)才提供了迎合這個(gè)抽象的渲染體系,;并不是硬件先弄出來(lái)面片,,然后程序員們一陣焦頭爛額手忙腳亂的往面片遷移……肯定不是這個(gè)過(guò)程,對(duì)吧,。 換句話(huà)說(shuō),,硬件支持可以證明一種做法的流行——流行到通過(guò)硬件管線(xiàn)直接支持——卻幾乎不可能是這種做法的來(lái)源(都出硬件支持了,可想而知這種設(shè)計(jì)在硬件出來(lái)之前有多流行),。 另一個(gè),,因?yàn)榇蠖鄶?shù)人只負(fù)責(zé)自己那一塊,很容易局限于“在我的領(lǐng)域,,XX事是怎么怎么來(lái)的”,。這大概就是高票二位大佬掐架的原因。 但游戲開(kāi)發(fā)是個(gè)很復(fù)雜的工作,,不可能遷就于某個(gè)單一方面,。 比如在3D游戲邏輯開(kāi)發(fā)里就沒(méi)有“面片”,那是建模和渲染玩的,,不會(huì)“侵染”游戲邏輯開(kāi)發(fā)過(guò)程,,對(duì)吧。 同樣的,,2D游戲開(kāi)發(fā),,精靈是從軟件架構(gòu)來(lái)的;但這個(gè)架構(gòu)在設(shè)計(jì)時(shí),,一定綜合考慮了圖像渲染,、游戲邏輯等諸多方面,最終才決定“同時(shí)向圖像組和游戲邏輯組開(kāi)放sprite這個(gè)概念”——也只有站在總體架構(gòu)的角度,,sprite這個(gè)術(shù)語(yǔ)才是貼切的:如果是圖像處理方單獨(dú)決定的,,那他們肯定不會(huì)叫它sprite。這個(gè)詞和他們做的事(合成活動(dòng)圖片到背景)有半點(diǎn)關(guān)系嗎,? 當(dāng)然,,因?yàn)檎Z(yǔ)言層面沒(méi)有面向?qū)ο蟮闹С郑@個(gè)設(shè)計(jì)只能通過(guò)以強(qiáng)制類(lèi)型變換為核心的各種奇技淫巧實(shí)現(xiàn),。 到了面向?qū)ο髸r(shí)代后,,這套體系就沿用下來(lái)了;后來(lái)大概是為了區(qū)分吧,,2D游戲仍然沿用精靈這個(gè)術(shù)語(yǔ),;而3D游戲就改名叫GameObject,不再使用“精靈”這個(gè)說(shuō)法(但一切GameObject仍然有坐標(biāo)有transform,哪怕它只是個(gè)計(jì)分牌,、只關(guān)心屏幕坐標(biāo)),。 正因此,當(dāng)年C++等面向?qū)ο笳Z(yǔ)言火爆時(shí),,游戲界反而不怎么感冒,。因?yàn)檫@些都已經(jīng)在C語(yǔ)言里面有了完美的解決體系,面向?qū)ο笳Z(yǔ)言搞的那么一堆private啦繼承啦之類(lèi)約束反而會(huì)打破這個(gè)體系,,把既有體系推倒重來(lái),、然后再把附著于既有體系的無(wú)數(shù)現(xiàn)有邏輯重寫(xiě)一遍,這實(shí)在太麻煩了,。所以……C++,,從游戲行業(yè)滾開(kāi)! |
|
來(lái)自: 半佛肉夾饃 > 《待分類(lèi)》