首页 > 代码库 > Cocos Studio1.5.0.1开发学习笔记(一)

Cocos Studio1.5.0.1开发学习笔记(一)

  听说Cocos Studio很久了,主要是因为骨骼动画。目前看来Cocos2d-x播放动画的方式只有2种:

  第一种:是播放序列帧动画,即将动画的每一帧都加载进缓存里,需要播放时再使用Animation类来播放,这种方法简单暴力,应对一些细节要求低的动画场景的时候,这么干无伤大雅。但是当动画帧数稍高的时候就会需要大量的图片,消耗资源很大。

  第二种:是由Cocos2d-x提供的Action类来播放动画,这种动画是在帧循环中靠调整每次渲染的坐标来打到动画效果,由于帧循环是1/60秒刷新一次,会让这样播放的动画非常流畅,而且不需要每一帧图片的资源。这种方案的缺点是播放动画的节点只能加载一张图片资源,当我们要实现一个如下的动画时,

  

  如果单从代码实现需要创建多个精灵,还要绑定各个精灵之间的协调和联动,总之会非常非常的麻烦。

  骨骼动画可以兼容以上两种方法的优点,同时不包含它们的缺点。所以现在越来越多的公司使用Cocos Studio来制作动画。

      要使用Cocos Studio 首先要到官网 http://cn.cocos2d-x.org/download 下载你需要的Studio 版本,由于Cocos2d-x引擎本身的版本迭代速度比较快,有些版本的Studio并不能与引擎兼容,这里附上论坛上一个较为详细的版本对应下载 http://www.cocoachina.com/bbs/read.php?tid=154886。我使用的是刚发布不久的3.2版引擎,Cocos Studio 1.5.0.1能够对其兼容。

  初次使用我想完成两个学习目标:

  第一是学会制作骨骼动画,http://www.cocoachina.com/bbs/read.php?tid=189665 这个链接里有详细的描述,跟着一步一步来就可以了,我就不做复述了。(小插曲:我在试用mac版本刚发布的studio时发现了很多Bug,建议大家还是在window平台下使用)

  第二是在Cocos2d-x工程中使用Studio制作的动画。

  首先在Cocos2d-x的根目录下找到cocos2d-x-3.2\cocos\editor-support目录,将cocostudio目录以及其包含的文件复制到你新建工程所在目录下。然后用vs打开新建的项目,右击解决方案-》添加-》现有项目,把cocostudio添加进工程。接着右键你的工程-》属性-》c\c++-》常规-》附加包含目录,把cocostudio的目录导入进去。最后接着右键你的工程-》属性-》通用属性-》引用-》添加新引用。

  现在我们可以开始写代码了,首先要设计有个Hero类,用他来播放动画,代码如下:

 1 #ifndef __HERO_H__ 2 #define __HERO_H__ 3 #include "cocos2d.h" 4 #include "cocos-ext.h" 5 #include "CocoStudio.h" 6 USING_NS_CC; 7 using namespace cocostudio; 8 USING_NS_CC_EXT; 9 enum DIRECTION { LEFT, RIGHT, NONE };10 class Hero:public Sprite11 {12 public:13     CREATE_FUNC(Hero);14     bool init();15     void runLeft(float dt);16     void runRight(float dt);17     void attack();18     void death();19     void stop();20 21     DIRECTION dir;22     Size size;23     Armature* armature;24     bool isAniRunLeft;25     bool isAniRunRight;26 };27 #endif

   我们在Hero的init函数里初始化动画,并调用一个stop函数加载一个站立时的动画:

 1 #include "Hero.h" 2  3 bool Hero::init() 4 { 5     Sprite::init(); 6     size = Director::getInstance()->getWinSize(); 7     ArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo("Hero0.png", "Hero0.plist", "Hero.ExportJson"); 8     armature = Armature::create("Hero"); 9     armature->setScale(0.7f);10     armature->setPosition(Vec2(size.width / 2, size.height / 2));11     addChild(armature);12     stop();13     14     dir = NONE;15     isAniRunLeft = false;16     isAniRunRight = false;17     return true;18 }19 void Hero::stop()20 {21     armature->getAnimation()->play("loading");22 }23 void Hero::runLeft(float dt)24 {25     float dis = dt * 200;26     setPositionX(getPositionX() - dis);27 }28 void Hero::runRight(float dt)29 {30     float dis = dt * 200;31     setPositionX(getPositionX() + dis);32 }33 void Hero::attack()34 {35     armature->getAnimation()->play("attack");36 }37 void Hero::death()38 {39     armature->getAnimation()->play("death");40 }

  接着我们需要一个场景类,让我们的Hero在这个场景里面动起来:

 1 #ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__ 3  4 #include "cocos2d.h" 5 #include "cocos-ext.h" 6 #include "CocoStudio.h" 7 #include "Hero.h" 8 USING_NS_CC_EXT; 9 class menuDelegate10 {11 public:12     virtual void stopstate() = 0;13 };14 class Panel :public Menu15 {16 public:17     menuDelegate* exm;18     MenuItem* getSelectItem()19     {20         return _selectedItem;21     }22     static Panel* create()23     {24         Panel* ret = new Panel;25         ret->init();26         ret->autorelease();27         return ret;28     }29     bool init()30     {31         Menu::init();32         scheduleUpdate();33         return true;34     }35     void update(float dt)36     {37         if (this->getSelectItem() && this->getSelectItem()->isSelected())38             this->getSelectItem()->activate();39         else40         {41             exm->stopstate();42         }43     }44 };45 class HelloWorld : public cocos2d::Layer,public menuDelegate46 {47 public:48     // there‘s no ‘id‘ in cpp, so we recommend returning the class instance pointer49     static cocos2d::Scene* createScene();50 51     // Here‘s a difference. Method ‘init‘ in cocos2d-x returns bool, instead of returning ‘id‘ in cocos2d-iphone52     virtual bool init();53 54     // a selector callback55     void menuCloseCallback(cocos2d::Ref* pSender);56 57     // implement the "static create()" method manually58     CREATE_FUNC(HelloWorld);59 60     void stopstate();61     void update(float dt);62     void moveRight();63     void moveLeft();64     void moveAttack();65     void moveDead();66     void loadMenu();67     Hero* hero;68     Panel* menu;69 };70 #endif // __HELLOWORLD_SCENE_H__

  以下是场景类的cpp文件:

  1 #include "HelloWorldScene.h"  2   3 USING_NS_CC;  4 using namespace cocostudio;  5 Scene* HelloWorld::createScene()  6 {  7     // ‘scene‘ is an autorelease object  8     auto scene = Scene::create();  9      10     // ‘layer‘ is an autorelease object 11     auto layer = HelloWorld::create(); 12  13     // add layer as a child to scene 14     scene->addChild(layer); 15  16     // return the scene 17     return scene; 18 } 19  20 // on "init" you need to initialize your instance 21 bool HelloWorld::init() 22 { 23     ////////////////////////////// 24     // 1. super init first 25     if ( !Layer::init() ) 26     { 27         return false; 28     } 29      30     Size visibleSize = Director::getInstance()->getVisibleSize(); 31     Vec2 origin = Director::getInstance()->getVisibleOrigin(); 32  33     ///////////////////////////// 34     // 2. add a menu item with "X" image, which is clicked to quit the program 35     //    you may modify it. 36  37     // add a "close" icon to exit the progress. it‘s an autorelease object 38     auto closeItem = MenuItemImage::create( 39                                            "CloseNormal.png", 40                                            "CloseSelected.png", 41                                            CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 42      43     closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , 44                                 origin.y + closeItem->getContentSize().height/2)); 45  46     // create menu, it‘s an autorelease object 47     auto menu = Menu::create(closeItem, NULL); 48     menu->setPosition(Vec2::ZERO); 49     this->addChild(menu, 1); 50  51     ///////////////////////////// 52     // 3. add your codes below... 53  54     // add a label shows "Hello World" 55     // create and initialize a label 56      57     auto label = LabelTTF::create("Hello World", "Arial", 24); 58      59     // position the label on the center of the screen 60     label->setPosition(Vec2(origin.x + visibleSize.width/2, 61                             origin.y + visibleSize.height - label->getContentSize().height)); 62  63     // add the label as a child to this layer 64     this->addChild(label, 1); 65     loadMenu(); 66     hero = Hero::create(); 67     addChild(hero); 68     scheduleUpdate(); 69     return true; 70 } 71 void HelloWorld::update(float dt) 72 { 73     if (hero->dir == RIGHT) 74     { 75         hero->runRight(dt); 76     } 77     if (hero->dir == LEFT) 78     { 79         hero->runLeft(dt); 80     } 81 } 82 void HelloWorld::loadMenu() 83 { 84     Size size = Director::getInstance()->getWinSize(); 85     auto closeItem1 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveLeft, this)); 86     auto closeItem2 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveRight, this)); 87     auto closeItem3 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveAttack, this)); 88     auto closeItem4 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveDead, this)); 89     menu = Panel::create(); 90     menu->addChild(closeItem1); 91     menu->addChild(closeItem2); 92     menu->addChild(closeItem3); 93     menu->addChild(closeItem4); 94     menu->alignItemsHorizontally(); 95     menu->setPositionY(menu->getPositionY() / 2); 96     menu->exm = this; 97     addChild(menu); 98 } 99 100 void HelloWorld::moveRight()101 {102     if (hero->dir == NONE)103         hero->armature->getAnimation()->play("run");104     float num = hero->armature->getRotationY();105     if (num == -180)106     {107         hero->armature->setRotationY(0);108     }109     hero->dir = RIGHT;110 }111 void HelloWorld::moveLeft()112 {113     if (hero->dir == NONE)114         hero->armature->getAnimation()->play("run");115     float num = hero->armature->getRotationY();116     if (num == 0 )117     {118         hero->armature->setRotationY(-180);119     }120     hero->dir = LEFT;121 }122 void HelloWorld::moveDead()123 {124     hero->death();125 }126 void HelloWorld::moveAttack()127 {128     hero->attack();129 }130 void HelloWorld::stopstate()131 {132     if (hero->dir == NONE)133         return;134     float num = hero->armature->getRotationY();135     if (num == 0)136     {137         hero->stop();138         CCLOG("111111");139     }140     else if (num == -180)141     {142         hero->stop();143         hero->armature->setRotationY(-180);144     }145     hero->dir = NONE;146 }147 void HelloWorld::menuCloseCallback(Ref* pSender)148 {149 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)150     MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");151     return;152 #endif153 154     Director::getInstance()->end();155 156 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)157     exit(0);158 #endif159 }

  运行后的效果如下: