Quick-3.3 开发笔记

由于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 源码目录

系统目录
  • 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框架核心目录

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",

模拟器

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
创建项目

项目目录结构

项目目录
  • debug.log 调试日志,即打印控制台窗口输出的日志。
  • config.json 项目配置文件
  • src 项目源码存放目录
  • runtime 预编译的运行时库存放目录
  • res 项目资源的存放目录
  • frameworks cocos2d-x引擎核心代码及各平台运行时资源

项目源码目录结构

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"

分辨率适配问题

市场上各种屏幕尺寸和分辨率的移动设备层出不穷,为了让开发的项目能够更好地适应不同的设备,分辨率适配尤为重要。

常见手机分辨率

Cocos中图片显示到屏幕有两个逻辑过程,结合在一起影响最终的显示效果。首先是将资源布局到设计分辨率,然后是将设计分辨率布局到屏幕。

分辨率适配.jpg

设计分辨率指config.lua文件中设置的CONFIG_SCREEN_WIDTHCONFIG_SCREEN_HEIGHT,相当于参考分辨率。确定了参考分辨率才能得到图片资源的缩放比率。

-- 图片资源显示到屏幕的缩放因子,由“背景图片资源宽高/设计分辨率宽高”得到。
cc.Director:getInstance():setContentScaleFactor(value)
  • 缩放因子 = 图片资源高/设计分辨率高
    保证了背景资源垂直方向在设计分辨率范围内的全部显示,但水平方向上可能会溢出或留有黑边。
缩放因子=图片资源高/设计分辨率高
  • 缩放因子 = 图片资源宽/设计分辨率宽
    保证了背景资源的水平方向在设计分辨率范围内的全部显示,但垂直方向上可能会超出屏蔽范围或留有黑边。
缩放因子=图片资源宽/设计分辨率宽
-- 设置设计分辨率宽高
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()加入内容缩放因子
    添加内容缩放因子
-- 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游戏中每个时刻都有一个场景在独立运行,通过切换不同的场景可完成整个游戏流程,场景切换的管理由导演来执行。

一个游戏可以有多个不同的游戏场景,每个场景又可包含多个不同的层或节点,每层可拥有任意的游戏节点。

quick是基于节点树渲染的游戏引擎

添加背景图片

图片资源

背景图片
添加背景图片

操作步骤

  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)

验证结果

验证分辨率适配结果

添加标题图片并上下运动

图片资源

标题图片

效果预览

添加标题图片并上下运动

操作步骤

  1. 创建标题图片 title.png 并存入 res/images/title.png
  2. 在主场景构造器中添加代码
代码
-- 添加图片精灵并设置位置,然后执行一系列动作。
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的动作。

添加按钮

图片资源

按钮图片

预览效果

添加按钮

源码分析

添加按钮

代码解析

-- 添加按钮
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) 用于监听按钮的状态改变事件
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容