CocoStudio在Cocos2d-x Lua项目中的应用--加载动画

当游戏进入了手游时代, 快成为了开发游戏的主题曲. 开发快, 上线快, Bug修复快, 挣钱也会特别快.
脚本成为了在游戏开发中的助力, 而且脚本可以即时更新的特性, 更是为了避免平台冗长的审核过程的法宝. Lua脚本以其开发速度快, 运行快, 成为了众多游戏开发的首选.

CocoStudio也是以快著称, 如果CocoStudio和Cocos2d-x Lua珠联璧合, 快上加快, 很有想象的空间.
今天我们来看下在Cocos2d-x Lua项目中如何调用CocoStudio导出的动画.

一 版本
我们采用的是Cocos2d-x 3.0RC0和CocoStudio 1.3, 不同的版本在功能上可能略有差异, 希望大家尽量能采用这个版本.

大家请自行下载并配置开发环境, 如果大家在安装活配置的过程中遇到问题, 不妨在CocoaChina的CocoStudio专区提出, 一起交流.

二 创建新的Cocos2d-x Lua项目并导入资源
大家在命令行或者终端中, 找到将要存放工程的路径并运行命令
cocos new -p com.young40.animation -l lua LuaAnimation
我们在LuaAnimation\frameworks\runtime-src\目录下可以看到有iOS, Mac, Android, Win32等工程.

大家可以根据自己的情况来打开对应的工程项目. 我是在Win下创建的, 所以选择Win32的工程并打开.

我们打开CocoStudio的动画编辑器, 并打开示例项目HeroAnimation.
我们切换到动画模式, 为attack的其中一帧添加一个kill帧事件. 对帧事件不太了解的同学, 可以看下这篇教程.
CocoStudio sample讲解 SampleCollision骨骼动画与简单碰撞 http://www.cocoachina.com/bbs/read.php?tid=189665
大家可以看下其中的帧事件部分, 这里不再赘述.

导出这个项目, 稍后将导出的文件复制到LuaAnimation的res目录下边. 可能iOS, Mac工程还需要将其添加到Xcode项目中, 这里不再赘述.我们还增加了两个武器的图片(weapon1tex.png, weapon2tex.png), 做换装的演示.

三 代码实现
我们在代码中对CocoStudio做好的动画的操作很简单, 大概可以分为以下几个操作.

  1. 加载动画数据
  2. 生成动画对象
  3. 播放动画
    包括按名称播放, 按顺序播放, 以及获取动画列表数量
  4. 骨骼动画换装
    添加新的皮肤, 切换新的皮肤
  5. 帧事件和动画事件
    添加帧事件监听, 以及监听回调
    添加动画事件, 以及监听回调

我们在默认的Cocos2d-x Lua工程里面直接修改main.lua.
好, 让我们直接看代码吧. 附件中有工程打包下载, 需要大家将2d-x copy一份到LuaAnimation\frameworks\cocos2d-x.

– 运行场景 local sceneGame = cc. Scene:create() --sceneGame:addChild(createLayerFarm()) --注释掉默认的农场的场景 --sceneGame:addChild(createLayerMenu())
local function createTestLayer () local layerTest = cc. Layer:create()
– 加载动画-资源 – 还有异步加载资源的方法addArmatureFileInfoAsync, 大家可以自行看下其用法, 今天暂不讨论 ccs .ArmatureDataManager: getInstance():addArmatureFileInfo( “res/Hero0.png”, “res/Hero0.plist” , “res/Hero.ExportJson” )
– 创建动画对象 local armature = ccs. Armature:create( “Hero”) – 设置位置 armature :setPosition(origin. x + visibleSize.width / 3, origin .y + visibleSize. height / 5) – 播放动画, 播放指定动作 armature :getAnimation(): play(“attack”) – 添加到游戏中 layerTest :addChild(armature)
– 帧事件回调 do – 添加用于显示的标签 local killEventCount = 0 – 计算事件发生数量 local killEventLabel = cc. Label:create( “Kill Event Count: 0”, s_markerFeltFontPath, 20) killEventLabel :setPosition(cc. p(50, 10))
layerTest :addChild(killEventLabel)
– 添加帧事件回调 armature :getAnimation(): setFrameEventCallFunc(function ( bone, evt, originFrameIndex, currentFrameIndex ) if evt == “kill” then – 判断帧事件名称是否为kill killEventCount = killEventCount + 1 – 更新输出显示 killEventLabel :setString("Kill Event Count: " … killEventCount) end end) end
– 动画事件回调 do – 添加一个动画事件显示标签 local moveEventLabel = cc. Label:create( “”, s_markerFeltFontPath, 20) moveEventLabel :setPosition(cc. p(50, 30))
layerTest :addChild(moveEventLabel)
– 添加帧事件回调 armature :getAnimation(): setMovementEventCallFunc(function (arm, eventType, movmentID) – 判断帧事件类型 local actionType = “Start Event” if eventType == ccs. MovementEventType.start then actionType = “Start Event” elseif eventType == ccs. MovementEventType.complete then actionType = “Complete Event” elseif eventType == ccs. MovementEventType.loopComplete then actionType = “Loop Complete Event” end
– 更新输出显示 moveEventLabel :setString("Got Event " … movmentID … " " … actionType) end) end
– 我们要实现触摸后切换动画- – 接受触摸 local function onTouchBegan(touch, event) return true end
local currentIndex = 0 – 获取动作列表数量 local animationListCount = armature: getAnimation():getMovementCount() – 触摸结束后切换动画 local function onTouchEnded(touch, event) – 通过播放动画 armature :getAnimation(): playWithIndex(currentIndex)
currentIndex = currentIndex + 1 if currentIndex >= animationListCount then currentIndex = 0 end end
– 监听触摸事件 local listener = cc. EventListenerTouchOneByOne:create() listener :registerScriptHandler(onTouchBegan, cc.Handler .EVENT_TOUCH_BEGAN) listener :registerScriptHandler(onTouchEnded, cc.Handler .EVENT_TOUCH_ENDED) local eventDispatcher = layerTest: getEventDispatcher() eventDispatcher :addEventListenerWithSceneGraphPriority(listener, layerTest)
– 换装的实现 – 生成新的皮肤(这里指装备) local skin1 = ccs. Skin:create( “res/weapon1tex.png”) local skin2 = ccs. Skin:create( “res/weapon2tex.png”)
– 获取到装备的骨骼, 并添加新的显示 local bone = armature: getBone(“Layer17”) bone :addDisplay(skin1, 1) bone :addDisplay(skin2, 2)
– 创建菜单 local function createLayerMenu() local menu = cc. Menu:create()
local label = cc. Label:create( “ChangeDisplay”, s_markerFeltFontPath, 20) local menuChageDisplay = cc. MenuItemLabel:create(label) menuChageDisplay :setAnchorPoint(cc. p(0, 0))
– 换装中装备显示的Index local displayIndex = 0 menuChageDisplay :registerScriptTapHandler(function () displayIndex = displayIndex + 1 if displayIndex > 2 then displayIndex = 0 end
– 换装 bone :changeDisplayWithIndex(displayIndex, true) end)
– 增加了一个用于调试的临时按钮 local menuReload = cc. MenuItemLabel:create(cc .Label: create(“Reload”, s_markerFeltFontPath, 20)) menuReload :setAnchorPoint(cc. p(0, 0)) menuReload :setPosition(0, 20) menuReload :registerScriptTapHandler(function () dofile( “src/main.lua”) – 强行重载, 写法欠考虑, 大家别学我 end)
menu :setAnchorPoint(cc. p(0, 0)) menu :setPosition(cc. p(50, 60)) menu :addChild(menuChageDisplay) menu :addChild(menuReload)
return menu end
layerTest :addChild(createLayerMenu())
return layerTest end
– 添加我们的测试层到Scene sceneGame :addChild(createTestLayer())

:8::8::8::8: 终于搞定了Lua的代码高浪…
不知道大家有没有什么好的办法…

求指教有没有…

一个图片都没有, 这是一个很环保的教程…

支持楼主~:2::2::2::2::2::2:

谢谢太阳哥支持!!!

我是来和杨老师学习骨骼动画的~

:3: :3: :3: :3: :3: :3: :3:

学习学习 不知道2.2版本支持不支持

LUA ERROR: ASSERT FAILED ON LUA EXECUTE: AnimationData not exist!
楼主,能说说看报这个错是什么原因吗,还有
local armature = ccs. Armature:create( “Hero”)这里create的参数是什么意思,我自己创建的动画,我应该设置什么参数
希望楼主抽空解答···谢谢·········

这个参数是动画制作时的工程名称

如果是资源读取失败,请注意添加searchpath。

fgdf辅导费丰富的非

:870:, 版主 , 为什么我的 cocos2d2.2.2 在android 下 不能强制 dofile ? 找不到目录!

感谢楼主分享,最近做手游项目,对我很有价值。

:7: :7: :7: :7: :7: :7:

我把创建的hero对象 缩小了下,但是他攻击完成之后的特效怎么位置还是原来的位置,难道他们不是在同一个坐标系?还是?

感谢 楼主分享,好东西啊。

wadasdasdasasdddddddddddddddddddddddddddasdasd

:2: :2: :2: :2: :2: 学习了

我也碰到这个问题,求解中