开始学习quick-cocos2d-x这个工具了,边学边记录吧。
欢迎各界交流
1.官方链接
1.1quick-x-player 使用说明
http://quick.cocoachina.com/?p=39
1.2初窥 quick-cocos2d-x
http://quick.cocoachina.com/?p=1
这篇文档讲的甚是明白
1.3用 Eclipse LDT 调试 quick-cocos2d-x 游戏
http://quick.cocoachina.com/?p=1527
断点调试编码必备
需要什么信息,可以直接在官网上进行搜索,必定会得到你想要的结果。
2.Quick和cocos2d-x区别
引用自官方文档:quick 和 cocos2d-x 的主要区别有如下几点:
1.更完善的 Lua 支持,包括一个 Lua 框架对 C++ 接口进行了二次封装
2.补充了大量cocos2d-x 没有提供,但游戏需要的功能
3.为提高开发效率,提供了Objective-C 和 Java 的桥接模块,以及强化的 Windows/Mac 模拟器
3.PLAYER
引用官方:quick-cocos2d-x 里附带了一个功能强大的模拟器,称为 quick-x-player(后文简称 player)。
player 可以在 Mac 和 Windows 环境中模拟游戏引擎的绝大部分功能。在开发过程中,利用 player 可以高效的测试游戏功能。
2.1从命令行启动 player
Player支持从命令行启动,感觉貌似作用不大了,因为现在直接可在图形化操作了。具体参数参看官网。
4.动态实时调试举例
这里先通过Player创建一个项目后,
在src目录中便可找到config.lua。
Config.lua文件中,定义了程序的一些特性是否开启,如是否调试、是否显示FPS信息等。
在code-ide中编辑MainScene.lua文件,修改如下文件
function MainScene:ctor()
cc.ui.UILabel.new({
UILabelType = 2,text = "Hello,World",size = 64})
:align(display.CENTER,display.cx,display.cy)
:addTo(self)
end
将text = "Hello,World",修改为text = "YES,World" 保存后即可见修改。
5.程序入口
每个程序都有自己的入门,这个基于LUA的项目入门函数在main.lua函数中,
function MyApp:run()
该函数会实现跳转,到达MainScene.lua文件中的函数。
6.创建新类
local Player = class("Player",function()
local sprite = display.newSprite("image/diji.png")
return sprite
end)
function Player:ctor()
end
return Player
即可实现新类创建。
然后在MainScene.lua中输入
一下代码即可
local Player =import("..role.Player")
local Player = class("Player",function()
return display.newSprite("image/diji.png") end)
function MainScene:ctor()
cc.ui.UILabel.new({
--其他代码省略
self.player = Player.new() --display.newSprite("#player1-1-1.png")
self.player:setPosition(display.left + self.player:getContentSize().width/2,display.cy)
self:addChild(self.player)
end
类的构造函数是ctor。
7.code ide工具使用
7.1注释
ctrl+shift+C 会加上或者去掉--注释
7.2Code IDE函数注释显示乱码
在工具上选中Window –> Preferences – >General –> Workspace,Text fileencoding,选成UTF-8即可。退出code-ide重进,问题解决。
7.3代码修改刷新程序
和刷新网页一样,F5即可。主要保护F5键盘。
8.代码细节
8.1增加搜索路径
CCFileUtils:sharedFileUtils():addSearchPath("res/")
8.2存档路径
device.writablePath获得存档文件保存目录
8.3屏幕分辨率
可以用 display.width,display.height 获得屏幕分辨率。
8.4创建菜单
cc.ui.UIPushButton.new("CloseNormal.png" )
:setButtonLabel(cc.ui.UILabel.new({text= "Use CCSLoader"}))
:onButtonPressed(function(event)
event.target:setScale(1.2)
print("pressed")
end)
8.5抖动菜单效果按钮,果冻按钮效果
这里假设大家已熟悉quick开发的基础知识。
Quick版本是3.3的。
local button1 = cc.ui.UIPushButton.new("CloseNormal.png")
:align(display.CENTER,display.cy + 40)
:onButtonPressed(function(event)
local function zoom1(offset,time,scale,onComplete)
local x,y = event.target:getPosition()
local size = self:getContentSize()
local scaleX = event.target:getScaleX() * (size.width + scale) / size.width
local scaleY = event.target:getScaleY() * (size.height - scale) / size.height
transition.moveTo(event.target,{y = y - offset,time = time})
transition.scaleTo(event.target,{
scaleX = scaleX,
scaleY = scaleY,
time = time,
onComplete = onComplete,
})
end
local function zoom2(offset,y = event.target:getPosition()
local size = self:getContentSize()
transition.moveTo(event.target,{y = y + offset,time = time / 2})
transition.scaleTo(event.target,{
scaleX = 1.0,
scaleY = 1.0,
})
end
zoom1(20,0.08,500, function()
zoom2(20,0.09, function()
zoom1(10,0.10,400, function()
zoom2(10,0.11, function()
end)
end)
end)
end)
print("pressed")
end)
:addTo(self)
8.6定时器使用
8.6.1每帧调用
文件头处输入:
local scheduler = require("framework.scheduler")
函数中输入
local time = 0
local function update(dt)
time = time + 1
print(time)
end
scheduler.scheduleUpdateGlobal(update)
8.6.2间隔一定时间调用
local time = 0
local function onInterval(dt)
time = time + 1
print(time)
end
scheduler.scheduleGlobal(onInterval,1)
8.6.3间隔时间调用一次
local time = 0
local function onInterval(dt)
time = time + 1
print(time)
print("over")
end
scheduler.performWithDelayGlobal(onInterval,1)
8.6.4停止定时器
scheduler.unscheduleGlobal() |
参数是前面那些定时器返回的句柄,所以如果需要在后面停止掉,在创建的留一个返回值
8.7触摸
local layer = display.newLayer()
self:addChild(layer)
layer:setTouchEnabled(true)
layer:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
layer:addNodeEventListener(cc.NODE_TOUCH_EVENT,function (event)
local x,y,prevX,prevY = event.x,event.y,event.prevX,event.prevY
if event.name == "began" then
print("layer began")
elseif event.name == "moved" then
print("layer moved")
elseif event.name == "ended" then
print("layer ended")
end
end)
·cc.TOUCH_MODE_ONE_BY_ONE 是单点触摸
·cc.TOUCH_MODE_ALL_AT_ONCE 是多点触摸
在添加节点事件监听addNodeEventListener中,我们设置监听事件的类型是cc.NODE_TOUCH_EVENT
这个监听事件类型,其定义了几个引擎级事件,分别是,
-- Cocos2d-x 引擎级事件
c.NODE_EVENT=0 c.NODE_ENTER_FRAME_EVENT=1 c.NODE_TOUCH_EVENT=2 c.NODE_TOUCH_CAPTURE_EVENT=3 c.MENU_ITEM_CLICKED_EVENT=4 c.ACCELERATE_EVENT=5 c.KEYPAD_EVENT=6 |
在event参数里,里面有name,x,y,prevX,prevY 这五个变量,分别代表着
·event.name 是触摸事件的状态:began,moved,ended,cancelled,added(仅限多点触摸),removed(仅限多点触摸);
·event.x,event.y 是触摸点当前位置;
·event.prevX,event.prevY 是触摸点之前的位置;
8.8触摸捕获世界
触摸捕获事件的优先级要比触摸事件要高,换句话说,触摸捕获事件会比触摸事件先响应,并且有权不分发给触摸事件响应。举例如下
local layer = display.newLayer()
self:addChild(layer)
layer:setTouchEnabled(true)
layer:setTouchSwallowEnabled(false)
layer:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
layer:addNodeEventListener(cc.NODE_TOUCH_EVENT,function (event)
if event.name == "began" then
print("layer began")
elseif event.name == "moved" then
print("layer moved")
elseif event.name == "ended" then
print("layer ended")
end
return true
end)
layer:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT,function (event)
if event.name == "began" then
print("layer capture began")
elseif event.name == "moved" then
print("layer capture moved")
elseif event.name == "ended" then
print("layer capture ended")
end
return true
end)
local sp = display.newSprite("HelloWorld.png",display.cy)
layer:addChild(sp)
--self:addChild(sp)
sp:setTouchEnabled(true)
sp:setTouchSwallowEnabled(false)
sp:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE)
sp:addNodeEventListener(cc.NODE_TOUCH_EVENT,function (event)
if event.name == "began" then
print("sp began")
elseif event.name == "moved" then
print("sp moved")
elseif event.name == "ended" then
print("sp ended")
end
return true
end)
sp:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT,function (event)
if event.name == "began" then
print("sp capture began")
elseif event.name == "moved" then
print("sp capture moved")
elseif event.name == "ended" then
print("sp capture ended")
end
return true
end)
8.9多点触摸
多点触摸如下:
local layer = display.newLayer()
self:addChild(layer)
layer:setTouchEnabled(true)
layer:setTouchMode(cc.TOUCH_MODE_ALL_AT_ONCE)
layer:addNodeEventListener(cc.NODE_TOUCH_EVENT,function (event)
if event.name == "began" or event.name == "added" then
for id,point in pairs(event.points) do
printf("%d,%f,%f",id,event.points[id].x,event.points[id].y)
end
elseif event.name == "removed" then
print("touch removed")
elseif event.name == "moved" then
print("touch moved")
elseif event.name == "ended" then
print("touch ended")
end
return true
end)
8.10硬件按键
硬件按键是设备上的触摸屏之外的按键。
预定义的层事件主要有两个:
·cc.ACCELERATE_EVENT:重力感应事件
·cc.KEYPAD_EVENT:硬件按键事件
要实现一个按键响应事件主要就两步:
·1. 打开键盘功能setKeypadEnabled(true)
·2. 添加事件监听addNodeEventListener
local layer = display.newLayer()
self:addChild(layer)
layer:setKeypadEnabled(true)
layer:addNodeEventListener(cc.KEYPAD_EVENT,function (event)
if event.key == "back" then
print("back")
device.showAlert("Confirm Exit","Are you sure exit game ?",{"YES","NO"},function (event)
if event.buttonIndex == 1 then
CCDirector:sharedDirector():endToLua()
else
device.cancelAlert()
end
end)
elseif event.key == "menu" then
print("menu")
end
end)
8.11其他事件
预定义的节点事件:
·cc.NODE_EVENT - enter,exit等事件
·cc.NODE_ENTER_FRAME_EVENT -帧事件
·cc.NODE_TOUCH_EVENT - 触摸事件
·cc.NODE_TOUCH_CAPTURE_EVENT- 捕获触摸事件
预定义的层事件:
·cc.ACCELERATE_EVENT - 重力感应事件
·cc.KEYPAD_EVENT - 硬件按键事件
预定义的菜单事件:
·cc.MENU_ITEM_CLICKED_EVENT- CCMenu 菜单项点击事件
9.断点调试
如果开发没有断点调试实在是让人异常头疼,好吧,蛤蟆就记录下如何是是实现QUICK项目的断点调试。
需要quick 的develop版本。只有DEVEOP版本才有断点调试。
仓库地址:https://github.com/chukong/quick-cocos2d-x
下载后运行加压包中的 setup_win.bat进行环境变量配置
然后按下网址代码进行配置
http://quick.cocos.org/?p=1527
Player3后的调试,查看官网
《在 Code IDE 中调试 Quick 工程》
CODE IDE 调试
命令行启动带CONSOLE
D:\cocos\quick-3.3\quick\player\win32>player3.exe-workdir F:\cocoside_zhizuo\com
10.状态机实现记录
创建状态机
self.fsm_ = {}
cc.GameObject.extend(self.fsm_)
:addComponent("components.behavior.StateMachine")
:exportMethods()
self.fsm_:setupState({
-- 初始状态
initial = "idle",
-- 事件和状态转换
events = {
-- t1:clickScreen; t2:clickEnemy; t3:beKilled; t4:stop
{name = "clickScreen",from = {"idle","attack"},to = "walk" },
{name = "clickEnemy","walk"},to = "attack"},
{name = "beKilled","walk",to = "dead"},
{name = "stop",from = {"walk",to = "idle"},
},
-- 状态转变后的回调
callbacks = {
onidle = function () print("idle") end,
onwalk = function () print("move") end,
onattack = function () print("attack") end,
ondead = function () print("dead") end
},
})
end
命名规则
·onbeforexxx: 执行xxx事件前的响应函数;
·onxxx或者onafterxxx: 执行xxx事件完成的响应函数;
·onenterxxx或者onxxx: 进入xxx状态时的响应函数;
·onleavexxx: 离开xxx状态时的响应函数;
·onbeforeevent: 执行所有事件之前会执行该响应函数,事件信息以参数形式下发;
·onafterevent或者onevent: 执行所有事件完成之后执行该响应函数,事件信息以参数形式下发;
·onchangestate: 改变状态时的响应函数,事件信息会以参数的形式下发;
·onenterstate: 进入状态时的响应函数,事件信息会以参数形式下发:
·onleavestate: 离开状态时的响应函数,事件信息会以参数形式下发。
设置状态逻辑是重写setupState方法,这其中有这么几个字段参数,
·initial:状态机的初始状态
·terminal (final):结束状态
·events:状态发生转变时对应的事件
·callbacks:发生转变时的回调函数
接下来一个重点是callbacks参数,即所谓回调了,就是事件触发,会执行一系列的函数。
·onbeforeEVNET:在事件EVENT开始前被激活
·onleaveSTATE:在离开旧状态STATE时被激活
·onenterSTATE 或 onSTATE:在进入新状态STATE时被激活
·onafterEVENT 或 onEVENT:在事件EVENT结束后被激活
此外还有5种通用型的回调来捕获所有事件和状态的变化:
·onbeforeevent:在任何事件开始前被激活
·onleavestate:在离开任何状态时被激活
·onenterstate:在进入任何状态时被激活
·onafterevent:在任何事件结束后被激活
·onchangestate:当状态发生改变的时候被激活
这里面的名称是不可以修改的,它是针对于任何事件和任何状态的。
最后,就是调用这些事件了,通过self.fsm:doEvent(event)就可以了,参数event对应events参数名称。此外还有这些,
·fsm:isReady():返回状态机是否就绪
·fsm:getState():返回当前状态
·fsm:isState(state):判断当前状态是否是参数state状态
·fsm:canDoEvent(eventName):当前状态如果能完成eventName对应的event的状态转换,则返回true
·fsm:cannotDoEvent(eventName):当前状态如果不能完成eventName对应的event的状态转换,则返回true
·fsm:isFinishedState():当前状态如果是最终状态,则返回true
·fsm:doEventForce(name,...):强制对当前状态进行转换
11.quick-coco2dx-x烧写到android/ios真机
官网链接如下:
http://cn.cocos2d-x.org/tutorial/show?id=1471
文章二
文章三
蛤蟆实践过程如下:
android环境编译手动记录,下面这些是必须的:
·Quick-Cocos2d-x引擎
·JDK
·android-sdk
·android-ndk(r9以上)
环境变量中需要设置ANDROID_NDK_ROOT
1、进入项目\upgrade_bak\frameworks\runtime-src\proj.android
2、在proj.android目录下执行./build_native(Mac)或者build_native.bat(windows)拷贝资源和编译C++文件。
编译完成后我们可以在proj.android目录下面的assets中有res和src文件夹,这两个文件夹就是我们的资源文件夹。(此处处理后第4、5步就不用操作了)
3、通过Eclipse来打包。
使用Eclipse打包相对来说要简单的多,打开Eclipse,点击File->Import
,在弹出的界面中选择Existing Android Code Into Workspace
:
选择刚才创建的工程,导入完成后点击Finish
结束导入。
4、将LUA 项目中\upgrade_bak \cocos2d-x\cocos\platform\android\java\src中java代码
复制到ECLIPSE项目中的\src 中,覆盖之。
5、最后将LUA代码复制到Eclipse 项目中assets/src/ 下
如果有图片等资源存放至:\assets\res\
6、编译运行。
成功!
1.4出错问题
运行Build_native.bat出错
'./obj/local/armeabi/objs-debug/extra_static/F_\cocoside_zhizuo\test\upgra
de_bak\frameworks\runtime-src\proj.android\/__/Classes/quick-src/extra/luabindin
g/lua_cocos2dx_extension_filter_auto.o.d':
Error opening output file
答:项目路径超长
复制\upgrade_bak文件夹出来到分区根目录下重命名后编辑即可。
12.相关链接
升级到最新3.2rc0
13.其他友情链接
13.1王信文(刀塔传奇)创业笔记
13.2创业不简单:一个失败手游创业者的自白
http://www.niaogebiji.com/article-4056-1.html
13.3鸟哥笔记
http://www.niaogebiji.com/article-1948-1.html