zoukankan      html  css  js  c++  java
  • 一个简单的游戏开发框架(七.动作Motion)

    发现还没谈到最基本也是最重要的问题,怎么画图,画动画?

    在原版cocos2d-x里画动画比较麻烦,见cocos2d-x学习笔记04:简单动画

    cocostudio扩展出CCArmature类,就比较简单了

    cocos2d::extension::CCArmature *armature = nullptr;
    armature = cocos2d::extension::CCArmature::create("name");
    armature->getAnimation()->playByIndex(0);

    从游戏逻辑的角度来看的话,比如考察一个RPG游戏的主角,通常他有站立,行走,攻击,受伤,倒地,死亡等动作,有中毒,加攻,加防等状态。一个动画会对应一个动作或状态,但是反过来不一定,一个动作可能包含不止一个动画。比如行走,在横版游戏中有两个方向,两个方向可以用一个翻转的动画来实现,还是一个动画;在ARPG游戏中可能有4个甚至8个方向,这时候行走动作不能用一个动画实现了,可能包含4或8个动画。

    因此这里可以把动作/状态抽象出来成为一个类,统称为动作Motion。一个Motion可能是一个静态图形,一个动画或几个动画。Motion和Action的区别在于,Action改变对象属性,客户端/服务器通用,Motion不改变对象属性,仅用于客户端表现。举例来讲,移动,就是一个Action(坐标改变)和一个Motion(行走动画)的组合。

    在接口篇里,没有提到Motion的概念。在概念上对象+行为就足以描述游戏逻辑,应该没有必要再增加新的实体,因此希望对Action的操作能导致Motion自动改变。考虑到,如果把“当前动作”作为对象的一个属性的话,可以认为所有Motion(动作+状态)都是随对象属性的改变而改变的,因此对Motion的操作可以通过以下方式进行:Action改变对象属性,属性改变导致动作/状态改变。

    一个对象,其所拥有的动作是有限的,可以在配置文件里配置,在对象加载的时候把所有动作一起加载进来。

    typedef struct
    {
        enum E
        {
            NONE,
            STAND,   // 站立
            MOVE,    // 移动
    
            COUNT
        };
    }Motions;
    
    class Motion
    {
    public:
        virtual ~Motion() {}
    
    public:
        virtual void InitMotion() = 0;
        virtual void RunWithObject(ObjectView* pObj) = 0;
        virtual void StopMotion() = 0;
    };
    
    class ObjectView : public Object
    {
    public:
        ObjectView();
        virtual ~ObjectView();
    
    public:
        virtual bool LoadObject(const char* fileName);
        virtual void OnPropertyChanged(uint32 propertyID, Property& oldValue);
    
        virtual Motion* CreateMotion(uint32 motionID);    // 工厂方法
    
    protected:
        std::map<uint32, Motion*>    _motions;
    };
    void ObjectView::OnPropertyChanged(uint32 propertyID, Property& oldValue)
    {
        if (Properties::MOTION == propertyID)    // 动作改变
        {
            // 停止旧动作
            uint32 oldMotion = oldValue;
            if (_motions.find(oldMotion) != _motions.end())
                _motions[oldMotion]->StopMotion();
    
            // 播放新动作
            uint32 motionID = GetProperty(Properties::MOTION);
            if (_motions.find(motionID) != _motions.end())
                _motions[motionID]->RunWithObject(this);
        }
    }

    静态图Motion:

    class MotionImage : public Motion
    {
    public:
        virtual void InitMotion();
        virtual void RunWithObject(ObjectView* pObj);
        virtual void StopMotion();
    
    private:
        Image    _image; // 等于CCSprite
    };
    void MotionImage::InitMotion()
    {
        CCTexture2D* pTex = CCTextureCache::sharedTextureCache()->textureForKey(_image._texKey.c_str());
        if (pTex)
        {
            _image._sprite->setTexture(pTex);
            _image._sprite->setTextureRect(_image._sprite->getTextureRect());
        }
    }
    
    void MotionImage::RunWithObject(ObjectView* pObj)
    {
    ObjectCocos2dx::Cast(pObj
    ->GetEngineData())->m_pNode->addChild(_image._sprite); } void MotionImage::StopMotion() { _image._sprite->removeFromParent(); }

    有两个方向的动画Motion:

    class MotionAnim2 : public Motion
    {
    public:
        MotionAnim2() : _pAnimation(nullptr), _direction(Directions::NONE) {}
        virtual ~MotionAnim2();
    
    public:
        virtual void InitMotion();
        virtual void RunWithObject(ObjectView* pObj);
        virtual void StopMotion();
    
    private:
        Animate*    _pAnimation; // 等于CCArmature
        int         _direction;
    };
    void MotionAnim2::InitMotion()
    {
        cocos2d::extension::CCArmature *armature = nullptr;
        armature = cocos2d::extension::CCArmature::create(_pAnimation->_animName.c_str());
        _pAnimation->_armature = armature;
    }
    
    void MotionAnim2::RunWithObject(ObjectView* pObj)
    {
        int direction = pObj->GetProperty(Properties::DIRECTION);
    
        if (_direction != direction)
        {
            // 镜像动画
            float sx = -_pAnimation->_armature->getScaleX();
            float sy = _pAnimation->_armature->getScaleY();
            _pAnimation->_armature->runAction(CCScaleTo::create(0.0f, sx, sy));
    
            _direction = direction;
        }
    
        _pAnimation->_armature->getAnimation()->playByIndex(0);
        // 加入对象的CCNode结点
        ObjectCocos2dx::Cast(pObj->GetEngineData())->m_pNode->addChild(_pAnimation->_armature);
    }
    
    void MotionAnim2::StopMotion()
    {
        _pAnimation->_armature->stopAllActions();
        _pAnimation->_armature->removeFromParentAndCleanup(false);
    }
  • 相关阅读:
    保持页面上滚动条原来位置
    ASP.NET页面刷新的实现方法
    绝对定位下的控件动态添加操作
    实现页面打开后滚动到最底端的效果
    获得页面下所有的控件
    获得sql列名
    PropertyUtils.getProperty和PropertyUtils.setProperty的用法详解
    Javascript 第三章
    Javascript 第五章
    Javascript 第六章
  • 原文地址:https://www.cnblogs.com/bnudc/p/3446475.html
Copyright © 2011-2022 走看看