Quick-3.3 開發筆記

weixin_33978044發表於2018-05-07

由於Cocos2d-x中使用的是C++,而C++對開發人員要求較高,逐漸的開發者開始將Cocos2d-x的C++介面轉換成了Lua介面,從而衍生出Cocos2d-lua的版本。而Quick是Cocos2d-lua的一個增強和擴充套件版本,它重寫了支援程式碼、解決了記憶體洩漏和只能使用全域性函式做回撥等問題。Quick能讓開發者使用Lua簡單易懂的指令碼來編寫遊戲,並大大提高了開發效率。

環境搭建

版本

  • Quick-3.3
  • SublimeText3

Quick框架

quick-cocos2d-x v3 是在 cocos2dx 3.x 的最新版本基礎之上,移植了原來 quick-cocos2d-x 的核心框架、強大的 player 、豐富的示例等,並增加更多新的功能。

$ git clone https://github.com/dualface/v3quick.git

Quick-3.3 原始碼目錄

4933701-55746847f3b4a480.png
系統目錄
  • build cocos2dx專案存放目錄
  • cocos cocos2dx主目錄核心程式碼存放位置
  • docsquick文件目錄
  • extension cocos擴充套件內容、GUI擴充套件庫
  • external 擴充套件內容,物理引擎第三方庫、Box2D和chipmunk、資料庫第三方庫、sqlite3、網路第三方庫、webp、websockets等
  • licenses 認證,引擎使用的各種許可證檔案
  • quick quick核心目錄,quick引擎程式碼
  • tools quick用作luabinding的工具
  • README.html 使用指南
  • setup_win.bat 搭建Windows開發環境的指令碼
  • VERSION 版本標識

Quick框架核心目錄

4933701-0bde06124eb6850c.png
quick目錄
  • bin quick工具指令碼,包括binding指令碼、加密指令碼等
  • cocos C++定義的常量與封裝的介面
  • framework quick框架核心目錄
  • lib quick類庫
  • player player的工程檔案
  • samples quick示例程式碼
  • templates quick專案模板
  • welcome player啟動介面程式碼

開發工具

QuickXDev是SublimeText開發quick-cocos2d-x的外掛,SublimeText配置QuickXDev外掛步驟:

  1. 下載之後解壓,並重新命名為QuickXDev。
  2. 把該資料夾放入到SublimeText的Packages目錄下Preferences->Browse Packages
  3. SublimeText設定 Preferences->Package Settings->QuickXDev->Settings – User
{
    "quick_cocos2dx_root": "D:\\quick-cocos2d-x",
    "date_format": "%Y-%m-%d %H:%M:%S",
    "author": "JunChow",
    "compile_scripts_key": ""
}

重點是配置Quick的根目錄"quick_cocos2dx_root": "D:\\quick-cocos2d-x",

模擬器

4933701-b84fb4efa6e33cf1.png
Player

quick-cocos2d-x 中帶有一個名為 Player 的工具,這個工具不但是一個功能完善的模擬器,可以在 Mac/Windows 桌面執行開發者的遊戲,還是一個功能齊備的開發工具入口。開發者啟動 Player 後,將可以完成下列任務:建立專案、開啟專案、編譯專案、檢視示例

  1. player 依賴一些特定的環境設定才能正常工作,Windows 平臺下執行 setup_win.bat。
  2. 啟動 player 後將看到以下畫面
  3. 建立專案,有兩種方式:命令列建立、通過 Player 建立

建立專案

# 建立一個test的專案
$ create_project.bat -p com.junchow.games.test
4933701-0afc98af376bcd65.png
建立專案

專案目錄結構

4933701-7a2a65835ed32275.png
專案目錄
  • debug.log 除錯日誌,即列印控制檯視窗輸出的日誌。
  • config.json 專案配置檔案
  • src 專案原始碼存放目錄
  • runtime 預編譯的執行時庫存放目錄
  • res 專案資源的存放目錄
  • frameworks cocos2d-x引擎核心程式碼及各平臺執行時資源

專案原始碼目錄結構

4933701-ebe5ec292af84da1.png
src專案原始碼目錄
  • app 專案工程介面等檔案,存放遊戲程式碼
  • cocos cocos引擎程式碼目錄
  • framework quick引擎核心
  • config.lua 專案工程配置檔案
  • main.lua 專案工程入口檔案

專案配置檔案 src/config.lua

-- 配置quick工程除錯資訊:0關閉,1列印少量除錯資訊,2列印標準除錯資訊
-- 0 - disable debug info, 1 - less debug info, 2 - verbose debug info
DEBUG = 1
-- 是否顯示模擬器左下角的FPS資訊
-- display FPS stats on screen
DEBUG_FPS = true
-- 是否每10秒列印一次記憶體資訊
-- dump memory info every 10 seconds
DEBUG_MEM = false
-- 是否載入已廢棄的API
-- load deprecated API
LOAD_DEPRECATED_API = false
-- 是否載入段程式碼的API
-- load shortcodes API
LOAD_SHORTCODES_API = true
-- 遊戲螢幕方向:landscape橫屏,portrait豎屏
-- screen orientation
CONFIG_SCREEN_ORIENTATION = "portrait"
-- 遊戲螢幕寬度:橫屏是時表示高度
-- design resolution
CONFIG_SCREEN_WIDTH  = 640
-- 遊戲螢幕高度:橫屏時表示寬度
CONFIG_SCREEN_HEIGHT = 960
-- 螢幕適配策略:
-- FIXED_WIDTH:保持傳入的設計解析度寬度不變,根據螢幕解析度修正設計解析度的高度。
-- FIXED_HEIGHT:保持傳入的設計解析度高度不變,根據螢幕解析度修正設計解析度的寬度。
-- FILL_ALL:保證設計區域某個方向鋪滿螢幕,另一方向可能超出螢幕或留有黑邊。
-- auto scale mode
CONFIG_SCREEN_AUTOSCALE = "FIXED_WIDTH"

解析度適配問題

市場上各種螢幕尺寸和解析度的移動裝置層出不窮,為了讓開發的專案能夠更好地適應不同的裝置,解析度適配尤為重要。

4933701-b891334ead13d673.png
常見手機解析度

Cocos中圖片顯示到螢幕有兩個邏輯過程,結合在一起影響最終的顯示效果。首先是將資源佈局到設計解析度,然後是將設計解析度佈局到螢幕。

4933701-767298608bb14121.jpg
解析度適配.jpg

設計解析度指config.lua檔案中設定的CONFIG_SCREEN_WIDTHCONFIG_SCREEN_HEIGHT,相當於參考解析度。確定了參考解析度才能得到圖片資源的縮放比率。

-- 圖片資源顯示到螢幕的縮放因子,由“背景圖片資源寬高/設計解析度寬高”得到。
cc.Director:getInstance():setContentScaleFactor(value)
  • 縮放因子 = 圖片資源高/設計解析度高
    保證了背景資源垂直方向在設計解析度範圍內的全部顯示,但水平方向上可能會溢位或留有黑邊。
4933701-2e6a13cf28d4a1fd.png
縮放因子=圖片資源高/設計解析度高
  • 縮放因子 = 圖片資源寬/設計解析度寬
    保證了背景資源的水平方向在設計解析度範圍內的全部顯示,但垂直方向上可能會超出遮蔽範圍或留有黑邊。
4933701-e911569925388ce4.png
縮放因子=圖片資源寬/設計解析度寬
-- 設定設計解析度寬高
setDesignResolutionSize(width, height, cc.ResolutionPolicy)
-- width 設計解析度寬度
-- height 設計解析度高度
-- cc.ResolutionPolicy 解析度適配策略,由config.lua中CONFIG_SCREEN_WIDTH、CONFIG_SCREEN_HEIGHT、CONFIG_SCREEN_AUTOSCALE來設定。

解析度適配的實現

橫屏的飛行遊戲,需要讓背景圖在高度上全部顯示,那麼寬度上必須會做出一些犧牲,即要麼被裁剪要麼留黑邊,當然黑邊可以通過將圖片寬度做的更寬來解決。

  1. 選擇1136x640的圖片資源,寬高比夠大,能確保在某些極端的解析度也能完整不留黑邊顯示。
  2. 設定src/config.lua螢幕相關引數
-- 遊戲螢幕方向:landscape橫屏,portrait豎屏
-- screen orientation
CONFIG_SCREEN_ORIENTATION = "landscape"
-- 遊戲螢幕寬度:橫屏是時表示高度
-- design resolution
CONFIG_SCREEN_WIDTH  = 480
-- 遊戲螢幕高度:橫屏時表示寬度
CONFIG_SCREEN_HEIGHT = 320
-- 螢幕適配策略
-- auto scale mode
CONFIG_SCREEN_AUTOSCALE = "FIXED_HEIGHT"
  1. src/app/MyApp.lua修改run()加入內容縮放因子
    4933701-921957f3eab0f047.png
    新增內容縮放因子
-- MyApp.lua
require("config")
require("cocos.init")
require("framework.init")

local MyApp = class("MyApp", cc.mvc.AppBase)

function MyApp:ctor()
    MyApp.super.ctor(self)
end

function MyApp:run()
    cc.FileUtils:getInstance():addSearchPath("res/")

    -- 新增內容縮放因子
    cc.Director:getInstance():setContentScaleFactor(640/CONFIG_SCREEN_HEIGHT)

    self:enterScene("MainScene")
end

return MyApp

專案主入口 src/main.lua

main.lua是Quick的預設入口,即專案啟動時,首先執行這個檔案。

function __G__TRACKBACK__(errorMessage)
    print("----------------------------------------")
    print("LUA ERROR: " .. tostring(errorMessage) .. "\n")
    print(debug.traceback("", 2))
    print("----------------------------------------")
end
-- 將自定義包路徑新增到package的所搜路徑中
package.path = package.path .. ";src/"
-- 設定圖片載入失敗時是否彈出訊息框
cc.FileUtils:getInstance():setPopupNotify(false)
-- 載入app.MyApp模組新建MyApp例項並執行
require("app.MyApp").new():run()

預設我的應用 src/app/MyApp.lua

-- 載入配置
require("config")
-- cocos框架初始化
require("cocos.init")
-- quick框架初始化
require("framework.init")

-- 定義類 MyApp
-- class()方法本身是quick框架中用於建立自定義lua類的函式,該函式在quick引擎的`quick/framework/functions.lua`中。
-- function class(classname, super)
-- classname 表示類名, super表示父類或建立物件例項的函式。
-- MyApp類是從cc.mvc.AppBase繼承而來
-- AppBase是Quick中自帶的一個MVC應用程式基礎類,此類為應用程式提供了邏輯控制上的功能,如進入場景、切換場景等。
local MyApp = class("MyApp", cc.mvc.AppBase)

-- MyApp:ctor()
-- 1. 相當於C++中的建構函式(constructor)以及初始化函式(init)
-- 2. 在ctor()中初始化遊戲資料
-- 3. 每次呼叫XXClass.new()建立物件例項時會自動執行ctor()
-- 4. 子類的ctor()中必須手動呼叫父類的建構函式,才能保證子類能繼承父類的屬性和方法。
function MyApp:ctor()
    MyApp.super.ctor(self)
end

function MyApp:run()
    -- 通過 addSearchPath()設定“資源搜尋路徑”
    cc.FileUtils:getInstance():addSearchPath("res/")
    -- 通過setContentScaleFactor()設定“內容縮放因子”
    cc.Director:getInstance():setContentScaleFactor(640/CONFIG_SCREEN_HEIGHT)
    -- MyApp繼承自AppBase,呼叫enterScene()進入名為MainScene的遊戲場景中
    self:enterScene("MainScene")
end

return MyApp
  1. ressrc目錄新增到檔案所搜路徑
cc.FileUtils:getInstance():addSearchPath("res/")
  1. 讀取config.lua載入Lua配置,並設定內容縮放因子,解決解析度適配問題。
cc.Director:getInstance():setContentScaleFactor(640/CONFIG_SCREEN_HEIGHT)
  1. 建立App物件,呼叫run(),執行並配置第一個進入的場景,預設為MainScence
self:enterScene("MainScene")

預設主場景 src/app/scenes/MainScene.lua

-- 使用 class() 函式建立了一個 MainScene 場景類
-- 與建立 MyApp 類不同的是,MainScene 類不是從基礎類繼承而來的,而是通過回撥函式建立出來的。
-- 因為 Scene 場景物件必須是 C++ 物件,而 C++物件是無法直接派生出 Lua 類的,所以只有用函式將其建立出來後再為其新增方法。
local MainScene = class("MainScene", function()
    -- display.newScene() :建立新場景並返回 Scene 場景物件
    -- quick中display模組封裝了絕大部分與顯示相關的功能,並負責根據 config.lua 中定義的解析度設定計算螢幕的設計解析度。
    -- display 模組提供了眾多方法和屬性,如建立層 display.newLayer,建立精靈 display.newSprite,恢復暫停切換場景等。
    return display.newScene("MainScene")
end)

-- MainScene 構造並初始化
function MainScene:ctor()
    -- 新增 UI 標籤,其作用是在螢幕正中間新增一個文字,並顯示到螢幕上。
    cc.ui.UILabel.new({UILabelType = 2, text = "Hello, World", size = 64})
        :align(display.CENTER, display.cx, display.cy)
        :addTo(self)
end

-- 進入場景時呼叫,用來做初始化工作。
function MainScene:onEnter()
end

-- 退出場景時呼叫,用來釋放資源重置變數等。
function MainScene:onExit()
end

return MainScene

display 物件

display常用屬性

  • display.widthInPixels 螢幕解析度的寬度
  • display.heightInPixels 螢幕解析度的寬度
  • display.width 設計解析度的寬度
  • display.height 設計解析度的高度
  • display.cx 設計解析度中央的x座標
  • display.cy 設計解析度中央的y座標
  • display.left 設計解析度左座標
  • display.top 設計解析度上座標
  • display.right 設計解析度右座標
  • display.bottom 設計解析度下座標
  • display.right 設計解析度右座標
  • display.c_left 當父物件在螢幕中央時螢幕左座標
  • display.c_top 當父物件在螢幕中央時螢幕上座標
  • display.c_right 當父物件在螢幕中央時螢幕右座標
  • display.c_bottom 當父物件在螢幕中央時螢幕下座標
  • display.contentScaleFactor 設計解析度到螢幕解析度的縮放因子,不同於內容縮放因子。

cc.ui模組中封裝了大量複合指令碼風格的cocos2d-x空間,包含UILabel、UIImage、UISlider等。

-- 例項化一個新的UILabel控制元件
cc.ui.UILabel.new()

-- UILabelType 建立文字物件所使用的方式
-- 1 表示使用點陣圖字型建立文字顯示物件,返回物件是LabelBMFont。
-- 2 表示使用TTF字型建立文字顯示物件,返回物件是Label。
-- text 要顯示的文字
-- size 文字尺寸

-- 建立好 UILabel後通過呼叫align()方法設定文字的錨點和顯示位置,最後用addTo()方法把文字新增到場景中。
cc.ui.UILabel.new({UILabelType = 2, text = "Hello, World", size = 64})
    :align(display.CENTER, display.cx, display.cy)
    :addTo(self)

選單場景

quick是一款基於節點樹渲染的遊戲引擎,它把遊戲的各個部分抽象成導演(director)、節點(node)、場景(scene)、層(layer)、精靈(sprit)等一系列的概念,可以把cocos2d-x遊戲中每個時刻都有一個場景在獨立執行,通過切換不同的場景可完成整個遊戲流程,場景切換的管理由導演來執行。

一個遊戲可以有多個不同的遊戲場景,每個場景又可包含多個不同的層或節點,每層可擁有任意的遊戲節點。

4933701-7b9fe0bf792fa1ac.png
quick是基於節點樹渲染的遊戲引擎

新增背景圖片

圖片資源

4933701-a0a70b4b6750abb1.png
背景圖片
4933701-ca93c60639b8f1c7.png
新增背景圖片

操作步驟

  1. 建立 1136x640 的背景圖片精靈 bg.png
  2. 將 bg.png 放到 /res/images/bg.png
  3. 編輯主場景 src/app/scenes/MainScene.luactor() 方法
-- 新增 UI 圖片精靈
display.newSprite("images/bg.png")
:pos(display.cx, display.cy)
:addTo(self)

程式碼分析

-- 建立精靈物件
display.newSprite()

-- 將精靈物件新增到主場景 MainScene 中相應的位置中
display.newSprite("images/bg.png")
:pos(display.cx, display.cy)
:addTo(self)

驗證結果

4933701-77d8e44f57f07cf9.png
驗證解析度適配結果

新增標題圖片並上下運動

圖片資源

4933701-7ead34ca507d9a9b.png
標題圖片

效果預覽

4933701-ff6b2582c7b07537.png
新增標題圖片並上下運動

操作步驟

  1. 建立標題圖片 title.png 並存入 res/images/title.png
  2. 在主場景構造器中新增程式碼
4933701-fbaa3712f8d6bf3f.png
程式碼
-- 新增圖片精靈並設定位置,然後執行一系列動作。
local title = display.newSprite("images/title.png")
:pos(display.cx / 2 * 3, display.cy)
:addTo(self)
local move1 = cc.MoveBy:create(0.5, cc.p(0, 10))
local move2 = cc.MoveBy:create(0.5, cc.p(0, -10))
local SequenceAction = cc.Sequence:create(move1, move2)
-- 執行動作效果
transition.execute(title, cc.RepeatForever:create(SequenceAction))

程式碼解析

-- 新增精靈圖片到場景上位置
pos(display.cs/2*3, display.cy)

-- 執行動作效果
transition.execute(target, action, args)
-- target 顯示 cc.Node 物件
-- action 動作物件
-- args table參數列格物件

transition.execute(title, cc.RepeatForever:create(SequenceAction))
-- action 引數是自定義構建的複合動作
-- cc.MoveBy() 
local move1 = cc.MoveBy:create(0.5, cc.p(0, 10))
local move2 = cc.MoveBy:create(0.5, cc.p(0, -10))
該動作將使節點從當地前座標點勻速直線運動到相對偏移一定向量的位置上
create()函式的兩個引數分別表示運動到指定位置所需的時間和移動的距離(偏移量)
move1表示在0.5秒內向Y軸的正軸上移動10個畫素
move2表示在0.5秒內向Y軸的負方向上移動10個畫素

local SequenceAction = cc.Sequence:create(move1, move2)
cc.Sequence動作允許將一系列動作組合起來,並按順序執行它們。
解析:
1. 建立一個順序執行move1、move2的動作
2. SequenceAction動作會首先執行move1
3. 等move1完成後,再馬上執行move2
4. 迴圈執行該動作的節點最終會回到原來的位置上

cc.RepeatForever:create(SequenceAction)
cc.RepeatForever動作是一個無限重複執行的動作
cc.RepeatForever:create(SequenceAction)表示建立一個無限地執行SequenceAction的動作。

新增按鈕

圖片資源

4933701-fc5539e98d406937.png
按鈕圖片

預覽效果

4933701-2cfb2dd7acb71414.png
新增按鈕

原始碼分析

4933701-255b522080b483e6.png
新增按鈕

程式碼解析

-- 新增按鈕
cc.ui.UIPushButton.new({normal = "images/btn1.png", pressed = "images/btn2.png"})
:onButtonClicked(function() print("start") end)
:pos(display.cx / 2, display.cy * 1.5)
:addTo(self)

在quick中有3中不同的Button按鈕空間,分別是:

  • UIPushButton 按鈕控制元件
    繼承自 UIButton,可通過 cc.ui.UIPushButton.new(image, options)方法來建立 UIPushButton
    引數 images 是 table 型別,代表各個按鈕狀態:正常、按下、禁用下的圖片。
    引數 options 為可選引數化,也是 table 型別,包含了是否 scale9 縮放,偏移flipX、flipY值等設定。

  • UICheckBoxButton CheckButton控制元件

  • UICheckBoxButtonGroup CheckButton組控制元件

onButtonClicked()用於監聽按鈕的點選事件,當點選按鈕時,將呼叫該方法中的程式碼。

-- 點選按鈕時,會在控制檯視窗列印 "start" 的欄位
onButtonClicked(function() print("start") end)

onButtonClicked() 方法類似的還有

  • onButtonPressed(callback) 用於監聽按鈕的按下事件
  • onButtonRelease(callback) 用於監聽按鈕的釋放事件
  • onButtonStateChanged(callback) 用於監聽按鈕的狀態改變事件

相關文章