cocos2dx3.0关于实现椭圆运动

椭圆数学知识

首先椭圆一开始是有一个公式的

S=π(圆周率)×a×b(其中a,b分别是椭圆的半长轴,半短轴的长).或S=π(圆周率)×A×B/4(其中A,B分别是椭圆的长轴,短轴的长).

c1c2clone可以依据关于圆的有关公式,类比出关于椭圆公式.

这个公式是面积公式的,周长公式没有精确计算的公式,该公式就是百度来的借鉴一下。

椭圆那就有一个长半轴和短半轴根据椭圆第一定义,用a表示椭圆长半轴的长,b表示椭圆短半轴的长,且a>b>0。

 椭圆周长公式:L=2πb+4(a-b) 

椭圆周长定理:椭圆的周长等于该椭圆短半轴长为半径的圆周长(2πb)加上四倍的该椭圆长半轴长(a)与短半轴长(b)的差。

    椭圆的参数方程: x=acosθ , y=bsinθ  (θ为参数)

这里主要是用了椭圆的一个“参数方程”,还有很多就不一一介绍了百度很多都有的。。。。。。。。。。。。。。等等


a是椭圆的长半轴,b是椭圆的短半轴。 o是角度,范围是[0, 2π]。(注:自己画的画好还请见谅)


------------头文件设定------------

#ifndef __SP__OvalAction__  
#define __SP__OvalAction__  

/*
   x=acosθ , y=bsinθ  (θ为参数)
*/


#include "cocos2d.h"  
定义一个结构来包含确定椭圆的参数 
typedef struct OvalConfig {
//中心坐标
cocos2d::Vec2 centerPos;
//长半径
float a;
//短半径
float b;
//是否逆时针运动
bool moveClockDir;
//层级设置
std::pair<int, int> zOrder;
}LOvalConfig;


//椭圆的运动
class MoveOvalBy : public cocos2d::ActionInterval {
public:
MoveOvalBy();
~MoveOvalBy();
//动作持续时间 和 椭圆控制参数 初始化动作
bool initWithDuration(float dt, const OvalConfig& c);
virtual MoveOvalBy* clone() const override;
virtual MoveOvalBy* reverse() const override;
virtual void update(float dt);//运用Update函数来进行不断的坐标设定
virtual void startWithTarget(cocos2d::Node *target) override;
public:
//动作持续时间 和 椭圆控制参数 初始化动作
static MoveOvalBy* create(float dt, const OvalConfig& c);


protected:
OvalConfig _config;
//x = a * cos(t)  t = [0, 2π] 
//当期那返回一个X坐标,,,,运用的是一个参数方程
inline float getPosXAtOval(float dt) {
if (_config.moveClockDir) {
return _config.a * cos(4 * MATH_PIOVER2 * dt);
}
return _config.a * cos(4 * MATH_PIOVER2 * (1 - dt));
}
//y = b * sin(t)  t = [0, 2π] 
//当期那返回一个Y坐标,,,,运用的是一个参数方程
inline float getPosYAtOval(float dt) {
if (_config.moveClockDir) {
return _config.b * sin(4 * MATH_PIOVER2 * dt);
}
return _config.b * sin(4 * MATH_PIOVER2 * (1 - dt));
}




};

#endif 



---------------------------Cpp文件---------------------




#include "OvalActionInterval.h"


USING_NS_CC;


MoveOvalBy::MoveOvalBy()
{


}


MoveOvalBy::~MoveOvalBy()
{


}
//利用定义的椭圆的参数初始化椭圆
MoveOvalBy *MoveOvalBy::create(float dt, const OvalConfig &c)
{
auto moveOvalBy = new MoveOvalBy();
if (moveOvalBy && moveOvalBy->initWithDuration(dt, c))
{
moveOvalBy->autorelease();
return moveOvalBy;
}


return nullptr;
}


bool MoveOvalBy::initWithDuration(float dt, const OvalConfig &c)
{
if (ActionInterval::initWithDuration(dt))
{
_config = c;
return true;
}


return false;
}


void MoveOvalBy::update(float dt)
{
//用之前的坐标计算函数计算坐标
//由于需要画计算出的椭圆做值是以原点为中心的,所以需要加上我们设定的中心点坐标  


if (_target)
{
float x = getPosXAtOval(dt);
float y = getPosYAtOval(dt);
_target->setPosition(_config.centerPos + Vec2(x, y));


if (dt <= 0.5)
{
_target->setZOrder(_config.zOrder.first);
}
else
{
_target->setZOrder(_config.zOrder.second);
}
}
}


MoveOvalBy *MoveOvalBy::clone() const
{
auto moveOvalBy = new MoveOvalBy();
if (moveOvalBy && moveOvalBy->initWithDuration(_duration, _config))
{
moveOvalBy->autorelease();
return moveOvalBy;
}


return nullptr;
}


MoveOvalBy *MoveOvalBy::reverse() const
{
OvalConfig newConfig;
newConfig.a = _config.a;
newConfig.b = _config.b;
newConfig.centerPos = _config.centerPos;
newConfig.moveClockDir = !_config.moveClockDir;
newConfig.zOrder = _config.zOrder;
return MoveOvalBy::create(_duration, newConfig);
}


void MoveOvalBy::startWithTarget(Node *target)
{
ActionInterval::startWithTarget(target);
}

---------------------------------------------------------------------运用

//调用方式
auto visibleSize = Director::getInstance()->getVisibleSize();
auto s1 = Sprite::create("CloseSelected.png");
addChild(s1);
s1->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
auto s2 = Sprite::create("CloseNormal.png");
addChild(s2);


OvalConfig c;
c.a = 100;
c.b = 60;
c.centerPos = s1->getPosition();

c.moveClockDir = false;
c.zOrder.first = -1;
c.zOrder.second = 1;
s2->runAction(RepeatForever::create(MoveOvalBy::create(1.0f, c)));


----------------

代码也是借鉴几位前辈的,如果多有冒犯还请见谅,第一次写。

写这个也主要是面试的时候被问到的一个这么个问题,谨记!!!!!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值