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 zOrderstd::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