从零开始学习cocoStudio(5)--骨骼动画使用方法

来源:互联网 发布:金数据怎么导出数据 编辑:程序博客网 时间:2024/05/16 06:23

骨骼动画


      当前有两种模型动画的方式:顶点动画和骨骼动画。顶点动画中,每帧动画其实就是模型特定姿态的一个“快照”。通过在帧之间插值的方法,引擎可以得到平滑的动画效果。在骨骼动画中,模型具有互相连接的“骨骼”组成的骨架结构,通过改变骨骼的朝向和位置来为模型生成动画。

      骨骼动画比顶点动画要求更高的处理器性能,但同时它也具有更多的优点,骨骼动画可以更容易、更快捷地创建。不同的骨骼动画可以被结合到一起——比如,模型可以转动头部、射击并且同时也在走路。一些引擎可以实时操纵单个骨骼,这样就可以和环境更加准确地进行交互——模型可以俯身并向某个方向观察或射击,或者从地上的某个地方捡起一个东西。多数引擎支持顶点动画,但不是所有的引擎都支持骨骼动画。

      一些引擎包含面部动画系统,这种系统使用通过音位(phoneme)和情绪修改面部骨骼集合来表达面部表情和嘴部动作。

      有关cocoStdio制作骨骼动画,可以参考下用户手册和Cocos2d-x 3.0开发(六)使用cocoStudio创建一个骨骼动画。本篇博文只是讲解怎么在cocos2d-x使用骨骼动画的。


骨骼动画使用




实现代码:


角色类:Player.h

#ifndef __CowboyScene__Player__#define __CowboyScene__Player__#include <iostream>#include "cocos2d.h"#include "cocos-ext.h"USING_NS_CC;USING_NS_CC_EXT;using namespace gui;#define WALK_SPEED 1#define WALK_LEFT 1#define WALK_RIGHT -1enum PlayerState{    IDLE = 0,      //默认    WALK,          //行走    SHOOT,         //射击    GRENADE        //子弹};class Player:public CCObject{public:    Player(CCNode* node);    void update(float dt);              //更新角色状态    void updateAnimation();             //状态判断及播放动画    void updateMovement();              //行走状态    void play(std::string animName);    //播放动画    bool isLockState();                 //锁定角色状态        inline void setState(PlayerState state) {newState = state;} //设置角色状态    void setDirection(int newDirection); //设置方向private:    CCNode* playerNode;    CCArmatureAnimation* animation;     //动画变量    PlayerState currentState;           //当前状态    PlayerState newState;               //更换状态    int direction;                      //方向    bool lockState;                     //锁定状态    void onAnimationEvent(CCArmature *pArmature, MovementEventType eventType, const char *animationID);                   //角色射击状态};#endif /* defined(__CowboyScene__Player__) */
角色类:Player.cpp

#include "Player.h"Player::Player(CCNode* playerNode):CCObject(){    CCComRender *pRender = static_cast<CCComRender*>(playerNode->getChildByTag(10004)->getComponent("CCArmature"));        this->playerNode = playerNode->getChildByTag(10004);        CCArmature* animationNode = static_cast<CCArmature*>(pRender->getNode());        this->animation = animationNode->getAnimation();    this->animation->setMovementEventCallFunc(this, movementEvent_selector(Player::onAnimationEvent));    currentState = IDLE;    newState = IDLE;    lockState = false;}//设置方向void Player::setDirection(int newDirection){    direction = newDirection;    playerNode->setScaleX(direction * fabs(playerNode->getScaleX()));}void Player::update(float dt){    if (currentState == newState || isLockState())    {        updateMovement();    }    else    {        currentState = newState;        updateAnimation();    }}void Player::updateMovement(){    CCPoint oldPos = playerNode->getPosition();    if (currentState == WALK)    {        playerNode->setPosition(oldPos.x + -direction * WALK_SPEED,oldPos.y);    }}void Player::updateAnimation(){    switch (currentState)    {        case IDLE:            animation->play("stand");            break;        case SHOOT:            animation->play("stand_fire");            break;        case WALK:            animation->play("walk");            break;        case GRENADE:            animation->play("grenade");            lockState = true;            break;        default:            break;    }}bool Player::isLockState(){    return lockState;}void Player::onAnimationEvent(cocos2d::extension::CCArmature *pArmature, cocos2d::extension::MovementEventType eventType, const char *animationID){    if (eventType == LOOP_COMPLETE) {        if (strcmp(animationID, "grenade") == 0)        {            lockState = false;            newState = IDLE;        }    }}

导入骨骼动画及使用:

HelloWorldScene.cpp

bool HelloWorld::init(){    //////////////////////////////    // 1. super init first    if ( !CCLayer::init() )    {        return false;    }        CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();    CCPoint origin = CCDirector::sharedDirector()->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    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(                                        "CloseNormal.png",                                        "CloseSelected.png",                                        this,                                        menu_selector(HelloWorld::menuCloseCallback));    pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,                                origin.y + pCloseItem->getContentSize().height/2));    // create menu, it's an autorelease object    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);    pMenu->setPosition(CCPointZero);    this->addChild(pMenu, 1);        //创建场景    CCNode* gameScene = SceneReader::sharedSceneReader()->createNodeWithSceneFile("DemoCowboy.json");    addChild(gameScene);    //创建角色    CCNode* playerNode = gameScene;    player = new Player(playerNode);    //创建按钮(控制左、右、射击)    CCComRender *pRender = static_cast<CCComRender*>(playerNode->getChildByTag(10005)->getComponent("GUIComponent"));    UILayer* ui = static_cast<UILayer*>(pRender->getNode());        UIButton * btnLeft = (UIButton*)ui->getWidgetByName("LeftButton");    btnLeft->addTouchEventListener(this, toucheventselector(HelloWorld::onMoveLeft));        UIButton* btnRight = (UIButton*)ui->getWidgetByName("RightButton");    btnRight->addTouchEventListener(this, toucheventselector(HelloWorld::onMoveRight));        UIButton* btnFire = (UIButton*)ui->getWidgetByName("FireButton");    //    btnFire->addReleaseEvent(this, coco_releaseselector(HelloWorld::onFire));    btnFire->addTouchEventListener(this, toucheventselector(HelloWorld::onFire));        //Enable update loop    this->scheduleUpdate();        return true;}
更新事件及按钮触发事件

void HelloWorld::update(float dt){    player->update(dt);}void HelloWorld::onMoveLeft(cocos2d::CCObject *pSender, TouchEventType type){    if (type == TOUCH_EVENT_BEGAN)    {        player->setDirection(WALK_LEFT);        player->setState(WALK);    }    if (type == TOUCH_EVENT_ENDED)    {        player->setState(IDLE);    }}void HelloWorld::onMoveRight(cocos2d::CCObject *pSender, TouchEventType type){    if (type == TOUCH_EVENT_BEGAN)    {        player->setDirection(WALK_RIGHT);        player->setState(WALK);    }    if (type == TOUCH_EVENT_ENDED)    {        player->setState(IDLE);    }}void HelloWorld::onFire(cocos2d::CCObject *pSender, TouchEventType type){    if (type == TOUCH_EVENT_BEGAN)    {        player->setState(SHOOT);    }    if (type == TOUCH_EVENT_ENDED)    {        player->setState(IDLE);    }}
示例资源及代码:  https://github.com/chukong/CocoStudioSamples 

0 0