上一篇介绍了敌人类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
}
上述的介绍中添加了创建了飞机精灵同时添加了跟随的小猪精灵,也为触摸屏幕添加了相应的响应回调函数,基本上没有难度,在上述以及前几篇的工作都做好后,最后就该介绍最重要的游戏主要场景和主要层中的逻辑了。
下一篇介绍游戏主要场景,并添加游戏中的主要逻辑,即可实现游戏的主要功能了。