cocos2d-x游戲角色待機和奔跑動作切換測試


粗略寫了個Player類,用來測試人物的待機動作和奔跑動作的播放,以及兩種動作的切換播放。

1,這里要用到plist文件,對於plist,我目前的理解就是:plist和xml很像,可以說就是xml, 不過在mac下面就成了plist,美術資源如果是一張有9個幀動作的圖片,那么plist文件里就應該有9個dict節點來分別對應這9個動作,每個節點里的屬性包括精靈大小、需要渲染的紋理矩形的左上角和右下角這兩個點的坐標、坐標偏移值、精靈單張原始圖片的大小...

最開始時是想通過setPostition和 setAnothorPoint來解決人物的原點位置設置,但發現可以直接在plist里設置offset偏移量來決定原點位置。

plist文件里的spriteOffset屬性正好可以用來設置原點的位置。

這里給出我自己算出的spriteOffset坐標公式:

X = 人物單幀圖片寬度的一半 減去 注冊點到圖片的右邊距    (得到值可能是負數,就要負數,不要絕對值)
Y = 人物單幀圖片高度的一半 減去 注冊點到圖片的底邊
 
2,cocos2d-x真心很贊,圖片紋理渲染優化都有處理,使用這種紋理緩存機制,可以避免重復渲染相同的紋理。
這里涉及到幾個類:

CCSpriteBatchNode, CCSpriteFrameCache, CCSpriteFrame, CCAnimation  

3, 代碼中包括觸屏之后除了人物的動作切換,還有位移、水平轉向的處理,代碼借鑒了官方test里的例子,貼心的2dx團隊呀有么有!!!

4,新手要注意,draw方法不是主動去調用的,這里是重寫了父類的draw方法,在這里繪制了一下人物的腳下畫了個十字以以表示原點位置,方便測試,

ccDrawLine()方法就是直接調用openGL ES的接口在屏幕上繪制一條線。那么draw方法是被誰調用的呢,是cocos2d-x的UI主線程。

 

//
//  Player.h
//  PlayerActionTest
//
//  Created by 嘉定 on 12-12-25.
//
//

#ifndef __PlayerActionTest__Player__
#define __PlayerActionTest__Player__

#include "cocos2d.h"
USING_NS_CC;

class Player : public CCSprite
{
public:
    Player();
    virtual ~Player();
        
    virtual bool init();
    
    virtual void draw();
    
    typedef enum
    {
        state_idle = 1,
        state_run = 2,
        state_sit = 3,
        state_UnKnown = 4
    } ActionState;
    
    typedef enum
    {
        headward_left = 1,
        headward_right = 2,
        headward_Unknow = 3
    }HeadwardType;
    
    //跑向一個點,達到目標后是否回調
    void runTo(CCPoint targetPos,bool callback);
    
    //播放某個動作動畫
    void playAction(ActionState state);
    
    //當前動作狀態
    ActionState currentActionState;
    
    //當前朝向
    HeadwardType currentHeadward;

    
    CREATE_FUNC(Player);
    
private:
    //動畫批處理節點
    CCSpriteBatchNode *idleSpriteBatch;
    CCSpriteBatchNode *runSpriteBatch;
    
    //偵動畫緩存
    CCSpriteFrameCache *idleFrameCache;
    CCSpriteFrameCache *runFrameCache;
    
    CCSprite *idleSprite;
    CCSprite *runSprite;
    
    void stopCurrentAction();
    
    //播放待機動畫
    void idle();
    //播放奔跑動畫
    void run();
    
    //跑到目標點之后回調
    //handler
    void runToCallBack();

};

#endif /* defined(__PlayerActionTest__Player__) */
//
//  Player.cpp
//  PlayerActionTest
//
//  Created by 嘉定 on 12-12-25.
//
//

#include "Player.h"

Player::Player():
    idleFrameCache(NULL),
    runFrameCache(NULL),
    idleSpriteBatch(NULL),
    runSpriteBatch(NULL),
    idleSprite(NULL),
    runSprite(NULL),
    currentActionState(Player::state_UnKnown),
    currentHeadward(Player::headward_Unknow)
{
    
}

Player::~Player()
{

}

bool Player::init()
{
    if(!CCSprite::init())
    {
        return false;
    }
    
    //默認朝向右邊
    currentHeadward = headward_right;
    
    //init total action  FrameCache
    idleFrameCache = CCSpriteFrameCache::sharedSpriteFrameCache();
    idleFrameCache->addSpriteFramesWithFile("player/heping.plist","player/heping.png");
    
    runFrameCache = CCSpriteFrameCache::sharedSpriteFrameCache();
    runFrameCache->addSpriteFramesWithFile("player/pao.plist", "player/pao.png");
    

    return true;
}

void Player::runTo(CCPoint targetPos,bool callback)
{
    this->stopAllActions();
    
    //目前用CCMoveTO,需要設定一個從當前位置到目標位置的移動時間,那么應提前算出移動所需的時間
    const float SPEED = 12;
    float playerX = this->getPosition().x;
    float playerY = this->getPosition().y;
    
    if(targetPos.x >= playerX)
    {
        this->currentHeadward = headward_right;
    }
    else
    {
        this->currentHeadward = headward_left;
    }
    this->playAction(state_run);
    
    float disX = playerX - targetPos.x;
    float disY = playerY - targetPos.y;
    

    const float DIS = sqrtf(disX * disX + disY * disY);
    float moveTime = (DIS / SPEED) / 60;

    //但是人物的移動時間要按照從當前點到touch點的真實距離來計算時間
    CCAction *action = NULL;
    if(callback)
    {
        action =  CCSequence::create(
                                     CCMoveTo::create(moveTime, targetPos),
                                     CCCallFunc::create(this, callfunc_selector(Player::runToCallBack)),
                                     NULL);
    }
    else
    {
        action = CCSequence::create(CCMoveTo::create(moveTime, targetPos),NULL);
    }

    this->runAction(action);
    
    //角度轉向
//
//        float at = (float) CC_RADIANS_TO_DEGREES(atanf(disX/disY));
//    
//        if(disX < 0)
//        {
//            if(disY < 0)
//                at = 180 + fabs(at);
//            else
//                at = 180 - fabs(at);
//       }
//      this->runAction(CCRotateTo::create(1, at));
}

void Player::playAction(ActionState state)
{
    if(currentActionState == state)
    {
        //這里邏輯有點細微,當正在向左跑時,如果點擊了人物右邊屏幕,那么不回重新創建一次奔跑的動畫變量,但是人物時需要反轉的
        //idle狀態不需要考慮這一點,跑到了就會idle,這時會自動根據之前奔跑的朝向來設定。
        if(currentActionState == state_run)
        {
            if(runSprite->isFlipX() && currentHeadward == headward_right)
            {
                runSprite->setFlipX(false);
            }
            else if(!runSprite->isFlipX() && currentHeadward == headward_left)
            {
                runSprite->setFlipX(true);
            }
        }
        return;
    }
    
    if(state == state_idle)
    {
        idle();
    }
    else if(state == state_run)
    {
        run();
    }
    else
    { 
        
    }
}

void Player::draw()
{
    ccDrawColor4B(255, 0, 0, 255);
 
    glLineWidth(6.0f);
    ccDrawLine(ccp(-20,0),ccp(20,0));
    ccDrawLine(ccp(0,15),ccp(0,-15));
}

void Player::idle()
{
    stopCurrentAction();
    
    idleSprite = CCSprite::createWithSpriteFrameName("heping_01");
    if(this->currentHeadward == headward_left)
    {
        idleSprite->setFlipX(true);
    }
    else if(this->currentHeadward == headward_right)
    {
          idleSprite->setFlipX(false);
    }
    CCSize idleSize = idleSprite->getContentSize();
    idleSpriteBatch = CCSpriteBatchNode::create("player/heping.png");
    idleSpriteBatch->addChild(idleSprite);
    addChild(idleSpriteBatch);

    //動畫幀數組
    CCArray *animatFrames = CCArray::createWithCapacity(8);
    char str[100] = {0};
    for(int i = 1;i < 8;++i)
    {
        sprintf(str, "heping_%02d",i);
        CCSpriteFrame *frame = idleFrameCache->spriteFrameByName(str);
        animatFrames->addObject(frame);
    }

    
    CCAnimation *animation = CCAnimation::createWithSpriteFrames(animatFrames,0.2f);
    idleSprite->runAction(CCRepeatForever::create(CCAnimate::create(animation)));
    currentActionState = state_idle;
}

void Player::run()
{
    stopCurrentAction();
    
    runSprite = CCSprite::createWithSpriteFrameName("run_01");
    if(this->currentHeadward == headward_left)
    {
        runSprite->setFlipX(true);
    }
    else if(this->currentHeadward == headward_right)
    {
        runSprite->setFlipX(false);
    }
    CCSize runSize = runSprite->getContentSize();
    runSpriteBatch = CCSpriteBatchNode::create("player/pao.png");
    runSpriteBatch->addChild(runSprite);
    addChild(runSpriteBatch);
    
    CCArray *animatFrames = CCArray::createWithCapacity(7);
    char str[100] = {0};
    for(int i = 1;i < 7;++i)
    {
        sprintf(str, "run_%02d",i);
        CCSpriteFrame *frame = runFrameCache->spriteFrameByName(str);
        animatFrames->addObject(frame);
    }
    
    CCAnimation *animation = CCAnimation::createWithSpriteFrames(animatFrames,0.08f);
    runSprite->runAction(CCRepeatForever::create(CCAnimate::create(animation)));

    currentActionState = state_run;
    
}

void Player::stopCurrentAction()
{
    if(currentActionState == state_idle)
    {
        idleSprite->stopAllActions();
        idleSpriteBatch->removeChild(idleSprite,true);
        removeChild(idleSpriteBatch,true);
     
    }
    else if(currentActionState == state_run)
    {
        runSprite->stopAllActions();
        runSpriteBatch->removeChild(runSprite, true);
        removeChild(runSprite,true);
    }
    else
    {
        
    }
    
    
    
    
}

void Player::runToCallBack()
{
    this->playAction(state_idle);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>frames</key>
    <dict>
        <key>run_01</key>
        <dict>
            <key>spriteSize</key>
            <string>{151, 127}</string>
            <key>textureRect</key>
            <string>{{0, 0}, {151,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_01</string>
            </array>
        </dict>
        <key>run_02</key>
        <dict>
            <key>spriteSize</key>
            <string>{151,127}</string>
            <key>textureRect</key>
            <string>{{151, 0}, {302,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_02</string>
            </array>
        </dict>
        <key>run_03</key>
        <dict>
            <key>spriteSize</key>
            <string>{151,127}</string>
            <key>textureRect</key>
            <string>{{302, 0}, {453,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_03</string>
            </array>
        </dict>
        <key>run_04</key>
        <dict>
            <key>spriteSize</key>
            <string>{151,127}</string>
            <key>textureRect</key>
            <string>{{453, 0}, {604,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_04</string>
            </array>
        </dict>
        <key>run_05</key>
        <dict>
            <key>spriteSize</key>
            <string>{151,127}</string>
            <key>textureRect</key>
            <string>{{604, 0}, {755,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_05</string>
            </array>
        </dict>
        <key>run_06</key>
        <dict>
            <key>spriteSize</key>
            <string>{151,127}</string>
            <key>textureRect</key>
            <string>{{755, 0}, {906,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_06</string>
            </array>
        </dict>
        <key>run_07</key>
        <dict>
            <key>spriteSize</key>
            <string>{151,127}</string>
            <key>textureRect</key>
            <string>{{906, 0}, {1057,127}}</string>
            <key>spriteOffset</key>
            <string>{-13, 42}</string>
            <key>textureRotated</key>
            <false/>
            <key>spriteSourceSize</key>
            <string>{151,127}</string>
            <key>aliases</key>
            <array>
                <string>run_07</string>
            </array>
        </dict>
    </dict>
    <key>metadata</key>
    <dict>
        <key>format</key>
        <integer>3</integer>
        <key>size</key>
        <string>{1057, 127}</string>
    </dict>
</dict>
</plist>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM