首页 > 代码库 > 豪华版飞机大战系列(四)

豪华版飞机大战系列(四)

上一篇介绍了敌人类EnemySprite的实现,这篇来介绍下主角类的实现。在游戏中可以看到主角类的周围有一直在飞行的小猪,时刻跟在主角飞机的旁边,我们先介绍下PigSprite的实现,因为后面的主角飞机类要用到此类。

看PigSprite.h的实现:

#include "cocos2d.h"
USING_NS_CC;

class PigSprite : public cocos2d::Sprite
{
public:
    PigSprite();
    ~PigSprite();
    virtual bool init();  //精灵初始化
    CREATE_FUNC(PigSprite);//create函数宏

    void f_createAnimate(int count,int fps);//创建动画
    void f_followPlane(float dt);//跟随飞机

    Sprite *spritepig;
};
接下来看PigSprite.cpp中的实现:
#include "PigSprite.h"
#include "PlaneLayer.h"

PigSprite::PigSprite() {
}

PigSprite::~PigSprite() {
}

bool PigSprite::init() {
	if (!Sprite::init()) {
		return false;
	}
	Size winSize = Director::getInstance()->getWinSize();
	spritepig = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("hero_01.png"));
	this->setPosition(Point(winSize.width / 2, winSize.height / 2));
	this->addChild(spritepig);
	//设置缩放倍数为0.6,也就是变为原来的0.6
	this->setScale(0.6);
	//穿件小猪飞行动画
	f_createAnimate(3, 8);
	//时间调度函数,使每一帧都调用f_followPlane函数来保持小猪在飞机周围
	this->schedule(schedule_selector(PigSprite::f_followPlane));
	return true;
}
/**
 * 获取飞机的位置信息,使小猪的位置始终在飞机周围,函数中判断是否到达边界,以更新小猪
 * 在飞机的左边还是右边
 */
void PigSprite::f_followPlane(float dt) {
	Size winSize = Director::getInstance()->getWinSize();
	auto PlanePos = PlaneLayer::sharedPlane->getChildByTag(AIRPLANE)->getPosition();
	if (PlanePos.x + 60 + spritepig->getContentSize().width <= winSize.width) {
		this->setPosition(Point(PlanePos.x + 60 + spritepig->getContentSize().width / 2,PlanePos.y));
	} else {
		this->setPosition(Point(PlanePos.x - 60 - spritepig->getContentSize().width / 2,PlanePos.y));
	}

}
/**
 * 创建小猪飞行的动画,count为帧动画的数量,fps为每帧的间隔时间,
 * RepeatForever创建无限重复动画,让spritepig来执行这个动画
 */
void PigSprite::f_createAnimate(int count, int fps) {
	char buff[16];
	Animation *panimation = Animation::create();
	panimation->setDelayPerUnit(1.0 / fps);
	for (int id = 1; id <= count; id++) {
		sprintf(buff, "hero_0%d.png", id);
		panimation->addSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(buff));
	}
	spritepig->runAction(RepeatForever::create(Animate::create(panimation)));

}
在此不做太多的解释,代码中都有详细的注释,没有特别难的地方,在小猪跟随飞机的函数中,用到了飞机的单例类来获取飞机的位置信息,飞机的单例类在下面实现。

单例飞机类继承Layer层,在这个层中会添加跟随的小猪精灵PigSprite,看下PlaneLayer.h的实现:

#include "cocos2d.h"
#include "PigSprite.h"
USING_NS_CC;

enum Enum_Plane {
	AIRPLANE = 1,
};

class PlaneLayer: public cocos2d::Layer {
public:
	static cocos2d::Scene* createScene();//创建场景,返回所创建的场景
	virtual bool init();//init初始化函数
	void menuCloseCallback(cocos2d::Ref* pSender);//menu回调函数
	static PlaneLayer* create();//create静态函数,在其中设置单例,并调用init方法
public:
	PigSprite *mp_pig;//跟随的小猪精灵
	static PlaneLayer* sharedPlane;//全局单例标志,以此来返回单例
	void f_createSprite();//创建飞机精灵函数
public:
	bool onTouchBegan(Touch* touch, Event* pEvent);//点击开始事件响应函数
	void onTouchMoved(Touch *touch, Event *pEvent);//点击移动事件响应函数
};
各个函数功能都有详细介绍,接下来看一下PlaneLayer.cpp的实现:

#include "PlaneLayer.h"
#include "BulletSprite.h"

USING_NS_CC;
/**
 * 静态单例变量初始化
 */
PlaneLayer *PlaneLayer::sharedPlane = NULL;
/**
 * 创建场景,并添加PlaneLayer层
 */
Scene* PlaneLayer::createScene() {
	auto scene = Scene::create();
	auto layer = PlaneLayer::create();
	scene->addChild(layer);
	return scene;
}

/**
 * 创建层,并将创建的层赋值给单例变量
 */
PlaneLayer* PlaneLayer::create() {
	PlaneLayer *pRet = new PlaneLayer();
	if (pRet && pRet->init()) {
		pRet->autorelease();
		sharedPlane = pRet;//赋值给单例变量
		return pRet;
	} else {
		CC_SAFE_DELETE(pRet);
		return NULL;
	}
}

bool PlaneLayer::init() {
	if (!Layer::init()) {
		return false;
	}
	/**
	 * 加载缓存类图片,图片用TexturePacker进行打包处理,
	 * 加载生成的plist文件,也即xml文件
	 * SpriteFrameCache缓存类会根据plist中的键值对应的图片进行加载并缓存到系统中
	 * 方便从缓存中获取相应图片
	 */
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("pig.plist");
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("bullet.plist");
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("wsparticle_p01.plist");
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("nplane.plist");

	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();
	//创建closemenu
	auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",
			CC_CALLBACK_1(PlaneLayer::menuCloseCallback, this));

	closeItem->setPosition(Point(origin.x + visibleSize.width- closeItem->getContentSize().width / 2,
			origin.y + closeItem->getContentSize().height / 2));

	auto menu = Menu::create(closeItem, NULL);
	menu->setPosition(Point::ZERO);
	this->addChild(menu, 1);
	//调用创建精灵函数
	f_createSprite();
	return true;
}

/**
 * 创建飞机精灵,并添加小猪精灵,同时注册点击事件
 */
void PlaneLayer::f_createSprite() {
	Size winSize = Director::getInstance()->getWinSize();
	//创建飞机精灵
	auto plane = Sprite::create("mplane.png");
	plane->setTag(AIRPLANE);
	plane->setScale(0.7f);
	plane->setPosition(Point(winSize.width / 2 - plane->getContentSize().width / 2,winSize.height / 7));
	this->addChild(plane);
	//用先前实现的小猪类来创建小猪精灵,并添加到层中
	mp_pig = PigSprite::create();
	this->addChild(mp_pig);
	/**
	 * 注册点击响应事件
	 */
	auto touchListener = EventListenerTouchOneByOne::create();
	touchListener->setSwallowTouches(true);//不向下传递触摸事件
	touchListener->onTouchBegan = CC_CALLBACK_2(PlaneLayer::onTouchBegan, this);//触摸开始
	touchListener->onTouchMoved = CC_CALLBACK_2(PlaneLayer::onTouchMoved, this);//触摸移动
	_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener,plane);//飞机精灵注册触摸事件
}

/**
 * 触摸开始事件,
 * 主要设置飞机移动到触摸的位置
 */
void PlaneLayer::onTouchMoved(Touch *touch, Event *pEvent) {
	auto target = static_cast<Sprite*>(pEvent->getCurrentTarget());
	target->setPosition(touch->getLocation());
}

/**
 * 触摸移动事件,飞机跟随手指的移动进行移动到相应位置
 */
bool PlaneLayer::onTouchBegan(Touch* touch, Event* pEvent) {
	auto target = static_cast<Sprite*>(pEvent->getCurrentTarget());
	Point locationInNode = target->convertToNodeSpace(touch->getLocation());
	target->setPosition(touch->getLocation());
	return true;
}

/**
 * closemenu回调函数,结束游戏
 */
void PlaneLayer::menuCloseCallback(Ref* pSender) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
	return;
#endif
	Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
}

上述的介绍中添加了创建了飞机精灵同时添加了跟随的小猪精灵,也为触摸屏幕添加了相应的响应回调函数,基本上没有难度,在上述以及前几篇的工作都做好后,最后就该介绍最重要的游戏主要场景和主要层中的逻辑了。

下一篇介绍游戏主要场景,并添加游戏中的主要逻辑,即可实现游戏的主要功能了。


豪华版飞机大战系列(四)