RPG Maker的引擎分析(一)(二)

來源:互聯網
上載者:User

寫在最前:

本系列教程原創著作權歸bsucat所有,本文只為收藏及共用。轉載請按如下方式標明原創作者出處,以示尊重!!

作者:bsucat

原文:http://blog.csdn.net/bsucat/archive/2010/03/01/5334619.aspx

 

目錄

 

0.    前言

1.    RM的運作原理

  1.1         概覽

  1.2         想象中的結構

2.    映像模組

  2.1         10s的秘密

  2.2         效能與偏見

  2.3         繪製流水線

 (待續)

 

 

0.    前言

什麼人適合閱讀這篇文章?

這篇文章涉及到的知識範疇,可能讓大家感到陌生。確實,這篇文章不太適合新手閱讀,對於大部分人來說這篇文章所講的內容是沒有用的。但是對想要瞭解RM內部運行原理的朋友來說,這篇文章的內容應該能值得大家一起分享、探討。

這篇文章裡講到的RGSS版本?

由於RM並不是一個公開原始碼的商業軟體,各位也對RM的反編譯很反感( 我也沒那個能力),所以這篇文章的內容,只是我憑個人經驗對RM底層引擎的一個猜測性的分析。如果有不對的地方,請大家務必諒解,煩請糾正。

另外,由於我個人對RMXP版本比較熟悉,所以這篇文章主要分析的是RGSS而不是RGSS2 。RGSS2較之RGSS,在底層實現裡並無太大的變化,只是更加規範,並增加了部分功能而已。所以這篇文章的大部分內容,對於RGSS2也是適用的。

 

1.    RM的運作原理

 

1.1概覽

可能有不少人詬病RM有這樣那樣的缺點,但是RPG Maker XP確實是一款設計得非常現代的2D遊戲製作工具。從組織圖來講,RMXP使用的是非常流行的遊戲內容和遊戲引擎分離的結構,遊戲邏輯靈活地獨立成一個模組,大概如所示。

 

 

 
不要覺得這個很簡單哦,實際上要設計好一個引擎上的指令碼系統並非易事,還好RM已經幫我們做到了。下面看看RM是怎麼實現的。

 

一般來說,指令碼有兩種作用方式,一種是宿主語言(比如C)載入指令碼處理部分內容,但控制權仍在宿主語言,另一種是則是宿主載入指令碼後失去控制權,控制權在指令碼語言。RM很明顯是屬於後者,RM在做了一系列初始化的工作後,調用ruby的C API(比如ruby_run?我對ruby的C API並不熟悉,只是猜測)來讓ruby解譯器取得了控制權。所以我們能感受到的整個遊戲的運行過程,就可以完全由RGSS來控制了。

RGSS在整個RM的軟體層次裡,已經屬於最進階的層次。如所示。

 
 

在指令碼層之下的,便是遊戲的引擎。RM通過擴充ruby庫,將引擎的功能抽象化,並封裝了部分操作。使用者並沒有必要關心底層引擎究竟是怎麼啟動並執行,比如怎麼使用DirectX ,怎麼管理記憶體,怎麼處理windows的訊息迴圈等等。只要使用者知道怎麼使用RGSS,便可順利地使用引擎做出自己的遊戲。

 

這一部分被封裝好的內容,是對使用者透明的,通常情況下你無需瞭解。但是對於求知慾很重的我們來說,今天要探討的,恰恰就是這部分內容了J。

 

1.2 想象中的結構

整個遊戲的運行,在預設情況下,至少有以下三個檔案存在,那就是:Game.exe,Game.ini和rgssxxxx.dll。趕快來猜猜,裡面都有些什麼吧(不是純粹的瞎猜哦)。

 

Game.exe是遊戲的主程式,Game.ini是設定檔,這個毫無疑問。Game.exe在一開始啟動並執行時候,就從Game.ini裡讀取了相關的資訊,比如視窗的標題是什麼,一會動態載入的dll檔案的名字(就是rgssxxxx.dll),以及哪裡去找ruby解譯器將要啟動並執行指令碼(比如預設的Script.rxdata)等等內容。解析ini檔案很簡單,調用windows提供的ini檔案處理API就行了,所以我估計RM也是這麼乾的(不然呢?!)。

Game.exe本身並沒有多少真正和遊戲引擎相關的內容,甚至沒有windows的訊息迴圈(這個後面會分析),它更像是一個“傀儡”。而操縱它的幕後黑手便是rgssxxxx.dll。在這個dll裡,封裝了一個用DirectX實現的遊戲引擎。Game.exe通過調用它提供的API,最終實現了我們想要的一切(好吧,也許你還想要得更多……)。

 

 

在一個遊戲程式裡,一般來說,大概流程如下:

 

這個迴圈,在RGSS的預設指令碼裡,也有所體現:

 

# 主迴圈<br />loop do<br /> # 重新整理遊戲畫面<br /> Graphics.update<br /> # 重新整理輸入資訊<br /> Input.update<br /> # 重新整理畫面<br /> update<br /> # 如果畫面被切換就中斷迴圈<br /> if $scene != self<br /> break<br /> end<br />end<br /> # 主迴圈<br /> loop do<br /> # 重新整理遊戲畫面<br /> Graphics.update<br /> # 重新整理輸入資訊<br /> Input.update<br /> # 重新整理畫面<br /> update<br /> # 如果畫面被切換就中斷迴圈<br /> if $scene != self<br /> break<br /> end<br /> end  

 

在這個迴圈裡,update這一句,擔負著的便是遊戲邏輯處理的任務,Graphics.update從字面上看,明顯是遊戲畫面的處理(實際上有更多內容……),那麼視窗訊息的處理跑到哪裡去了呢?

 

2.

映像模組

 

 

2.1 10s的秘密

假如你有自己寫過一個差勁的尋路指令碼,導致遊戲視窗彈出“指令碼已備份”的提示欄,相信你對RGSS每10s至少要調用一次Graphics.update的限制並不陌生。有的人認為這個10s限制非常的沒有道理,是RM的效能瓶頸。但經過我的仔細思考,事實並非如此。

熟悉windows編程的朋友們想必都知道,windows程式都是訊息驅動型的,假如沒有訊息迴圈的更新,整個程式必定會陷入卡死的狀態。前面我說過,在RM的Game.exe程式運行時,ruby解譯器佔用了整個程式的控制權。我們姑且假設在Game.exe中,一旦呼叫指令碼,便無法返回。這樣,視窗訊息更新的任務,就只能交給指令碼了。

假設指令碼中不調用視窗訊息的更新,整個程式必定陷入卡死狀態,所以為了防止使用者寫出的糟糕指令碼導致程式運行過慢而無法終止程式,很有必要加上只要10s沒有調用訊息更新,則自動終止程式的限制。

所以,沒錯,消失的視窗訊息處理,實際上就封裝在了Graphics.update裡面。

 

所以Graphics.update的功能,現在看起來就像是這樣了:視窗訊息處理+渲染映像。但是,僅僅是這樣嗎?

不知道你有沒有注意到,Graphics.frame_rate和Graphics.frame_count這兩個Graphics模組的屬性值,這說明RM是有幀速控制的。而從兩個屬性在RM文檔裡的說明來分析,幀速的控制很明顯封裝在了Graphics.update裡來處理(至於什麼是幀速控制?!這個可不是什麼新鮮的東西,請自行搜尋“regulating frame rate”)。

目前我們已知Graphics.update包含了視窗訊息處理、幀速控制和映像渲染,而且它實際上可能還包含了更多東西(修改標題什麼的?!天知道?!),不過那些我們現在都不關心了。接下來我想仔細說說的,就是映像渲染。

 

2.2 效能與偏見

RM的映像引擎用的是DirectDraw。這一點請不用懷疑,這可能是這篇文章中我最敢發誓是正確的觀點……

不過rgssxxxx.dll並沒有直接連結DirectDraw的庫檔案,而是在運行時載入的。這裡我順便提一下,微軟從DirectX 8開始就不提供DirectDraw的文檔支援了,而在之後,更是直接拋棄了DirectDraw 。但是,DirectX是一個COM組件,所以即使微軟不再更新ddraw,它還是可以歡暢地在任何相容它的新版本裡啟動並執行。

使用RM的人常常會有兩個偏見。第一個是認為Ruby的解譯器相對較慢,導致效能不佳;第二個則是認為DirectDraw是一個已經夭折的產品,基於它的RM引擎,必然效能表現不佳。

關於第一個偏見,我對ruby解譯器速度的相關測試並不瞭解,但是就我個人使用的感受來說,一個設計得良好的RGSS指令碼結構,不可能會慢到哪裡去。很多人寫指令碼的時候並不考慮效能的開銷,每一幀裡都要做大量無用的迴圈檢查,累得ruby解譯器氣喘籲籲(可憐的Ruby娘!J),這才是真正拖慢ruby解譯器速度的元兇。

好吧,下面回到我們映像模組的正題上來,也就是第二個關於DirectDraw的偏見。固然,微軟已經徹底地拋棄了DirectDraw,而DirectDraw也只能算一個半成品而已但這並不意味著DirectDraw就是一個低效能的東西。實際上,DirectDraw能滿足製作2D畫面的絕大部分需求,而且效率很不錯。

可能有人心中會有疑問,既然DirectDraw能滿足2D遊戲的開發,為什麼會有用Direct3D來開發的2D引擎?前面我說過了,DirectDraw只是一個半成品,很多功能微軟並沒有做,需要開發人員自己去擴充,這無疑增加了開發人員的使用難度。而之前我在國外某論壇上看洋人們討論過這個問題,最後眾洋人得出的結論是現在眾多的硬體廠商在已經放棄產品對2D加速,也就是Blitter的支援(沒錯,Bitmap類裡的blit興許就是調用了它),而3D加速幾乎是現在每塊顯卡都能支援的(我也不知道這結論是否屬實,反正是洋人們說的!),所以Direct3D是更明智的選擇……

話說回來,以上兩點絕對不是導致你的遊戲運行緩慢的效能瓶頸。當出現遊戲運行遲緩的情況時,還是首先檢查下你自己都寫了些什麼低效率的指令碼吧,而不是一味地責怪RM愚笨!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.