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

时间:2023-03-08 19:24:12

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

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

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

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

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

  骨骼动画可以兼容以上两种方法的优点,同时不包含它们的缺点。所以现在越来越多的公司使用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类,用他来播放动画,代码如下:

 #ifndef __HERO_H__
#define __HERO_H__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "CocoStudio.h"
USING_NS_CC;
using namespace cocostudio;
USING_NS_CC_EXT;
enum DIRECTION { LEFT, RIGHT, NONE };
class Hero:public Sprite
{
public:
CREATE_FUNC(Hero);
bool init();
void runLeft(float dt);
void runRight(float dt);
void attack();
void death();
void stop(); DIRECTION dir;
Size size;
Armature* armature;
bool isAniRunLeft;
bool isAniRunRight;
};
#endif

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

 #include "Hero.h"

 bool Hero::init()
{
Sprite::init();
size = Director::getInstance()->getWinSize();
ArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo("Hero0.png", "Hero0.plist", "Hero.ExportJson");
armature = Armature::create("Hero");
armature->setScale(0.7f);
armature->setPosition(Vec2(size.width / , size.height / ));
addChild(armature);
stop(); dir = NONE;
isAniRunLeft = false;
isAniRunRight = false;
return true;
}
void Hero::stop()
{
armature->getAnimation()->play("loading");
}
void Hero::runLeft(float dt)
{
float dis = dt * ;
setPositionX(getPositionX() - dis);
}
void Hero::runRight(float dt)
{
float dis = dt * ;
setPositionX(getPositionX() + dis);
}
void Hero::attack()
{
armature->getAnimation()->play("attack");
}
void Hero::death()
{
armature->getAnimation()->play("death");
}

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

 #ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__ #include "cocos2d.h"
#include "cocos-ext.h"
#include "CocoStudio.h"
#include "Hero.h"
USING_NS_CC_EXT;
class menuDelegate
{
public:
virtual void stopstate() = ;
};
class Panel :public Menu
{
public:
menuDelegate* exm;
MenuItem* getSelectItem()
{
return _selectedItem;
}
static Panel* create()
{
Panel* ret = new Panel;
ret->init();
ret->autorelease();
return ret;
}
bool init()
{
Menu::init();
scheduleUpdate();
return true;
}
void update(float dt)
{
if (this->getSelectItem() && this->getSelectItem()->isSelected())
this->getSelectItem()->activate();
else
{
exm->stopstate();
}
}
};
class HelloWorld : public cocos2d::Layer,public menuDelegate
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init(); // a selector callback
void menuCloseCallback(cocos2d::Ref* pSender); // implement the "static create()" method manually
CREATE_FUNC(HelloWorld); void stopstate();
void update(float dt);
void moveRight();
void moveLeft();
void moveAttack();
void moveDead();
void loadMenu();
Hero* hero;
Panel* menu;
};
#endif // __HELLOWORLD_SCENE_H__

  以下是场景类的cpp文件:

 #include "HelloWorldScene.h"

 USING_NS_CC;
using namespace cocostudio;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create(); // 'layer' is an autorelease object
auto layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
} // on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
} Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin(); /////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it. // add a "close" icon to exit the progress. it's an autorelease object
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/ ,
origin.y + closeItem->getContentSize().height/)); // create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, ); /////////////////////////////
// 3. add your codes below... // add a label shows "Hello World"
// create and initialize a label auto label = LabelTTF::create("Hello World", "Arial", ); // position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/,
origin.y + visibleSize.height - label->getContentSize().height)); // add the label as a child to this layer
this->addChild(label, );
loadMenu();
hero = Hero::create();
addChild(hero);
scheduleUpdate();
return true;
}
void HelloWorld::update(float dt)
{
if (hero->dir == RIGHT)
{
hero->runRight(dt);
}
if (hero->dir == LEFT)
{
hero->runLeft(dt);
}
}
void HelloWorld::loadMenu()
{
Size size = Director::getInstance()->getWinSize();
auto closeItem1 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveLeft, this));
auto closeItem2 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveRight, this));
auto closeItem3 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveAttack, this));
auto closeItem4 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png", CC_CALLBACK_0(HelloWorld::moveDead, this));
menu = Panel::create();
menu->addChild(closeItem1);
menu->addChild(closeItem2);
menu->addChild(closeItem3);
menu->addChild(closeItem4);
menu->alignItemsHorizontally();
menu->setPositionY(menu->getPositionY() / );
menu->exm = this;
addChild(menu);
} void HelloWorld::moveRight()
{
if (hero->dir == NONE)
hero->armature->getAnimation()->play("run");
float num = hero->armature->getRotationY();
if (num == -)
{
hero->armature->setRotationY();
}
hero->dir = RIGHT;
}
void HelloWorld::moveLeft()
{
if (hero->dir == NONE)
hero->armature->getAnimation()->play("run");
float num = hero->armature->getRotationY();
if (num == )
{
hero->armature->setRotationY(-);
}
hero->dir = LEFT;
}
void HelloWorld::moveDead()
{
hero->death();
}
void HelloWorld::moveAttack()
{
hero->attack();
}
void HelloWorld::stopstate()
{
if (hero->dir == NONE)
return;
float num = hero->armature->getRotationY();
if (num == )
{
hero->stop();
CCLOG("");
}
else if (num == -)
{
hero->stop();
hero->armature->setRotationY(-);
}
hero->dir = NONE;
}
void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit();
#endif
}

  运行后的效果如下:

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