聽說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 Sprite 11 { 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 menuDelegate 10 { 11 public: 12 virtual void stopstate() = 0; 13 }; 14 class Panel :public Menu 15 { 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 else 40 { 41 exm->stopstate(); 42 } 43 } 44 }; 45 class HelloWorld : public cocos2d::Layer,public menuDelegate 46 { 47 public: 48 // there's no 'id' in cpp, so we recommend returning the class instance pointer 49 static cocos2d::Scene* createScene(); 50 51 // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone 52 virtual bool init(); 53 54 // a selector callback 55 void menuCloseCallback(cocos2d::Ref* pSender); 56 57 // implement the "static create()" method manually 58 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 #endif 153 154 Director::getInstance()->end(); 155 156 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) 157 exit(0); 158 #endif 159 }
運行後的效果如下:
cocos2dx和unity3d一樣都是游戲引擎。一款開源,跨平台的引擎。采用C++等編碼。可以在VS上編寫代碼也可以在Mac的Xcode上編寫代碼。cocos2dstudio是cocos推出的和cocos2dx配合的制作UI界面等的美工工具。
望采納。
CocosStudio只搞動畫和界面,沒有cocos2d無法實現邏輯,無法運行你的項目。Cocos2d是一個游戲開發框架,而游戲開發用到的界面可以由CocoStudio來完成。CocoStudio是由Cocos2d框架團隊做出來的一個搞界面的軟件。CocoStudio不登錄也可以使用,因為我從來都沒有登錄過。