- Cocos:http://www.cocos.com/download
- Quick-Coco2d-x:https://github.com/dualface/quick-cocos2d-x
- QuickXDev: https://github.com/leitwolf/QuickXDev
由于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](https://i-blog.csdnimg.cn/blog_migrate/fa1dcda8391e5846e6741a8f89597067.png)
-
build
cocos2dx项目存放目录 -
cocos
cocos2dx主目录核心代码存放位置 -
docs
quick文档目录 -
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](https://i-blog.csdnimg.cn/blog_migrate/db49d5c3d88143d0cd9e370bca389555.png)
-
bin
quick工具脚本,包括binding脚本、加密脚本等 -
cocos
C++定义的常量与封装的接口 -
framework
quick框架核心目录 -
lib
quick类库 -
player
player的工程文件 -
samples
quick示例代码 -
templates
quick项目模板 -
welcome
player启动界面代码
开发工具
QuickXDev是SublimeText开发quick-cocos2d-x的插件,SublimeText配置QuickXDev插件步骤:
- 下载之后解压,并重命名为QuickXDev。
- 把该文件夹放入到SublimeText的Packages目录下
Preferences->Browse Packages
- 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](https://i-blog.csdnimg.cn/blog_migrate/174f388c1a3a37f5284de0c968498e0b.png)
quick-cocos2d-x 中带有一个名为 Player 的工具,这个工具不但是一个功能完善的模拟器,可以在 Mac/Windows 桌面运行开发者的游戏,还是一个功能齐备的开发工具入口。开发者启动 Player 后,将可以完成下列任务:创建项目、打开项目、编译项目、查看示例
- player 依赖一些特定的环境设置才能正常工作,Windows 平台下运行 setup_win.bat。
- 启动 player 后将看到以下画面
- 创建项目,有两种方式:命令行创建、通过 Player 创建
创建项目
# 创建一个test的项目
$ create_project.bat -p com.junchow.games.test
![4933701-0afc98af376bcd65.png](https://i-blog.csdnimg.cn/blog_migrate/e8b7b6c7370421576ad3fd23d95d6aa7.png)
项目目录结构
![4933701-7a2a65835ed32275.png](https://i-blog.csdnimg.cn/blog_migrate/0e1251a668998025780f8464c24ba86c.png)
-
debug.log
调试日志,即打印控制台窗口输出的日志。 -
config.json
项目配置文件 -
src
项目源码存放目录 -
runtime
预编译的运行时库存放目录 -
res
项目资源的存放目录 -
frameworks
cocos2d-x引擎核心代码及各平台运行时资源
项目源码目录结构
![4933701-ebe5ec292af84da1.png](https://i-blog.csdnimg.cn/blog_migrate/6d3307005f88de256cee2215d75621d5.png)
-
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](https://i-blog.csdnimg.cn/blog_migrate/f031b1ab18c90c791b19bda8dbacfad1.png)
Cocos中图片显示到屏幕有两个逻辑过程,结合在一起影响最终的显示效果。首先是将资源布局到设计分辨率,然后是将设计分辨率布局到屏幕。
![4933701-767298608bb14121.jpg](https://i-blog.csdnimg.cn/blog_migrate/19647dc190b7ea242e74cfc4bc636215.jpeg)
设计分辨率指config.lua
文件中设置的CONFIG_SCREEN_WIDTH
和CONFIG_SCREEN_HEIGHT
,相当于参考分辨率。确定了参考分辨率才能得到图片资源的缩放比率。
-- 图片资源显示到屏幕的缩放因子,由“背景图片资源宽高/设计分辨率宽高”得到。
cc.Director:getInstance():setContentScaleFactor(value)
- 缩放因子 = 图片资源高/设计分辨率高
保证了背景资源垂直方向在设计分辨率范围内的全部显示,但水平方向上可能会溢出或留有黑边。
![4933701-2e6a13cf28d4a1fd.png](https://i-blog.csdnimg.cn/blog_migrate/a04f6257230e8fcb9a10f30c12d0dcf2.png)
- 缩放因子 = 图片资源宽/设计分辨率宽
保证了背景资源的水平方向在设计分辨率范围内的全部显示,但垂直方向上可能会超出屏蔽范围或留有黑边。
![4933701-e911569925388ce4.png](https://i-blog.csdnimg.cn/blog_migrate/203333f7ccb77abd512fc400065c34a1.png)
-- 设置设计分辨率宽高
setDesignResolutionSize(width, height, cc.ResolutionPolicy)
-- width 设计分辨率宽度
-- height 设计分辨率高度
-- cc.ResolutionPolicy 分辨率适配策略,由config.lua中CONFIG_SCREEN_WIDTH、CONFIG_SCREEN_HEIGHT、CONFIG_SCREEN_AUTOSCALE来设置。
分辨率适配的实现
横屏的飞行游戏,需要让背景图在高度上全部显示,那么宽度上必须会做出一些牺牲,即要么被裁剪要么留黑边,当然黑边可以通过将图片宽度做的更宽来解决。
- 选择
1136x640
的图片资源,宽高比够大,能确保在某些极端的分辨率也能完整不留黑边显示。 - 设置
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"
-
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
- 将
res
和src
目录添加到文件所搜路径
cc.FileUtils:getInstance():addSearchPath("res/")
- 读取
config.lua
加载Lua配置,并设置内容缩放因子,解决分辨率适配问题。
cc.Director:getInstance():setContentScaleFactor(640/CONFIG_SCREEN_HEIGHT)
- 创建
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](https://i-blog.csdnimg.cn/blog_migrate/35a6bef7dd36d9bac708667fdc727df1.png)
添加背景图片
图片资源
![4933701-a0a70b4b6750abb1.png](https://i-blog.csdnimg.cn/blog_migrate/f40e82247c1fdf18c3d4a85a8219160d.png)
![4933701-ca93c60639b8f1c7.png](https://i-blog.csdnimg.cn/blog_migrate/e3d8661a8915dd0a095000518977322f.png)
操作步骤
- 创建 1136x640 的背景图片精灵 bg.png
- 将 bg.png 放到
/res/images/bg.png
- 编辑主场景
src/app/scenes/MainScene.lua
中ctor()
方法
-- 添加 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](https://i-blog.csdnimg.cn/blog_migrate/43bd21a7e9e03e692fb06d0009e825e3.png)
添加标题图片并上下运动
图片资源
![4933701-7ead34ca507d9a9b.png](https://i-blog.csdnimg.cn/blog_migrate/fb58778823cb2891f393c5a4564be300.png)
效果预览
![4933701-ff6b2582c7b07537.png](https://i-blog.csdnimg.cn/blog_migrate/c9d523d412a469966f7ec513817dacf3.png)
操作步骤
- 创建标题图片
title.png
并存入res/images/title.png
- 在主场景构造器中添加代码
![4933701-fbaa3712f8d6bf3f.png](https://i-blog.csdnimg.cn/blog_migrate/6d5b25e7f0be3159d0f90c45e42cc291.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](https://i-blog.csdnimg.cn/blog_migrate/e4de7806a9f861a11abc38ac55bd4c14.png)
预览效果
![4933701-2cfb2dd7acb71414.png](https://i-blog.csdnimg.cn/blog_migrate/d11ce7a0cd9932b82ba25422ead12b87.png)
源码分析
![4933701-255b522080b483e6.png](https://i-blog.csdnimg.cn/blog_migrate/d69b0be30da3b36ad715034c0a0b21d2.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)
用于监听按钮的状态改变事件