本篇博客为我们的飞机大战来添加UFO和炸弹,UFO和炸弹的运动轨迹是不确定的,而且是曲线运动,这样的话就得使用贝塞尔曲线运动了。所以我们先来看下如何使用贝塞尔曲线。贝塞尔曲线一共有四个点组成,开始点,结束点,以及俩个控制点,开始点和结束点顾名思义就是精灵开始动作的位置和结束动作的位置,而这俩个控制点可以控制曲线的形状,ccBezierConfig变量中保存的就是这些配置信息,然后我们可以有BezierTo和BezierBy动作,BezierBy动作和BezierTo动作的区别就是By所使用的坐标都是相对坐标,配置信息中没有起始点,这是因为精灵的当前位置就是起始点,并且这个点的坐标在By看来就是0,0,,其他的坐标点是相对于这个0,0点的坐标位置,To所使用的坐标就是绝对坐标了,好了看下代码中怎么用。

用3.0实现飞机大战——贝塞尔曲线和添加UFO

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();

	//创建一个精灵用来执行贝塞尔曲线
	auto sprite = Sprite::create("sprite.png");
	sprite->setPosition(Point(visibleSize.width/2,visibleSize.height/3));
	this->addChild(sprite);

	//贝塞尔曲线一共有四个点组成,开始点,结束点,以及俩个控制点,开始点和结束点顾名思义就是精灵开始动作的
	//位置和结束动作的位置,而这俩个控制点可以控制曲线的形状,ccBezierConfig保存的就是这些配置信息
    ccBezierConfig bezier;
	bezier.controlPoint_1 = CCPoint(200,0);
	bezier.controlPoint_2 = CCPoint(200,200);
	bezier.endPosition = CCPoint(0,200);
	//BezierBy动作和BezierTo动作的区别就是By所使用的坐标都是相对坐标,上边的配置信息中没有起始点,这是因为精灵
	//的当前位置就是起始点,并且这个点的坐标在By看来就是0,0,,其他的坐标点是相对于这个0,0点的坐标位置,例如第一
	//个控制点的坐标是200,0,这个坐标不是实际中的200,0,而是相对于精灵的起始坐标x方向增大200个单位
	auto action = BezierBy::create(2.0f,bezier);
	//To所使用的坐标就是绝对坐标了,例如第一个控制点的坐标是200,0,那么它就是位于屏幕上的200,0这个坐标,最后
	//结束点的0,200也说明精灵最后移动到的点是200,0这个点
	auto action2 = BezierTo::create(2.0f,bezier);
	sprite->runAction(action2);

    return true;
}

有了上边贝塞尔曲线的知识,下面我们就来添加一下UFO吧,仍然新建一个类用来表示UFO,代码如下。

#ifndef _UFO_H_
#define _UFO_H_
#include "cocos2d.h"

USING_NS_CC;

//ufo和炸弹类,继承自sprite
class Ufo : public Sprite
{
public:
	Ufo(void);
	~Ufo(void);
public:
	bool init();
	CREATE_FUNC(Ufo);
public:
	//根据不同的纹理初始化不同的ufo和炸弹
	void initUfo(std::string name);
	int getRandomNumber(int start,int end);
};

#endif
#include "Ufo.h"

Ufo::Ufo(void)
{
}

Ufo::~Ufo(void)
{
}

bool Ufo::init()
{
	if(!Sprite::init())
		return false;

	return true;
}

void Ufo::initUfo(std::string name)
{
	this->initWithSpriteFrameName(name);

	//获得坐标
	auto size = Director::getInstance()->getWinSize();
	auto contentSize = this->getContentSize();
	//横纵坐标按照以下的方法设置
	auto point = Point(getRandomNumber(contentSize.width/2,
		size.width-this->getContentSize().width/2),
		size.height);
	this->setPosition(point);

	//设置一个曲线动作让ufo来执行
	ccBezierConfig bezier;
	//贝塞尔曲线的俩个控制点都在屏幕内
	bezier.controlPoint_1 = Point(getRandomNumber(contentSize.width/2,
		size.width-contentSize.width/2),
		getRandomNumber(contentSize.height/2,size.height-contentSize.height/2));
	bezier.controlPoint_2 = Point(getRandomNumber(contentSize.width/2,
		size.width-contentSize.width/2),
		getRandomNumber(contentSize.height/2,size.height-contentSize.height/2));
	//贝塞尔曲线的结束点是屏幕的下边,这样UFO就相当于飞走了
	bezier.endPosition = Point(getRandomNumber(contentSize.width/2,
		size.width-contentSize.width/2),-contentSize.height);

	//使用BezierTo动作,因为上边的控制点配置信息使用的都是绝对坐标点
	auto bezierAction = BezierTo::create(2.0f,bezier);
	//移除自己
	auto removeAction = RemoveSelf::create();
	auto action = Sequence::create(bezierAction,removeAction,NULL);
	//执行上边的动作
	this->runAction(action);
}

//如果要获得a~b之间的一个随机数,则应该是CCRANDOM_0_1*(b-a)+a,传入的参数就是a和b
int Ufo::getRandomNumber(int start,int end)
{
	return CCRANDOM_0_1()*(end-start)+start;
}

我们创建了一个UFO类,并且让UFO的出现位置是随机的,UFO出现了以后开始执行贝塞尔曲线运动,最后移动出屏幕并且从父节点中移除。下面需要在主场景中添加一下UFO。

//场景切换完毕调用
void MainGame::onEnterTransitionDidFinish()
{
	//必须先调用父类的函数
	Layer::onEnterTransitionDidFinish();
	//添加敌机,每秒添加一个
	this->schedule(SEL_SCHEDULE(&MainGame::addEnemy),1.0f);
	//添加子弹
	this->schedule(SEL_SCHEDULE(&MainGame::addBullet),0.08f);
	//添加UFO和炸弹
	this->schedule(SEL_SCHEDULE(&MainGame::addUfo),1.0f);
	//碰撞检测
	this->schedule(SEL_SCHEDULE(&MainGame::isHitEnemy));
}

//添加UFO和炸弹
void MainGame::addUfo(float tm)
{
	auto ufo = Ufo::create();
	int num = CCRANDOM_0_1()*3+1;
	//在不同的概率下添加不同的物品
	if(num == 1)
	{
		ufo->initUfo("ufo1.png");
	}
	else if(num == 2)
	{
		ufo->initUfo("ufo2.png");
	}
	else
	{
		ufo->initUfo("bomb.png");
	}
	this->addChild(ufo);
}

用3.0实现飞机大战——贝塞尔曲线和添加UFO