CocoStudio sample讲解 SampleChangeEquip 换装系统

换装系统是游戏里面可以提升游戏内容的部分, 就像电影里面女猪脚总是不停地上换一套一套漂亮的衣服. 我们在做游戏的时候, 就没有拍电影那么潇洒了, 要费好大力气才能实现换装. 现在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); //显示新添加的骨骼
}
 
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值