EllipseBy.h:
#ifndef _ELLIPSEBY_H_
#define _ELLIPSEBY_H_
#include "cocos2d.h"
USING_NS_CC;
#define PI 3.14159
//椭圆的参数信息
struct EllipseConfig
{
//椭圆a的长度
float ellipseA;
//椭圆b的长度
float ellipseB;
//椭圆的中心坐标
Vec2 cenPos;
//是否逆时针旋转
bool isAntiClockwise;
//目标开始旋转的位置,默认位置是在椭圆长轴右方,即值为0
float startAngle;
//目标自身的角度
float selfAngle;
};
class EllipseBy : public ActionInterval
{
public:
EllipseBy();
~EllipseBy();
//初始化函数,参数t为持续时间,config为椭圆参数
static EllipseBy * create(float t,const EllipseConfig & config);
bool initWithDuration(float t,const EllipseConfig & config);
//每帧更新当前椭圆坐标
virtual void update(float time) override;
//在动作开始前调用
virtual void startWithTarget(Node *target) override;
//动作的拷贝
virtual EllipseBy * clone() const override;
//动作的逆序
virtual EllipseBy * reverse() const override;
protected:
//获得椭圆上当前点坐标
inline Vec2 & getPosWithEllipse(float t)
{
float angle = 2 * PI * ((m_config.isAntiClockwise ? t : (1 - t)) + m_config.startAngle / 360);
return Vec2(m_config.ellipseA * cos(angle),m_config.ellipseB * sin(angle));
}
private:
EllipseConfig m_config;
};
#endif
EllipseBy.cpp:
#include "EllipseBy.h"
EllipseBy::EllipseBy()
{
}
EllipseBy::~EllipseBy()
{
}
EllipseBy * EllipseBy::create(float t,const EllipseConfig & config)
{
auto pAction = new EllipseBy();
if (pAction && pAction->initWithDuration(t,config))
{
pAction->autorelease();
}
else
{
CC_SAFE_DELETE(pAction);
}
return pAction;
}
bool EllipseBy::initWithDuration(float t,const EllipseConfig & config)
{
if (!ActionInterval::initWithDuration(t))
{
return false;
}
m_config = config;
return true;
}
EllipseBy * EllipseBy::clone() const
{
auto pAction = new EllipseBy();
pAction->initWithDuration(_duration, m_config);
pAction->autorelease();
return pAction;
}
EllipseBy * EllipseBy::reverse() const
{
EllipseConfig resConfig = m_config;
resConfig.isAntiClockwise = !m_config.isAntiClockwise;
return EllipseBy::create(_duration, m_config);
}
void EllipseBy::startWithTarget(Node *target)
{
ActionInterval::startWithTarget(target);
}
void EllipseBy::update(float time)
{
if (_target)
{
Vec2 curPos = this->getPosWithEllipse(time);
float tmpAngle = m_config.selfAngle / 180 * PI;
float newX = curPos.x * cos(tmpAngle) + curPos.y * sin(tmpAngle);
float newY = curPos.y * cos(tmpAngle) - curPos.x * sin(tmpAngle);
_target->setPosition(m_config.cenPos + Vec2(newX,newY));
}
}
LotteryTurnTest.h:
#ifndef _LOTTERY_TURN_TEST_H_
#define _LOTTERY_TURN_TEST_H_
#include "cocos2d.h"
USING_NS_CC;
class LotteryTurnTest : public cocos2d::Layer
{
public:
LotteryTurnTest();
~LotteryTurnTest();
static cocos2d::Scene * create();
virtual bool init();
protected:
void onBtnCallback(Ref * obj);
void onTurnEnd();
private:
Sprite * m_turnBg;
MenuItemSprite * m_turnArr;
Sprite * m_pBg;
ParticleSystemQuad * m_pElliRtt_1;
ParticleSystemQuad * m_pElliRtt_2;
ParticleSystemQuad * m_pCircle_1;
ParticleSystemQuad * m_pCircle_2;
};
#endif
LotteryTurnTest.cpp:
#include "LotteryTurnTest.h"
#include "EllipseBy.h"
LotteryTurnTest::LotteryTurnTest()
: m_turnBg(nullptr)
, m_turnArr(nullptr)
, m_pBg(nullptr)
, m_pElliRtt_1(nullptr)
, m_pElliRtt_2(nullptr)
, m_pCircle_1(nullptr)
, m_pCircle_2(nullptr)
{
}
LotteryTurnTest::~LotteryTurnTest()
{
}
Scene * LotteryTurnTest::create()
{
auto scene = Scene::create();
auto pLayer = new LotteryTurnTest();
if (pLayer && pLayer->init())
{
pLayer->autorelease();
scene->addChild(pLayer);
return scene;
}
else
{
CC_SAFE_DELETE(pLayer);
return NULL;
}
}
bool LotteryTurnTest::init()
{
if (!Layer::init())
{
return false;
}
auto bgSize = Director::getInstance()->getWinSize();
m_pBg = Sprite::create("LotteryTurn/bg_big.png");
m_pBg->setPosition(Vec2(bgSize.width / 2,bgSize.height / 2));
this->addChild(m_pBg);
//添加标题
auto plabel = Label::createWithTTF("LotteryTurnTest","fonts/Marker Felt.ttf",30);
plabel->setPosition(Vec2(bgSize.width / 2,bgSize.height * 0.9));
m_pBg->addChild(plabel);
//添加转盘
m_turnBg = Sprite::create("LotteryTurn/turn_bg.png");
m_turnBg->setPosition(Vec2(bgSize.width / 2,bgSize.height / 2));
m_pBg->addChild(m_turnBg);
//添加指针
auto arrNor = Sprite::create("LotteryTurn/turn_arrow.png");
auto arrSel = Sprite::create("LotteryTurn/turn_arrow.png");
arrSel->setColor(Color3B(190,190,190));
m_turnArr = MenuItemSprite::create(arrNor,arrSel,CC_CALLBACK_1(LotteryTurnTest::onBtnCallback,this));
m_turnArr->setPosition(Vec2(bgSize.width / 2,bgSize.height * 0.557));
m_turnArr->setScale(0.7);
auto pMenu = Menu::createWithItem(m_turnArr);
pMenu->setPosition(Vec2::ZERO);
m_pBg->addChild(pMenu);
//添加中奖之后的简单界面
auto awardLayer = LayerColor::create(Color4B(0,0,0,100));
awardLayer->setPosition(Point::ZERO);
awardLayer->setTag(100);
m_pBg->addChild(awardLayer,10);
awardLayer->setVisible(false);
return true;
}
void LotteryTurnTest::onBtnCallback(Ref * obj)
{
//防止多次点击
m_turnArr->setEnabled(false);
srand(unsigned(time(NULL)));
float angleZ = rand() % 720 + 720;
auto pAction = EaseExponentialOut::create(RotateBy::create(4,Vec3(0,0,angleZ)));
m_turnBg->runAction(Sequence::create(pAction,CallFunc::create(CC_CALLBACK_0(LotteryTurnTest::onTurnEnd,this)),NULL));
//添加椭圆旋转粒子效果
m_pElliRtt_1 = ParticleSystemQuad::create("LotteryTurn/whiteBall.plist");
m_pBg->addChild(m_pElliRtt_1);
m_pElliRtt_2 = ParticleSystemQuad::create("LotteryTurn/yellowBall.plist");
m_pBg->addChild(m_pElliRtt_2);
//椭圆旋转
EllipseConfig config;
config.ellipseA = 100;
config.ellipseB = 50;
config.cenPos = m_turnBg->getPosition();
config.isAntiClockwise = true;
config.startAngle = 0;
config.selfAngle = 45;
m_pElliRtt_1->runAction(RepeatForever::create( EllipseBy::create(2.5,config)));
config.startAngle = 180;
config.selfAngle = -45;
m_pElliRtt_2->runAction(RepeatForever::create(EllipseBy::create(2.5,config)));
//圈圈闪烁粒子效果
m_pCircle_1 = ParticleSystemQuad::create("LotteryTurn/bigCircle.plist");
m_pCircle_1->setPosition(m_turnBg->getPosition());
m_pBg->addChild(m_pCircle_1);
m_pCircle_1->runAction(RepeatForever::create(RotateBy::create(5,Vec3(0,0,angleZ))));
m_pCircle_2 = ParticleSystemQuad::create("LotteryTurn/smallCircle.plist");
m_pCircle_2->setPosition(m_turnBg->getPosition());
m_pBg->addChild(m_pCircle_2);
m_pCircle_2->runAction(RepeatForever::create(RotateBy::create(5,Vec3(0,0,angleZ))));
}
void LotteryTurnTest::onTurnEnd()
{
m_pElliRtt_1->removeFromParentAndCleanup(true);
m_pElliRtt_2->removeFromParentAndCleanup(true);
m_pCircle_1->removeFromParentAndCleanup(true);
m_pCircle_2->removeFromParentAndCleanup(true);
//弹出抽中奖品
((LayerColor *)m_pBg->getChildByTag(100))->setVisible(true);
auto award = Sprite::create("LotteryTurn/award.png");
award->setAnchorPoint(Vec2(0.5,0));
award->setPosition(Vec2(m_pBg->getPositionX(),m_pBg->getPositionY() * 2));
this->addChild(award);
auto bounce = EaseBounceOut::create(MoveBy::create(2,Vec2(0,-m_pBg->getPositionX() * 2)));
award->runAction(Sequence::createWithTwoActions(bounce,CallFuncN::create([=](Node * node){
award->removeFromParentAndCleanup(true);
((LayerColor *)m_pBg->getChildByTag(100))->setVisible(false);
m_turnArr->setEnabled(true);
})));
}