zoukankan      html  css  js  c++  java
  • cocos2dx游戏角色待机和奔跑动作切换测试

    粗略写了个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>
  • 相关阅读:
    #1045
    PHP程序员的技术成长规划
    403 Forbidden
    读《暗时间》的思考
    常用判断重复记录的SQL语句
    PHP中生产不重复随机数的方法
    echo 1+2+"3+4+5“输出的结果是6
    GET vs. POST
    详解PHP中的过滤器(Filter)
    Session变量在PHP中的使用
  • 原文地址:https://www.cnblogs.com/JD85/p/2842271.html
Copyright © 2011-2022 走看看