一直想學lua,學它如何與C結合來做邏輯,因此找了雲風的一份代碼來研究。這份代碼是個框架庫,叫ejoy2d,據雲風的博客說,他們最新的手機遊戲用的就是這套框架,因此實用性應該很強,雖然我不是學遊戲的,但應該也能學習到不少。
話很少說,開始看源碼。html
框架支持windows, linux, ios三種環境,這裏只看windows的,用的是mingw。linux
程序入口main
在 window.c:ios
ejoy2d_win_init
用來初始化ejoy2dejoy2d_win_init
定義在winfw.c中,一共就下面這幾步:git
startscript
先看看create_game
到底作了啥:github
再看看加載的 startscript
是個啥:windows
local path, script = ...require("ejoy2d.framework").WorkDir = ''assert(script, 'I need a script name')path = string.match(path,[[(.*)\[^\]*$]])package.path = path .. [[\?.lua;]] .. path .. [[\?\init.lua;.\?.lua;.\?\init.lua]]local f = assert(loadfile(script))f(script)
由於最後生成的ej2d.exe調用時是 ej2d.exe xxx.lua
,因此根據上面的代碼,那麼path
中就會保存ej2d.exe
的所在路徑,而script則保存xxx.lua
,因此上面這段腳本最後會設置package的搜索路徑(這裏爲後面自定義腳本加載ejoy2d的lua庫作好鋪墊),同時執行給定的腳本。框架
看到這裏,應該能明白上面第3步裏其實就是執行的這段腳本,至於爲啥不用dofile來加載startscript
,是想在這裏打印錯誤信息的緣由。函數
行,到這兒create_game
看完了,再回到ejoy2d_win_init
接着往下看。學習
screen_init
,代碼裏很簡單,就是初始化好opengl的viewport。字體
ejoy2d_game_start
這個函數看代碼,應該是依次調了 EJOY_INIT
,EJOY2D_UPDATE
,EJOY2D_DRAWFRAME
這三個函數,不過這裏用到了LUA_REGISTRYINDEX
這個東西,lua我不熟,因此看看PIL後又結合網上其餘人的說法,這是lua的「註冊表」,這個東西其實也是一張表,可是一張全局的表,能夠經過僞索引
來搜索,貌似是比其餘的方式快?
好的,問題來了:挖掘機技術哪家。。。打住,不是這個,而是EJOY_INIT
,EJOY2D_UPDATE
,EJOY2D_DRAWFRAME
這三個函數是從哪兒來的,源碼裏沒有找到對應的實現,沒辦法,只能看看example了。
略過 examples/ex01.lua 前面的一堆代碼,咱們看到這個:
local game = {}function game.update()endfunction game.drawframe() -- use shader.draw to draw a polygon to screen (for debug use) shader.draw(TEXID, { 88, 0, 88, 45, 147, 45, 147, 0, -- texture coord -958, -580, -958, 860, 918, 860, 918, -580, -- screen coord, 16x pixel, (0,0) is the center of screen })endfunction game.touch(what, x, y)endej.start(game)
這裏定義了一個game對象,實現了三個方法:update, drawframe, touch,最後做爲參數傳入了ej.start裏。等等,前兩個函數好像跟上面的有關係。看看ej.start(game)
都幹了些什麼。
打開 ejoy2d/init.lua:
function fw.EJOY2D_INIT() shader.init()endfunction ejoy2d.start(callback) fw.EJOY2D_UPDATE = assert(callback.update) fw.EJOY2D_DRAWFRAME = assert(callback.drawframe) fw.EJOY2D_TOUCH = function(x,y,what,id) return callback.touch(touch[what],x,y,id) end fw.EJOY2D_GESTURE = function(what, x1, y1, x2, y2, state) return callback.gesture(gesture[what], x1, y1, x2, y2, state) end fw.inject()end
哈,這裏把剛纔game中定義的三個方法都放到對應的EJOY2D_XX裏了,同時調用inject函數,完成了lua函數的注入。此時再回到ejoy2d_game_start中,一切合理了。