正文  游戏开发 > 游戏引擎 >

Cocos2d-x 3.1.1 Lua示例 ActionManagerTest(动作管理)

Cocos2d-x 3.1.1 Lua示例 ActionManagerTest(动作管理)本篇博客介绍Cocos2d-x的动作管理例子,这个例子展示了Cocos2d-x的几个动作:MoveT...

Cocos2d-x 3.1.1 Lua示例 ActionManagerTest(动作管理)

本篇博客介绍Cocos2d-x的动作管理例子,这个例子展示了Cocos2d-x的几个动作:
MoveTo——移动动作,移动到某一个点
MoveBy——移动动作,与MoveTo是类似的,只是MoveBy可以移动到某一个点然后按原路返回,提供reverse方法。RotateTo——旋转动作,把某一精灵旋转到某一角度
RotateBy——旋转动作,把某一精灵旋转某个角度,它有一个方法reverse,它让对象按原路径旋转回ScaleTo——缩放动作,把某一精灵(Sprite)放大或缩小到某一比例Scaleby——缩放动作,把某一精灵(Sprite)放大或缩小多少比例,它有一个方法reverse,它让对象按原路径旋转回

这个例子涉及到的知识点有:
创建动作序列,例如: cc.Sequence:create(cc.DelayTime:create(1.4),cc.CallFunc:create(removeThis)执行动作序列,例如:ret:runAction( cc.Sequence:create(cc.DelayTime:create(1.4),cc.CallFunc:create(removeThis)))
我们先来看一下这个例子的效果,特别制作动态图给大家展示:\


\

\

具体代码实现,具体API的使用方法,希望各位能认真看,如果对其中所传参数不清楚和不理解的,可以请教百度老师或者到官网参考具体API,这是学习方法。》》》ActionManagerTest.lua
local    kTagNode = 0   -- 结点标识
local    kTagGrossini = 1 -- 
local    kTagSequence = 2 -- 
-- 获取和这个 director 关联的调度器
local   scheduler = cc.Director:getInstance():getScheduler()
--------------------------------------------------------------------
--
-- Test1
--
--------------------------------------------------------------------

local function CrashTest()
    -- 创建测试层
    local ret = createTestLayer("Test 1. Should not crash")
    -- 精灵,s_pPathGrossini为图片路径
    local  child = cc.Sprite:create(s_pPathGrossini)
    -- 显示到x=200,y=200的位置
    child:setPosition( 200,200 )
    ret:addChild(child, 1)

    --Sum of all action's duration is 1.5 second.
    -- 旋转一个节点,1.5秒,旋转90度
    child:runAction(cc.RotateBy:create(1.5, 90))
    -- 执行动作序列,1.4秒延迟,淡出
    child:runAction(cc.Sequence:create(cc.DelayTime:create(1.4),cc.FadeOut:create(1.1)))
    
    local function removeThis()
        -- 溢出孩子
        ret:getParent():removeChild(ret, true)
        Helper.nextAction()
    end

    --After 1.5 second, self will be removed.
    -- 1.5秒之后,自身会被移除
    ret:runAction( cc.Sequence:create(cc.DelayTime:create(1.4),cc.CallFunc:create(removeThis)))
    return ret
end


--------------------------------------------------------------------
--
-- LogicTest
-- 逻辑测试
--------------------------------------------------------------------
local function LogicTest()
    local ret = createTestLayer("Logic test")
    -- 精灵,s_pPathGrossini为图片路径
    local  grossini = cc.Sprite:create(s_pPathGrossini)
    -- 添加一个子节点到容器中,有Z轴顺序和一个标记。
    ret:addChild(grossini, 0, 2)
    grossini:setPosition(200,200)
    local function bugMe(node)
        -- 停止所有动作
        node:stopAllActions() --After this stop next action not working, if remove this stop everything is working
        node:runAction(cc.ScaleTo:create(2, 2))
    end
    -- 运行动作序列
    grossini:runAction( cc.Sequence:create(cc.MoveBy:create(1, cc.p(150,0)) ,cc.CallFunc:create(bugMe)))
    return ret
end

--------------------------------------------------------------------
--
-- PauseTest
-- 暂停测试
--------------------------------------------------------------------

local function PauseTest()
    local ret = createTestLayer("Pause Test")
    local schedulerEntry = nil
    local function unpause(dt)
        scheduler:unscheduleScriptEntry(schedulerEntry)
        schedulerEntry = nil
        local  node = ret:getChildByTag( kTagGrossini )
        local  pDirector = cc.Director:getInstance()
        pDirector:getActionManager():resumeTarget(node)
    end

    local function onNodeEvent(event)
        -- 进入时
        if event == "enter" then
            local  s = cc.Director:getInstance():getWinSize()
            local  l = cc.Label:createWithTTF("After 3 seconds grossini should move", "fonts/Thonburi.ttf", 16)
            ret:addChild(l)
            l:setAnchorPoint(cc.p(0.5, 0.5))
            l:setPosition( cc.p(s.width / 2, 245) )
            
            local  grossini = cc.Sprite:create(s_pPathGrossini)
            ret:addChild(grossini, 0, kTagGrossini)
            grossini:setPosition(cc.p(200,200))
            
            -- 创建移动动作,持续时间1秒,移动到(150,0)的位置
            local  action = cc.MoveBy:create(1, cc.p(150,0))

            local  pDirector = cc.Director:getInstance()
            -- 通过获取director关联的ActionManager并为目标添加动作
            -- 为一个目标添加动作。 如果目标已经存在,动作将被加在已经存在的目标上。
            -- 如果目标不存在,将会创建这个目标的新对象,这个动作将被添加在这个新创建出来的对象上 当目标动作被暂停,动作队列的顺序也不会乱。
            pDirector:getActionManager():addAction(action, grossini, true)

            schedulerEntry = scheduler:scheduleScriptFunc(unpause, 3.0, false)
        -- 退出
        elseif event == "exit" then
            if schedulerEntry ~= nil then
                scheduler:unscheduleScriptEntry(schedulerEntry)
            end
        end
    end
    -- 注册响应事件
    ret:registerScriptHandler(onNodeEvent)
    return ret
end

--------------------------------------------------------------------
--
-- RemoveTest
-- 
--------------------------------------------------------------------
local function RemoveTest()
    local ret = createTestLayer("Remove Test")
    local  l = cc.Label:createWithTTF("Should not crash", "fonts/Thonburi.ttf", 16)
    -- 获得屏幕大小
    local  s = cc.Director:getInstance():getWinSize()
    ret:addChild(l)
    l:setAnchorPoint(cc.p(0.5, 0.5))
    l:setPosition( cc.p(s.width / 2, 245))

    -- 创建移动动作,持续2秒,到(200,0)的位置
    local  pMove = cc.MoveBy:create(2, cc.p(200, 0))
    -- 停止动作
    local function stopAction()
        -- 根据Tag来获取子节点
        local  pSprite = ret:getChildByTag(kTagGrossini)
        pSprite:stopActionByTag(kTagSequence)
    end
    
    -- 创建一个回调函数
    local callfunc = cc.CallFunc:create(stopAction)
    local  pSequence = cc.Sequence:create(pMove,callfunc)
    pSequence:setTag(kTagSequence)

    
    local  pChild = cc.Sprite:create(s_pPathGrossini)
    pChild:setPosition( 200, 200 )

    ret:addChild(pChild, 1, kTagGrossini)
    pChild:runAction(pSequence)
    return ret
end


--------------------------------------------------------------------
--
-- ResumeTest
-- 恢复测试
--------------------------------------------------------------------
local function ResumeTest()
    local ret = createTestLayer("Resume Test")

    local schedulerEntry = nil
    local function resumeGrossini(time)
        scheduler:unscheduleScriptEntry(schedulerEntry)
        schedulerEntry = nil
        local  pGrossini = ret:getChildByTag(kTagGrossini)
        local  pDirector = cc.Director:getInstance()
        pDirector:getActionManager():resumeTarget(pGrossini)
    end


    local function onNodeEvent(event)
        if event == "enter" then
            local  l = cc.Label:createWithTTF("Grossini only rotate/scale in 3 seconds", "fonts/Thonburi.ttf", 16)
            ret:addChild(l)
            local  s = cc.Director:getInstance():getWinSize()
            l:setAnchorPoint(cc.p(0.5, 0.5))
            l:setPosition( s.width / 2, 245)

            local  pGrossini = cc.Sprite:create(s_pPathGrossini)
            ret:addChild(pGrossini, 0, kTagGrossini)
            pGrossini:setPosition(200,200)
            
            -- 运行缩放的动作
            pGrossini:runAction(cc.ScaleBy:create(2, 2))

            local  pDirector = cc.Director:getInstance()
            -- 暂停目标
            pDirector:getActionManager():pauseTarget(pGrossini)
            -- 运行旋转动作,旋转360度,持续2秒
            pGrossini:runAction(cc.RotateBy:create(2, 360))

            schedulerEntry = scheduler:scheduleScriptFunc(resumeGrossini, 3.0, false)
        elseif event == "exit" then
            if schedulerEntry ~= nil then
                scheduler:unscheduleScriptEntry(schedulerEntry)
            end
        end
    end

    ret:registerScriptHandler(onNodeEvent)

    return ret
end


function ActionManagerTestMain()
    cclog("ActionManagerTestMain")
    Helper.index = 1 -- 初始索引为1
    -- 设置深度测试
    cc.Director:getInstance():setDepthTest(true)
    -- 创建场景
    local scene = cc.Scene:create()
    -- 初始化方法表
    Helper.createFunctionTable = {
        CrashTest,
        LogicTest,
        PauseTest,
        RemoveTest,
        ResumeTest
    }
    -- 添加层
    scene:addChild(CrashTest())
    scene:addChild(CreateBackMenuItem())
    return scene
end

在例子中用到一些定义好的资源路径,还有相关帮助类,童鞋们可以到可以到相应目录下进行查找:help.lua(帮助类,封装定义了相关方法,创建测试层、切换场景等)
require "Cocos2d"

CC_CONTENT_SCALE_FACTOR = function()
  -- 获取surface的大小,单位为像素
  return cc.Director:getInstance():getContentScaleFactor()
end

--把以像素为单位的矩形转换为以点为单位的矩形
CC_POINT_PIXELS_TO_POINTS = function(pixels)
  return cc.p(pixels.x/CC_CONTENT_SCALE_FACTOR(), pixels.y/CC_CONTENT_SCALE_FACTOR())
end

-- 把以点为单位的矩形转换为以像素为单位的矩形
CC_POINT_POINTS_TO_PIXELS = function(points)
  return cc.p(points.x*CC_CONTENT_SCALE_FACTOR(), points.y*CC_CONTENT_SCALE_FACTOR())
end


-- cclog 打印日志
cclog = function(...)
  print(string.format(...))
end

-- change table to enum type  把表转换为枚举类型
function CreateEnumTable(tbl, index)
  local enumTable = {}
  local enumIndex = index or -1
  for i, v in ipairs(tbl) do
    enumTable[v] = enumIndex + i
  end
  return enumTable
end

-- back menu callback 返回菜单回调
local function MainMenuCallback()
  local scene = cc.Scene:create()
  scene:addChild(CreateTestMenu())
  
  -- 切换场景
  cc.Director:getInstance():replaceScene(scene)
end

-- add the menu item for back to main menu
-- 为返回主菜单添加菜单项
function CreateBackMenuItem()
  -- 创建一个标签
  local label = cc.Label:createWithTTF("MainMenu", s_arialPath, 20)
  -- 设置器锚点
  label:setAnchorPoint(cc.p(0.5, 0.5))
  -- 设置菜单项标签
  local MenuItem = cc.MenuItemLabel:create(label)
  MenuItem:registerScriptTapHandler(MainMenuCallback)

  -- 获得屏幕大小
  local s = cc.Director:getInstance():getWinSize()
  -- 创建菜单
  local Menu = cc.Menu:create()
  -- 添加菜单项
  Menu:addChild(MenuItem)
  -- 设置菜单位置
  Menu:setPosition(0, 0)
  -- 设置菜单项位置,大致在右下角的位置
  MenuItem:setPosition(s.width - 50, 25)

  return Menu
end

-- 帮助类
Helper = {
  index = 1,  -- 索引
  createFunctioinTable = nil, -- 存储方法的表
  currentLayer = nil,   -- 当前层
  titleLabel = nil,     -- 标题
  subtitleLabel = nil   -- 子标题
}

-- 下个动作
function Helper.nextAction()
  Helper.index = Helper.index + 1 -- 索引加1
  if Helper.index > table.getn(Helper.createFunctionTable) then
    Helper.index = 1 
  end

  return Helper.newScene()
end

-- 回退动作
function  Helper.backAction()
  Helper.index = Helper.index - 1
  if Helper.index == 0 then
    Helper.index = table.getn(Helper.createFunctionTable)
  end

  return Helper.newScene()
end

-- 重新开始动作
function Helper.restartAction()
  return Helper.newScene()
end

-- 切换新的场景
function Helper.newScene()
  local scene
  -- 如果使用物理效果
  if Helper.usePhysics then
    -- 创建一个带物理效果的场景
    scene = cc.Scene:createWithPhysics()
  else
    scene = cc.Scene:create()
  end
  Helper.currentLayer = Helper.createFunctionTable[Helper.index]()
  -- 添加当前层
  scene:addChild(Helper.currentLayer)
  -- 添加返回菜单
  scene:addChild(CreateBackMenuItem())

  -- 切换场景
  cc.Director:getInstance():replaceScene(scene)
end

-- 初始化层
function Helper.initWithLayer(layer)
  Helper.currentLayer = layer

  -- 获取屏幕大小
  local size = cc.Director:getInstance():getWinSize()
  Helper.titleLabel = cc.Label:createWithTTF("", s_arialPath, 28)
  Helper.titleLabel:setAnchorPoint(cc.p(0.5, 0.5))
  layer:addChild(Helper.titleLabel, 1)
  Helper.titleLabel:setPosition(size.width / 2, size.height - 50)

  Helper.subtitleLabel = cc.Label:createWithTTF("", s_thonburiPath, 16)
  Helper.subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5))
  layer:addChild(Helper.subtitleLabel, 1)
  Helper.subtitleLabel:setPosition(size.width / 2, size.height - 80)

  -- menu菜单
  local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2)
  local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2)
  local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2)
  item1:registerScriptTapHandler(Helper.backAction)
  item2:registerScriptTapHandler(Helper.restartAction)
  item3:registerScriptTapHandler(Helper.nextAction)

  local menu = cc.Menu:create()
  menu:addChild(item1)
  menu:addChild(item2)
  menu:addChild(item3)
  menu:setPosition(cc.p(0, 0))
  -- 摆放三个菜单项的位置
  item1:setPosition(cc.p(size.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2))
  item2:setPosition(cc.p(size.width / 2, item2:getContentSize().height / 2))
  item3:setPosition(cc.p(size.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2))
  layer:addChild(menu, 1)

  local background = cc.Layer:create()
  layer:addChild(background, -10)
end

-- 创建测试层
function createTestLayer(title, subtitle)
  -- 创建一个层
  local layer = cc.Layer:create()
  Helper.initWithLayer(layer)
  local titleStr = title == nil and "No title" or title
  local subTitleStr = subtitle  == nil and "" or subtitle
  Helper.titleLabel:setString(titleStr)
  Helper.subtitleLabel:setString(subTitleStr)
  return layer
end

testResource.lua定义了所有的资源路径,方便管理和获取
s_pPathGrossini       = "Images/grossini.png"
s_pPathSister1        = "Images/grossinis_sister1.png"
s_pPathSister2        = "Images/grossinis_sister2.png"
s_pPathB1             = "Images/b1.png"
s_pPathB2             = "Images/b2.png"
s_pPathR1             = "Images/r1.png"
s_pPathR2             = "Images/r2.png"
s_pPathF1             = "Images/f1.png"
s_pPathF2             = "Images/f2.png"
s_pPathBlock          = "Images/blocks.png"
s_back                = "Images/background.png"
s_back1               = "Images/background1.png"
s_back2               = "Images/background2.png"
s_back3               = "Images/background3.png"
s_stars1              = "Images/stars.png"
s_stars2              = "Images/stars2.png"
s_fire                = "Images/fire.png"
s_snow                = "Images/snow.png"
s_streak              = "Images/streak.png"
s_PlayNormal          = "Images/btn-play-normal.png"
s_PlaySelect          = "Images/btn-play-selected.png"
s_AboutNormal         = "Images/btn-about-normal.png"
s_AboutSelect         = "Images/btn-about-selected.png"
s_HighNormal          = "Images/btn-highscores-normal.png"
s_HighSelect          = "Images/btn-highscores-selected.png"
s_Ball                = "Images/ball.png"
s_Paddle              = "Images/paddle.png"
s_pPathClose          = "Images/close.png"
s_MenuItem            = "Images/menuitemsprite.png"
s_SendScore           = "Images/SendScoreButton.png"
s_PressSendScore      = "Images/SendScoreButtonPressed.png"
s_Power               = "Images/powered.png"
s_AtlasTest           = "Images/atlastest.png"

-- tilemaps resource
s_TilesPng            = "TileMaps/tiles.png"
s_LevelMapTga         = "TileMaps/levelmap.tga"

-- spine test resource
s_pPathSpineBoyJson       = "spine/spineboy.json"
s_pPathSpineBoyAtlas       = "spine/spineboy.atlas"

-- fonts resource
s_markerFeltFontPath   = "fonts/Marker Felt.ttf"
s_arialPath            = "fonts/arial.ttf"
s_thonburiPath         = "fonts/Thonburi.ttf"
s_tahomaPath           = "fonts/tahoma.ttf"