quick-cocos2d-x 学习系列之 开篇杂记

         开始学习quick-cocos2d-x这个工具了,边学边记录吧。

邮箱[email protected]

欢迎各界交流

1.  官方链接

1.1    quick-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函数中,

然后进入MyApp.lua文件,该文件中的

function MyApp:run()

该函数会实现跳转,到达MainScene.lua文件中的函数。

6.  创建新类

新建一个LUA文件,输入代码如

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.2         Code 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的。

在ctor()函数中加入如下函数即可是实现一个抖动菜单

 

    local button1 = cc.ui.UIPushButton.new("CloseNormal.png")

    :align(display.CENTER, display.cx,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, time, scale,onComplete)

                    local x, 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,

                        time       = time,

                        onComplete = onComplete,

                    })

                end                   

                zoom1(20, 0.08,500, function()

                    zoom2(20, 0.09,500, function()

                        zoom1(10, 0.10,400, function()

                            zoom2(10, 0.11,400, 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参数里,里面有namexyprevXprevY 这五个变量,分别代表着

·        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.cx,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 调试

http://cn.cocos2d-x.org/article/index?type=quick_doc&url=/doc/cocos-docs-master/manual/framework/quick/V3/how-to/use-codeide/zh.md

 

命令行启动带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",  from = {"idle", "walk"},  to = "attack"},

            {name = "beKilled", from = {"idle", "walk", "attack"},  to = "dead"},

            {name = "stop", from = {"walk", "attack"}, to = "idle"},

        },

 

        -- 状态转变后的回调

        callbacks = {

            onidle = function () print("idle") end,

            onwalk = function () print("move") end,

            onattack = function () print("attack") end,

            ondead = function () print("dead") end

        },

    })   

end

增加doEvent函数

命名规则

·        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

文章二

http://cn.cocos2d-x.org/article/index?type=quick_doc&url=/doc/cocos-docs-master/manual/framework/quick/V3/how-to/compile-android/zh.md

文章三

http://cn.cocos2d-x.org/article/index?type=quick_doc&url=/doc/cocos-docs-master/tutorial/framework/quick/chap1/zh.md

蛤蟆实践过程如下:

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中有ressrc文件夹,这两个文件夹就是我们的资源文件夹。(此处处理后第45步就不用操作了)

3、通过Eclipse来打包。

使用Eclipse打包相对来说要简单的多,打开Eclipse,点击File->Import,在弹出的界面中选择Existing Android Code Into Workspace

选择刚才创建的工程,导入完成后点击Finish结束导入。

4、将LUA 项目中\upgrade_bak \cocos2d-x\cocos\platform\android\java\srcjava代码

复制到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

http://cn.cocos2d-x.org/article/index?type=quick_doc&url=/doc/cocos-docs-master/manual/framework/quick/V3/how-to/upgrade/zh.md

 

 

13.        其他友情链接

13.1   王信文(刀塔传奇)创业笔记

http://www.verypig.com/

 

13.2   创业不简单:一个失败手游创业者的自白

 

http://www.niaogebiji.com/article-4056-1.html

13.3   鸟哥笔记

http://www.niaogebiji.com/article-1948-1.html 

 

13.4   Hadoop开源社区

http://www.oschina.net/question/tag/hadoop

你可能感兴趣的:(quick-cocos2d-x 学习系列之 开篇杂记)