• cocos2d 走动椭圆


    1.效果图


    艺术与规划说他想与我合作在全国率先主角光环加,椭圆形走动。

    cocos2d自带没有,參考网上的写了一个。



    2.椭圆数学知识


    有关椭圆的数学知识我已经忘光了。网上找了点资料:

    a是椭圆的长半轴,b是椭圆的短半轴。

    o是角度,范围是[0, 2π]。

    我们须要知道椭圆上的位置,能够用以下的公式:



    3.直接代码了..


    OvalActionInterval.h

    #ifndef __JumpGame__OvalInterval__
    #define __JumpGame__OvalInterval__
    
    #include "CCActionInterval.h"//包括系统延时类动作头文件
    
    using namespace cocos2d;
    
    // 定义一个结构来包括确定椭圆的參数
    typedef struct OvalConfig {
        //中心点坐标
        Vec2 centerPosition;
        //椭圆a长半轴
        float a;
        //椭圆b短半轴
        float b;
        //是否逆时针运动
        bool moveInAnticlockwise;
        //two zOrder
        std::pair<int, int> zOrder;
    } lOvalConfig;
    
    /**
      以椭圆方式移动
    */
    
    class CC_DLL MoveOvalBy : public ActionInterval{
    public:
        MoveOvalBy();
        //用“动作持续时间”和“椭圆控制參数”初始化动作
        bool initWithDuration(float t, const OvalConfig& c);
        virtual MoveOvalBy* clone() const override;
        virtual MoveOvalBy* reverse() const override;
        virtual void update(float t);//利用update函数来不断的设定坐标
        virtual void startWithTarget(Node *target) override;
    public:
        //用“动作持续时间”和“椭圆控制參数”创建动作
        static MoveOvalBy *create(float t, const OvalConfig& c);
        
    protected:
        OvalConfig _config;
        
        //x = a * cos(t)  t = [0, 2Pi]
        inline float getPositionXAtOval(float t ){//返回X坐标
            //參数方程
            if(_config.moveInAnticlockwise == false){
                return _config.a * cos(6.2831852 * (1 - t));
            }else{
                return _config.a * cos(6.2831852 * t);
            }
            
        }
        //y = b * sin(t)  t = [0, 2Pi]
        inline float getPositionYAtOval(float t ){//返回Y坐标
            //參数方程
            if(_config.moveInAnticlockwise == false){
                return _config.b * sin(6.2831852 * (1 - t));
            }else{
                return _config.b * sin(6.2831852 * t);
            }
        }
    private:
        CC_DISALLOW_COPY_AND_ASSIGN(MoveOvalBy);
    };
    
    
    #endif 
    

    OvalActionInterval.cpp

    #include "OvalActionInterval.h"
    
    MoveOvalBy::MoveOvalBy(){
    
    }
    
    //
    //MoveOvalBy
    //
    MoveOvalBy* MoveOvalBy::create(float t, const OvalConfig& c){//利用之前定义的椭圆的參数初始化椭圆
        MoveOvalBy *action = new MoveOvalBy();
        action->initWithDuration(t, c);
        action->autorelease();
        
        return action;
    }
    
    bool MoveOvalBy::initWithDuration(float t, const OvalConfig& c){
        if (ActionInterval::initWithDuration(t)){
            _config = c;
            return true;
        }
        
        return false;
    }
    void MoveOvalBy::update(float t){
        //t [0, 1]
        //log("t:%f", t);
        if (_target){
            float x = getPositionXAtOval(t);//调用之前的坐标计算函数来计算出坐标值
            float y = getPositionYAtOval(t);
            _target->setPosition(_config.centerPosition + Vec2(x, y));//因为我们画计算出的椭圆你做值是以原点为中心的。所以须要加上我们设定的中心点坐标
            
            if(t <= 0.5){
                _target->setLocalZOrder(_config.zOrder.first);
            }else{
                _target->setLocalZOrder(_config.zOrder.second);
            }
        }
    }
    
    MoveOvalBy* MoveOvalBy::clone() const{
        auto action = new MoveOvalBy();
        action->initWithDuration(_duration, _config);
        action->autorelease();
        return action;
    }
    
    MoveOvalBy* MoveOvalBy::reverse() const{
        OvalConfig newConfig;
        newConfig.centerPosition = _config.centerPosition;
        newConfig.a = _config.a;
        newConfig.b = _config.b;
        newConfig.moveInAnticlockwise = !_config.moveInAnticlockwise;
        newConfig.zOrder = _config.zOrder;
        return MoveOvalBy::create(_duration, newConfig);
    }
    
    void MoveOvalBy::startWithTarget(Node *target){
        ActionInterval::startWithTarget(target);
    }

    參考:http://blog.csdn.net/ufolr/article/details/7447773
    我这里还加上了zOrder。这样有透视效果。

    a等于b的时候就是圆形了。

    有时候在游戏中略微用上点数学知识感觉非常爽。
    调用例如以下:

    auto size = this->getContentSize();
     
        auto ball = Sprite::createWithSpriteFrameName("defenceBall.png");
        this->addChild(ball);
        ball->setPosition(Vec2(size.width * 0.5, size.height * 0.5) + Vec2(0, 10));
     
        OvalConfig config;
        config.a = 100;
        config.b = 20;
        config.centerPosition = ball->getPosition();
        config.moveInAnticlockwise = true;
        config.zOrder = make_pair(-1, 0);
        auto moveAction = MoveOvalBy::create(1.0, config);
     
        ball->runAction(RepeatForever::create(moveAction));

    http://www.waitingfy.com/archives/1343


  • 相关阅读:
    快速排序中的partition函数的枢纽元选择,代码细节,以及其标准实现
    并发包的线程池第二篇--Executors的构造
    并发包的线程池第一篇--ThreadPoolExecutor执行逻辑
    Servlet学习笔记
    npm + webpack +react
    取消eclipse启动时的subclipse Usage弹窗
    关于webpack最好的文档
    WebStorm2016.1 破解 激活
    微信web调试工具
    webstorm下设置sass
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5040004.html
Copyright © 2020-2023  润新知