CocoStudio sample讲解SamplesSceneEditor场景编辑器

CocoStudio sample讲解SamplesSceneEditor场景编辑器

一、目标

本节目标是为了整合UI界面与动画元素,并通过程序完成对UI和动画的控制。本场景最终实现的效果是场景开始的时候控制左边的英雄向左移动,当检测到距离够近时则攻击右侧的怪物,怪物被攻击后掉血并播放死亡动作。

二、创建并导入资源

— Begin quote from ____

本节内容重心在场景的编辑与控制,所以关于骨骼动画的制作及UI的制作不做赘述。如果需要了解UI或者骨骼动画的制作细节请参考前面的章节。

— End quote

本场景主要包含了两个骨骼动画人物和一个UI界面,我们我们需要通过动画编辑器和UI编辑器制作完成两个人物及UI界面。关于骨骼动画的制作请参考 http://www.cocoachina.com/bbs/read.php?tid=189665。本节教程所用的到两个骨骼动画均可在编辑器的启动器示例中获取,也可以直接拿取示例中附带的资源。
此处大致介绍一下UI界面,因为下面需要在程序中控制UI的控件。

这个界面是这个战斗场景的UI界面部分,主要有任务的信息展示栏及下面的护栏。其中重点在4个由进度条做成的血量和魔法值条,其余的部分均是图片控件。本节示例中需要控制右侧的血量条,制作UI界面的时候一定要记下右侧两个进度条的名称,本示例中两个名称分别为“hp02_LoadingBar”、“mp02_LoadingBar”。

三、制作场景

开始之前先了解下这个工程的结构,列表由上往下分别是背景、两个骨骼动画、UI界面、火焰粒子、两个头像。其中火焰粒子和头像是放在UI节点内部的。

背景是一个图片,在场景编辑器中对应的空间就是精灵,类似于UI编辑器中的图片控件。拖入控件后将背景图片添加进文件属性,并调整坐标,精灵的锚点为中心点,所以坐标应该是(480,320)

接下来是两个骨骼动画,这个选用的是骨骼组件,这个需要将骨骼动画导出的数据文件(josn/ExportJson格式)从资源面板拖入到骨骼的“文件”属性中。

导入动画后就剩下UI部分了,UI同骨骼动画类似,也是需要引入UI编辑器导出后的json数据文件引入到UI组件的“文件”属性中即可。UI的内部还有两个头像和一个粒子特效,头像就是一个图片,这里仍然使用精灵组件。
待这些组件加载完整个场景已经完成大部分了。接下来将场景最顶层的火焰粒子特效加上,粒子特效是有例子编辑器制作而成的,目前mac平台下可以使用“ParticleDesigner”,win平台推荐使用“”,导出后的数据主要是一个plist文件(有时候会带有一张图片),制作方法这里不做讲解我们直接使用项目提供的“particle/1-buff.plist”

四、导入工程

在菜单栏中选择“文件”—》“导出项目”—》“导出资源”

场景编辑器里的导出设置较为简单,名称使用默认即可,导出位置可以选择当前项目内或游戏工程的目录。“格式化输出”这个是为了优化导出数据的。

五、程序实现

// on “init” you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
//初始化全局变量
m_fTime = 0.0f;
m_bStart = false;
m_bDead = false;
m_fPercentage = 100.0f;
m_fSpeed = 4.0f;
m_fAttackDis = 120.0f;
m_pGameScene = NULL;

//通过场景文件,初始化游戏场景

CCNode *pGameScene = SceneReader::sharedSceneReader()->createNodeWithSceneFile(“FightScene.json”);
m_pGameScene = pGameScene;
this->addChild(pGameScene);
//获取英雄节点
CCComRender render = (CCComRender)(m_pGameScene->getChildByTag(10005)->getComponent(“CCArmature”));
//将节点转换为CCArmature类型对象
CCArmature pArmature = (CCArmature)(render->getNode());
//播放“run”动画
pArmature->getAnimation()->play(“run”);

m_bStart = true;

//创建关闭菜单项
CCMenuItemFont *itemBack = CCMenuItemFont::create(“End”, this, menu_selector(HelloWorld::menuCloseCallback));
itemBack->setColor(ccc3(255, 255, 255));
//设置关闭菜单项的位置,VisibleRect是一个视图辅助类,rightBottom表示屏幕右下角的坐标
itemBack->setPosition(ccp(VisibleRect::rightBottom().x - 50, VisibleRect::rightBottom().y + 25));
CCMenu *menuBack = CCMenu::create(itemBack, NULL);
menuBack->setPosition(CCPointZero);
menuBack->setZOrder(4);

this->addChild(menuBack);

scheduleUpdate();

return true;

}

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
//清理内存并退出游戏
CCArmatureDataManager::purge();
SceneReader::sharedSceneReader()->purge();
cocos2d::extension::ActionManager::shareManager()->purge();
GUIReader::shareReader()->purge();
CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

void HelloWorld::animationEvent(CCArmature *pArmature,
MovementEventType movementType, const char *movementID)
{
//获取右侧的怪物节点
CCComRender render = (CCComRender)(m_pGameScene->getChildByTag(10006)->getComponent(“CCArmature”));
//转换为CCArmature类型对象
CCArmature pEnemy = (CCArmature)(render->getNode());
//如果是动画播放完成
if (movementType == COMPLETE)
{
//"怪物"播放“death”动画
pEnemy->getAnimation()->play(“death”);
//给怪物添加事件监听
pArmature->getAnimation()->setMovementEventCallFunc(NULL, NULL);
//记录B的死亡
m_bDead = true;
}

}

void HelloWorld::update(float delta)
{
//判断是否是第一次更新
if(m_bStart)
{
//获取英雄节点
CCComRender pHeroRender = (CCComRender)(m_pGameScene->getChildByTag(10005)->getComponent(“CCArmature”));
CCArmature pHero = (CCArmature)(pHeroRender->getNode());
//给英雄设置坐标
pHero->getParent()->setPositionX(pHero->getParent()->getPositionX() + m_fSpeed);
//获取怪物节点
CCComRender pEnemyRender = (CCComRender)(m_pGameScene->getChildByTag(10006)->getComponent(“CCArmature”));
CCArmature pEnemy = (CCArmature)(pEnemyRender->getNode());
//计算两个armature的间隔,如果小于预设值,则执行英雄的攻击动作
if(ccpDistance(ccp(pHero->getParent()->getPositionX(), 0), ccp(pEnemy->getParent()->getPositionX(), 0)) < m_fAttackDis)
{ //执行攻击动作
pHero->getAnimation()->play(“attack”);
//添加帧事件监听
pHero->getAnimation()->setMovementEventCallFunc(this,
movementEvent_selector(HelloWorld::animationEvent));
m_bStart = false;//标记已经开始
}
}
//判断B是否死亡
if(m_bDead)
{
//获取ui界面
CCComRender pUIRender = static_cast<CCComRender>(m_pGameScene->getChildByTag(10007)->getComponent(“GUIComponent”));
//转换为TouchGroup类型
cocos2d::gui::TouchGroup *pUILayer = static_castcocos2d::gui::TouchGroup*(pUIRender->getNode());
//获取血条
cocos2d::gui::LoadingBar *pHPLoadingBar = static_castcocos2d::gui::LoadingBar*(pUILayer->getWidgetByName(“hp02_LoadingBar”));
//获取魔法值
cocos2d::gui::LoadingBar *pMPLoadingBar = static_castcocos2d::gui::LoadingBar*(pUILayer->getWidgetByName(“mp02_LoadingBar”));
//更新血条和魔法值
pHPLoadingBar->setPercent(m_fPercentage);
pMPLoadingBar->setPercent(m_fPercentage);
//递减血量
m_fPercentage -= 2.0f;

    if (m_fPercentage < 0.0f) {

//如果血条为空,注销掉帧刷新监听
unscheduleUpdate();
}
}

}

版主好样的,教程很详细,学习了。谢谢哈

你好版主
//获取英雄节点
CCComRender render = (CCComRender)(m_pGameScene->getChildByTag(10005)->getComponent(“CCArmature”));

//将节点转换为CCArmature类型对象
CCArmature pArmature = (CCArmature)(render->getNode());

上面是在场景里做的固定的两个骨骼动画框,如果是场景里那两个人是要换的,或者说是随机上去两个骨骼动画,那两个骨骼动画框初始时空,就是光拖上去两个框设置下位置,然后在代码里
给那两个框添加骨骼动画的CCArmature该怎么做?

您好,请问是想用代码添加armature么?

armature = cocos2d::extension::CCArmature::create(“Cowboy”);

scene->addChild(armature);

这个是直接代码添加
我的意思是在场景中放两个空的骨骼组件,然后每次进入这个场景的时候拿两个骨骼组件中的人物是不同的
就好像你以前回答我的给一个image换图片一样。image的组件在场景里,每次进去给image换个图
这次是问问能不能同样的每次进入场景给骨骼组件换个别的一套的动画形象,比如这次英雄是拿刀的这个人,下次可能就是牛仔拿枪的那套动画的.ExportJson
因为在场景设置了组件的位置后,替换组件内容的话不用再去添加组件的位置大小的信息了,用代码添加每次得设置组件的位置很多大小还有方向吧

请问一下:这个例子对应的cocos2dx版本是什么呢?是cocos2dx2.2.1,还是3.0呢?

请问能根据COCOS2DX 3.0 再出个例子吗,下面的代码在3.0不能用:
/获取ui界面
CCComRender pUIRender = static_cast<CCComRender>(m_pGameScene->getChildByTag(10007)->getComponent(“GUIComponent”));
//转换为TouchGroup类型
cocos2d::gui::TouchGroup *pUILayer = static_castcocos2d::gui::TouchGroup*(pUIRender->getNode());
//获取血条
cocos2d::gui::LoadingBar *pHPLoadingBar = static_castcocos2d::gui::LoadingBar*(pUILayer->getWidgetByName(“hp02_LoadingBar”));
//获取魔法值
cocos2d::gui::LoadingBar *pMPLoadingBar = static_castcocos2d::gui::LoadingBar*(pUILayer->getWidgetByName(“mp02_LoadingBar”));

git目录中每个demo内的https://github.com/chukong/CocoStudioSamples/tree/master/SampleSceneEditor/SampleSceneEditor_Editor 类似“SampleXXXXEditor_Editor ”的文件夹都是编辑器工程文件,不过你说的是一个场景,而非UI了。

另外我们即将发布的2.0版本将去掉部分重叠功能,所以你现在多看看UI即可,场景的部分功能都融合到UI里了。