码迷,mamicode.com
首页 > 其他好文 > 详细

CocoStudio1.2.0.1做装备切换

时间:2015-02-04 16:44:28      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:cocostudio   animation   装备   人物   cocoachina   

尊重原创,源地址:http://www.cocoachina.com/bbs/read.php?tid=194122

CocoStuido sample----DemoMap 源代码地址  

https://github.com/chukong/CocoStudioSamples  
大家可以预先下载这个源代码, 等下要用到里面的图片资源哦  
 
换装系统是游戏里面可以提升游戏内容的部分, 就像电影里面女猪脚总是不停地上换一套一套漂亮的衣服. 我们在做游戏的时候, 就没有拍电影那么潇洒了, 要费好大力气才能实现换装. 现在CocoStudio提供了超酷的换装系统, 分分秒秒实现换装, 让我们游戏的主角也可以像电影女猪脚那样不停地换上漂亮, 酷帅的衣服装备了. 下面就让我们看看如何实现吧!  
 
一 目标  

技术分享
  
在本教程里, 我们学习下如何使用CocoStudio来快速实现换装.  
我们使用的cocos2d-x的版本是即将发布的2.2.3(即github上cocos2d-x的master分支较新版本), CocoStudio的版本是1.2.0.1. 不同的版本, 功能上会有差异, 大家学习时, 最好采用对应的版本.  
 
二 创建项目并导入资源  
今天我们要同时用到动画编辑和UI编辑器.  
大家可以在下载到的源代码的SampleChangeEquip\SampleChangeEquip_Editor\EquipArmature\EquipArmature\Resources 目录下找到动画编辑器需要的资源.  
在SampleChangeEquip\SampleChangeEquip_Editor\SampleChangeEquip_UI\SampleChangeEquip_UI\Resources 目录中找到UI编辑器需要的资源.  
 
大家分别创建新的动画编辑器和UI编辑器项目, 并分别导入资源.  
 
三 制作人物骨骼和界面UI  
关于骨骼的制作, 由于篇幅关系, 我们这里无法详细展开. 大家可以参见下 "CocoStudio sample讲解 SampleCollision骨骼动画与简单碰撞"(http://www.cocoachina.com/bbs/read.php?tid=189665) .  
 
我们在动画编辑器中制作完成后英雄如下图所示,  

技术分享
  
我们可以看到英雄由beltbone(皮带), glovebone(手套), helmetbone(头盔), necklacebone(项链), amourbone(衣服), weaponebone(武器)组成. 这些骨骼将是我们换装的基础.  

技术分享
  
我们再打开UI编辑器, 构建界面. 我们这里简单看下UI上英雄, 背包, 装备的构成.  

技术分享
  
如上图所示, 我们用一个层容器和一些按钮控件组成了英雄换装部分. 稍后会用程序将英雄添加到居中部位.  
周围按钮可以接受对应的武器, 比如头盔按钮可以接受头盔, 如果放置了头盔, 也可以将头盔从这个区域拖走.  

技术分享
  
 
背包也是由层容器和众多按钮构成.  

技术分享
  
 
武器层由层容器和分组过的图片组成, 并整体处于不可见状态. 我们稍后会用程序的方式将其解析到正确的位置.  
这里其实是一种取巧的做法, 相当于大家在真实游戏中的数据库的作用.  
 
大家经过几次练习之后, 无论是人物还是界面都能很快构建出来. 如果大家在制作的过程中遇到了问题, 不妨到CocoaChina论坛的CocoStudio专区提出来, 大家多加交流.  
 
四 导出资源  
我们分别在两个编辑器里面用快捷键Ctrl+E打开导出对话框, 选择导出的路径,  按默认配置导出. 我们稍后会用到这些文件.  
 
五 在cocos2d-x工程中添加导出后的资源  
想必各位看官都已经熟练掌握了cocos2d-x工程的创建, 我这里就不再啰嗦了.  
创建完工程之后, 需要将我们上面用CocoStudio导出的几个文件拷贝到cocos2d-x工程的Resources文件夹下.  
 
六 代码实现  
我们在HellWorld工程中, 添加一个Bag类, 我们着看下几个重要函数的实现. 其他的代码, 由于篇幅有限, 请大家参见源代码.  
 

首先我们定于了一个枚举, 来确定装备的类型. 需要注意的是, 这些枚举的先后需要和我们在UI中equippanel的子节点对应.   


enum
{
             EQUIP_TYPE_HELMET = 1,//头盔
             EQUIP_TYPE_NECKLACE ,//项链
             EQUIP_TYPE_ARMOUR ,//衣服
            
             EQUIP_TYPE_WEAPON ,//武器
             EQUIP_TYPE_SKILL ,//技能
             EQUIP_TYPE_SHIELD ,//盾牌
            
             EQUIP_TYPE_OTHER ,//其他
             EQUIP_TYPE_BELT ,//皮带
             EQUIP_TYPE_GLOVE //手套
};
 
 
 
我们首先看下装备的解析.   
//装备初始化
void Bag ::initEquips()
{
             //获取装备面板
             UIPanel* equipPanel = dynamic_cast <UIPanel *>(uiLayer->getWidgetByName( "equippanel"));
             CCArray* equips = equipPanel->getChildren();
             CCObject* object = NULL;
 
             int bagGridCount = 1;
 
             //第一个类型是头盔
             int equipType = EQUIP_TYPE_HELMET ;                   //the first type of equip
 
             CCARRAY_FOREACH (equips,object)
            {
                         //该装备类型下所有节点
                         UIPanel* equipChildPanel = ( UIPanel*)object;
                         CCArray* equips = equipChildPanel->getChildren();
 
                         int equipStartNum = 1;
 
                         CCARRAY_FOREACH_REVERSE (equips, object)
                        {
                                     //获取到的装备
                                     UIWidget* equip = dynamic_cast< UIWidget*>(object);
                                     //给装备添加了触摸回调
                                    equip->addTouchEventListener( this, toucheventselector (Bag ::touchEvent));
                                     //给装备设置ID, 其实是设置了装备的tag, 下面我们再看下其算法
                                    initEquipID(equip,equipType,equipStartNum);
                                    
                                     //获取背包面板里面第bagGridCount格子
                                     UIWidget* bagGrid = getBagGrid(bagGridCount++);
                                    changeParent(bagGrid,equip); //将装备加入背包格式.
 
                                    equipStartNum++;
                        }
                        equipType++;
            }
}
 
 
再来看下装备的tag算法.   
//装备tag算法, 类型*100 + 序号*10
void Bag ::initEquipID( UIWidgetpEquip, int type, int num)
{
             //
             pEquip->setTag( type*100 + num *10);
}
 
 
我们再来看下英雄面板的初始化.  
//英雄面板初始化
void Bag ::initPlayerEquipGrid()
{
             //获取英雄面板
             UIPanel* playerPanel = dynamic_cast <UIPanel *>(uiLayer->getWidgetByName( "playerpanel"));
 
             CCArray* equipGrids = playerPanel->getChildren();
             CCObject* object = NULL;
            
             //遍历英雄面板并给节点设置tag为类型*100
             int gridType = EQUIP_TYPE_HELMET ;
             CCARRAY_FOREACH (equipGrids,object)
            {
                         UIWidget* equipGrid = ( UIWidget*)object;
                        equipGrid->setTag(gridType * 100);
                        gridType++;
            }
}
 
 
我们再来看下人物的初始化.  
void Bag ::initArmature()
{
             //加载人物数据
             CCArmatureDataManager ::sharedArmatureDataManager()->addArmatureFileInfo( "ArmatureAndEquip/EquipArmature.ExportJson");
            armature = CCArmature::create( "EquipArmature" );
            armature->getAnimation()->playByIndex(0);
            armature->setScale(0.28);
            armature->setPosition( ccp( CCDirector::sharedDirector()->getVisibleSize().width * 0.28,
                         CCDirector::sharedDirector()->getVisibleSize().height * 0.55));
 
             //将英雄添加到界面
             UIWidget* armatureWidget = UIWidget::create();
            uiLayer->addWidget(armatureWidget);
            armatureWidget->addNode(armature);
 
             //initArmatureOriginEquips();
}
void Bag ::initArmatureOriginEquips()
{
             //隐藏编辑器中给英雄添加的默认装备
            armature->getBone( "beltbone" )->changeDisplayWithIndex(-1,true );
            armature->getBone( "necklacebone" )->changeDisplayWithIndex(-1,true );
            armature->getBone( "weaponbone" )->changeDisplayWithIndex(-1,true );
            armature->getBone( "helmetbone" )->changeDisplayWithIndex(-1,true );
}
 
 
刚才我们给装备添加了触摸事件, 我们来看下装备如何响应触摸.  
//触摸事件
void Bag ::touchEvent( CCObjectpSender, TouchEventType type)
{
             UIWidget* equip = ( UIWidget*) pSender;
             if ( type == TOUCH_EVENT_BEGAN )//触摸开始
            {
                        touchBeganEvent(equip);
            }
             if ( type == TOUCH_EVENT_MOVED )//移动
            {
                        touchMoveEvent(equip);
            }
             if ( type == TOUCH_EVENT_ENDED )//结束
            {
                        touchEndedEvent(equip);
            }
}
 
//当触摸开始时
void Bag ::touchBeganEvent( UIWidgetpEquip)
{
            startGrid = ( UIWidget*) pEquip->getParent(); //记录移动开始的格子
            
             pEquip->retain();
             pEquip->removeFromParent(); //从当前父节点移除
             pEquip->setPosition(CCPointZero);
             pEquip->setPosition( pEquip->getTouchStartPos()); //设置坐标
            uiLayer->addWidget( pEquip); //放入uiLayer中, 可以理解为放入根节点中
             pEquip->release();
 
             pEquip->setZOrder(2); //调整zorder
}
 
//移动过程中
void Bag ::touchMoveEvent( UIWidgetpEquip)
{
             CCPoint point = pEquip->getTouchMovePos();
 
             pEquip->setPosition(point);
}
//移动结束时
void Bag ::touchEndedEvent( UIWidgetpEquip)
{
             //获取背包面板, 英雄面板
             UIPanel* bagPanel = dynamic_cast <UIPanel *>(uiLayer->getWidgetByName( "bagpanel"));
             UIPanel* playerPanel = dynamic_cast <UIPanel *>(uiLayer->getWidgetByName( "playerpanel"));
 
             if(hitTestPanel(bagPanel, pEquip))
    { //放入了背包面板的格子上
        if (targetGrid->getChildren()->count()>0) //格子上已经有装备
        {
            UIWidget* originEquip = ( UIWidget*)targetGrid->getChildren()->objectAtIndex(0);
            changeParent(startGrid, originEquip); //将目标格子原装备放入移动起始格子
            if(startGrid->getTag() >= 100) changeEquip(originEquip, startGrid); //英雄更新装备.
        }
        else if(startGrid->getTag()>=100) unequipEquip(); //英雄卸下装备
        changeParent(targetGrid, pEquip); //将当前装备放入目标格子
        return;
    }
             if(hitTestPanel(playerPanel, pEquip))
    { //放入了英雄面板
        if (targetGrid->getChildren()->count()>0) //格子上已经有装备
        {
            UIWidget* originEquip = ( UIWidget*)targetGrid->getChildren()->objectAtIndex(0);
            changeParent(startGrid, originEquip); //将目标格子原装备放入移动起始格子
        }
        changeParent(targetGrid, pEquip); //将当前装备放入目标格子
        changeEquip( pEquip, targetGrid); //英雄更新装备
        return;
    }
 
            changeParent(startGrid, pEquip); //如果没有放入合适的格子, 则当前装备回到起始格子
}
 
 
我们再来看下英雄是如何更新和卸载装备的.  
//更新装备
void Bag ::changeEquip( UIWidgetpWeapon, UIWidgetpGrid)
{
    int equipType = pGrid->getTag()/100;
    if (equipType == EQUIP_TYPE_SKILL return ;
    if (equipType == EQUIP_TYPE_SHIELD return ;
    if (equipType == EQUIP_TYPE_OTHER return ;
 
             //获取装备, 骨骼的节点名称
             CCString* weaponName = CCString ::createWithFormat("%stex.png" ,pWeapon ->getName());
             CCString* boneName = CCString::createWithFormat( "%sbone" ,pGrid ->getName());
 
             //创建皮肤
             CCSkin* weaponSkin = CCSkin ::createWithSpriteFrameName(weaponName->getCString());
            armature->getBone(boneName->getCString())->addDisplay(weaponSkin,0); //添加皮肤到骨骼
            armature->getBone(boneName->getCString())->changeDisplayWithIndex(0, true); //显示新添加的骨骼
}
 
 
 

技术分享
  
好了, 快来运行下吧.  

CocoStudio1.2.0.1做装备切换

标签:cocostudio   animation   装备   人物   cocoachina   

原文地址:http://blog.csdn.net/u013007305/article/details/43486255

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!