最近有人用2d写了模仿微信的打飞机,我参考了下,用2dx来重新写下,我们一步步来,先整理好整个项目的框架,还有逻辑。我们先写一个有开始菜单的界面,
HelloWorldScene.h:
class HelloWorld : public cocos2d::CCLayer
{
public:
// Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer)
virtual bool init();
// there's no 'id' in cpp, so we recommend to return the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// preprocessor macro for "static create()" constructor ( node() deprecated )
CREATE_FUNC(HelloWorld);
void initData();
void startGame();
}
HelloWorldScene.cpp:
bool HelloWorld::init()
{
//
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
this->initData();
CCSprite *bgSprite = CCSprite::createWithSpriteFrameName("background_2.png");
bgSprite->setPosition(ccp(wSize.width/2, wSize.height/2));
this->addChild(bgSprite, 0);
CCSprite *logoSprite = CCSprite::create("BurstAircraftLogo-hd.png");
logoSprite->setPosition(ccp(wSize.width/2, wSize.height/2+100));
this->addChild(logoSprite, 0);
CCMenuItemFont *startItem=CCMenuItemFont::create("开始游戏", this,menu_selector(HelloWorld::startGame));
startItem->setPosition(ccp(wSize.width/2, wSize.height/2-200));
startItem->setFontSizeObj(55);
startItem->setFontNameObj("Georgia-Bold");
CCMenu *pMenu = CCMenu::create(startItem, NULL);
pMenu->setPosition(CCPointZero);
this->addChild(pMenu, 1);
return true;
}
void HelloWorld::initData()
{
CCSpriteFrameCache *frameCache=CCSpriteFrameCache::sharedSpriteFrameCache();
frameCache->addSpriteFramesWithFile("gameArts-hd.plist");
}
//开始游戏
void HelloWorld::startGame()
{
CCScene *scene=CCScene::create();
GameLayer *layer=GameLayer::create();
scene->addChild(layer);
//跳跃式动画
CCDirector::sharedDirector()->replaceScene(CCTransitionJumpZoom::create(1.2f, scene));
}
很简单的界面,效果如下:
我们看下游戏界面
GameScene.h:
class GameLayer : public cocos2d::CCLayer
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
CREATE_FUNC(GameLayer);
private:
void initUI();
void initData();
void scrollBg();
void update(float t);
cocos2d::CCSprite *bgSprite1;
cocos2d::CCSprite *bgSprite2;
int bgHeight;
cocos2d::CCSprite *playSprite;
};
GameScene.cpp
bool GameLayer::init()
{
if ( !CCLayer::init() )
{
return false;
}
this->initData();
this->initUI();
//系统的刷新
this->scheduleUpdate();
return true;
}
void GameLayer::initData()
{
//背景音乐
SimpleAudioEngine::sharedEngine()->playBackgroundMusic("game_music.mp3",true);
bgHeight=480;
}
void GameLayer::initUI()
{
//背景
bgSprite1=CCSprite::createWithSpriteFrameName("background_2.png");
//锚点
bgSprite1->setAnchorPoint(ccp(0.5, 0));
bgSprite1->setPosition(ccp(320, 0));
this->addChild(bgSprite1, 0);
bgSprite2=CCSprite::createWithSpriteFrameName("background_2.png");
bgSprite2->setAnchorPoint(ccp(0.5, 0));
bgSprite2->setPosition(ccp(320, bgHeight-1));
this->addChild(bgSprite2, 0);
//玩家
playSprite=CCSprite::createWithSpriteFrameName("hero_fly_1.png");
playSprite->setPosition(ccp(300, 200));
this->addChild(playSprite, 3);
//自身动画
CCArray *array=CCArray::create();
for (int i=1; i<3; i++)
{
CCString *string=CCString::createWithFormat("hero_fly_%d.png",i);
CCSpriteFrame *frame=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(string->getCString());
array->addObject(frame);
}
CCAnimation *animation=CCAnimation::createWithSpriteFrames(array,0.1);
CCAnimate *animate=CCAnimate::create(animation);
CCRepeatForever *ac1=CCRepeatForever::create(animate);
playSprite->runAction(ac1);
}
//循环滚动背景
void GameLayer::scrollBg()
{
bgHeight--;
if (bgHeight<=0)
{
bgHeight=480;
}
bgSprite1->setPosition(ccp(bgSprite1->getPosition().x, bgHeight-480));
bgSprite2->setPosition(ccp(bgSprite2->getPosition().x, bgHeight-1));
}
//刷新
void GameLayer::update(float t)
{
this->scrollBg();
}
在上面中,我们初始化了一些数据,精灵,设置滚动的背景,当然,我们需要一步步来实现,得想好逻辑,这个功能实现了,然后接下去该实现什么,然后直到完善。。。。
OK,我们继续。。。。。
接下来我们要让我们的飞机跟随我们的手指移动,简单点,我们就用layer的触摸事件来实现,设置setTouchEnabled为true就可以了,
在GameScene.cpp的initData函数中增加
this->setTouchEnabled(true);
并且在GameScene类的头文件中重写touch事件
virtual void ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEven);
在cpp中具体实现函数
//手指移动飞机
void GameLayer::ccTouchesMoved(CCSet *pTouches,CCEvent *pEven)
{
CCSetIterator it = pTouches->begin();
CCTouch* touch = (CCTouch*)(* it);
CCPoint curLocation = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
//前一个点的坐标
CCPoint oldLocation=touch->getPreviousLocation();
CCPoint translation=ccpSub(curLocation, oldLocation);
// CCLOG("%f",translation.y);
//相减,得到偏移量
playSprite->setPosition(this->boundLayerPos(translation));
}
CCPoint GameLayer::boundLayerPos(CCPoint newPos)
{
CCPoint point=newPos;
point.x=playSprite->getPosition().x+newPos.x;
point.y=playSprite->getPosition().y+newPos.y;
if (point.x>=286*2) {
point.x = 286*2;
}else if (point.x<=33*2) {
point.x = 33*2;
}
if (point.y >=wSize.height-50*2) {
point.y = wSize.height-50*2;
}else if (point.y <= 43*2) {
point.y = 43*2;
}
return point;
}
有人说飞机位置直接设成移动的坐标点,如果不松手没关系,但一松手,再按住就出现问题了,
这样飞机就可以随着手指的移动而移动了。。。。。
然后我们增加发射子弹的功能,因为子弹是自动发射的,不需要通过发射按钮来发射子弹,所以这时候,你可以考虑就只创建一颗子弹精灵来实现,
我们在GameScene.cpp中增加新函数
//制造子弹
void GameLayer::madeBullet()
{
bullet=CCSprite::createWithSpriteFrameName("bullet1.png");
this->addChild(bullet, 1);
//音效
// SimpleAudioEngine::sharedEngine()->playEffect("bullet.mp3");
}
//重置子弹
void GameLayer::resetBullet()
{
bulletSpeed = (wSize.height - (playSprite->getPosition().y + 50))/15;
if (bulletSpeed<5)
{
bulletSpeed=5;
}
bullet->setPosition(ccp(playSprite->getPosition().x, playSprite->getPosition().y+50));
}
//开火
void GameLayer::firingBullets()
{
bullet->setPosition(ccp(bullet->getPosition().x, bullet->getPosition().y+bulletSpeed));
if (bullet->getPosition().y > wSize.height - 20)
{
this->resetBullet();
}
}
在上面中,我们创建子弹,设置子弹的速度,开火,超出屏幕时,我们重置子弹的位置,
在update(float t)函数中,我们增加函数
this->firingBullets();
OK,这样就添加完了子弹:
OK,现在飞机可以移动,并且可以发射子弹,那么现在,我们需要加入敌人的飞机。。。。。。。
我们定义一个类继承CCSprite
上代码:
EnemyPlane.h
//敌人的飞机
class EnemyPlane :public cocos2d::CCSprite
{
public:
//飞机的种类
int planeType;
//飞机的血量
int hp;
//飞机的速度s
int speed;
EnemyPlane();
~EnemyPlane();
static EnemyPlane* createWithSpriteFrameName(const char *spriteFrameName);
};
EnemyPlane.cpp
using namespace cocos2d;
using namespace CocosDenshion;
EnemyPlane::EnemyPlane()
{
}
EnemyPlane::~EnemyPlane()
{
}
EnemyPlane* EnemyPlane::createWithSpriteFrameName(const char *spriteFrameName)
{
EnemyPlane* pSprite = new EnemyPlane;
if (pSprite && pSprite->initWithSpriteFrameName(spriteFrameName))
{
pSprite->autorelease();
return pSprite;
}
CC_SAFE_DELETE(pSprite);
return NULL;
}
然后我们需要制造这个敌人的飞机,有各种类型的,
//添加飞机
void GameLayer::addEnemyPlane()
{
smallPlaneTime++;
mediumPlaneTime ++;
bigPlaneTime ++;
if (smallPlaneTime > 60)
{
EnemyPlane *smallPlane=this->makeSmallPlane();
this->addChild(smallPlane, 3);
planeArray->addObject(smallPlane);
smallPlaneTime = 0;
}
if (mediumPlaneTime > 400)
{
EnemyPlane *mediumPlane=this->makeMediumPlane();
this->addChild(mediumPlane, 3);
planeArray->addObject(mediumPlane);
mediumPlaneTime = 0;
}
if (bigPlaneTime > 700)
{
EnemyPlane *bigPlane=this->makeBigPlane();
this->addChild(bigPlane, 3);
planeArray->addObject(bigPlane);
bigPlaneTime = 0;
}
}
//制造小飞机
EnemyPlane* GameLayer::makeSmallPlane()
{
EnemyPlane *smallPlane=EnemyPlane::createWithSpriteFrameName("enemy1_fly_1.png");
smallPlane->setPosition(ccp(arc4random()%290+17, 960));
smallPlane->planeType=1;
smallPlane->hp=1;
smallPlane->speed=arc4random()%4+2;
return smallPlane;
}
//制造中等飞机
EnemyPlane* GameLayer::makeMediumPlane()
{
EnemyPlane *mediumPlane=EnemyPlane::createWithSpriteFrameName("enemy3_fly_1.png");
mediumPlane->setPosition(ccp(arc4random()%280+23, 960));
mediumPlane->planeType=3;
mediumPlane->hp=15;
mediumPlane->speed=arc4random()%3+2;
return mediumPlane;
}
//制造大飞机
EnemyPlane* GameLayer::makeBigPlane()
{
//大飞机有浆的动画
CCArray *array=CCArray::create();
for (int i=1; i<=2; i++)
{
CCString *string=CCString::createWithFormat("enemy2_fly_%i.png",i);
CCSpriteFrame *frame=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(string->getCString());
array->addObject(frame);
}
CCAnimation *animation=CCAnimation::createWithSpriteFrames(array,0.1);
CCAnimate *animate=CCAnimate::create(animation);
CCRepeatForever *ac1=CCRepeatForever::create(animate);
EnemyPlane *bigPlane=EnemyPlane::createWithSpriteFrameName("enemy2_fly_1.png");
bigPlane->setPosition(ccp(arc4random()%210+55, 1200));
bigPlane->planeType=2;
bigPlane->hp=25;
bigPlane->speed=arc4random()%2+2;
bigPlane->runAction(ac1);
array->removeAllObjects();
return bigPlane;
}
//移动飞机
void GameLayer::moveEnemyPlane()
{
for (int i=0;i<planeArray->count();i++)
{
EnemyPlane *tmpPlane=(EnemyPlane *)planeArray->objectAtIndex(i);
tmpPlane->setPosition(ccp(tmpPlane->getPosition().x,tmpPlane->getPosition().y - tmpPlane->speed));
if (tmpPlane->getPosition().y<(-75*2))
{
planeArray->removeObject(tmpPlane);
tmpPlane->removeFromParentAndCleanup(false);
}
}
}
在上面中,我们制作了不同类型的飞机,它们各有自己的特点,设置他们出现的时间,然后我们在update函数中增加
this->addEnemyPlane();
this->moveEnemyPlane();
OK,这样就有敌人的飞机啦。。。。。。。
。。。。。。。。。。。。未完。。。。
OK。。。。我们继续,接下来,我们要考虑碰撞检测了,我的飞机子弹打出来,让打中敌人的飞机,并且显示相应的分数。这里碰撞检测,我们要知道,什么跟什么碰撞了,这里很简单,飞机的子弹跟敌人的飞机有个碰撞,敌人的飞机跟我的飞机有个碰撞,目前是这么多,当然后面还有。上代码
在GameSence.h中
void collisionDetection();
void enemyPlaneBlowupAnimation(EnemyPlane *enemyPlane);
void hitAnimationToFoePlane(EnemyPlane *enemyPlane);
void blowupEnd(CCObject *object);
//得分
int scoreInt;
GameSence.cpp
//碰撞检测
void GameLayer::collisionDetection()
{
//子弹所在的矩形区域
CCRect bulletRect=bullet->boundingBox();
//敌人飞机的数组
// CCARRAY_FOREACH(<#__array__#>, <#__object__#>)
for (int i=0; i<planeArray->count(); i++)
{
EnemyPlane *enemyPlane=(EnemyPlane *)planeArray->objectAtIndex(i);
//矩形和矩形
if (bulletRect.intersectsRect(enemyPlane->boundingBox()))
{
//碰到飞机了,子弹要消失,所以这里重置
this->resetBullet();
enemyPlane->hp=enemyPlane->hp-1;
if (enemyPlane->hp<=0)
{
this->enemyPlaneBlowupAnimation(enemyPlane);
planeArray->removeObject(enemyPlane);
}
else
{
this->hitAnimationToFoePlane(enemyPlane);
}
}
}
}
//敌人飞机爆炸效果
void GameLayer::enemyPlaneBlowupAnimation(EnemyPlane *enemyPlane)
{
int animationNum = 0;
//动画帧数跟相应的分数
if (enemyPlane->planeType == 1)
{
animationNum = 4;
scoreInt += 2000;
}
if (enemyPlane->planeType == 3)
{
animationNum = 4;
scoreInt += 10000;
}
if (enemyPlane->planeType == 2)
{
animationNum = 7;
scoreInt += 40000;
}
CCString *string=CCString::createWithFormat("%i",scoreInt);
scoreLabel->setString(string->getCString());
//停止所以动画
enemyPlane->stopAllActions();
//动画效果
CCArray *array=CCArray::create();
for (int i=1; i<=animationNum; i++)
{
CCString *string=CCString::createWithFormat("enemy%i_blowup_%i.png",enemyPlane->planeType,i);
CCSpriteFrame *frame=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(string->getCString());
array->addObject(frame);
}
CCAnimation *animation=CCAnimation::createWithSpriteFrames(array,0.1);
CCAnimate *animate=CCAnimate::create(animation);
CCSequence *seq=CCSequence::create(animate,CCCallFuncN::create(this, callfuncN_selector(GameLayer::blowupEnd)),NULL);
enemyPlane->runAction(seq);
array->removeAllObjects();
if (enemyPlane->planeType == 3)
{
// SimpleAudioEngine::sharedEngine()->playEffect("enemy1_down.mp3");
}
else if (enemyPlane->planeType == 2)
{
// SimpleAudioEngine::sharedEngine()->playEffect("enemy2_down.mp3");
}
else if (enemyPlane->planeType == 1)
{
// SimpleAudioEngine::sharedEngine()->playEffect("enemy3_down.mp3");
}
}
//动画结束后的处理
void GameLayer::blowupEnd(CCObject *object)
{
EnemyPlane *enemyPlane=(EnemyPlane *)object;
enemyPlane->removeFromParentAndCleanup(false);
}
//飞机被击打的动画
void GameLayer::hitAnimationToFoePlane(EnemyPlane *enemyPlane)
{
//中等飞机
if (enemyPlane->planeType==3)
{
if (enemyPlane->hp==13)
{
CCArray *array=CCArray::create();
for (int i=1; i<=2; i++)
{
CCString *string=CCString::createWithFormat("enemy3_hit_%i.png",i);
CCSpriteFrame *frame=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(string->getCString());
array->addObject(frame);
}
CCAnimation *animation=CCAnimation::createWithSpriteFrames(array,0.1);
CCAnimate *animate=CCAnimate::create(animation);
CCRepeatForever *ac1=CCRepeatForever::create(animate);
enemyPlane->runAction(ac1);
array->removeAllObjects();
}
}
//大飞机
else if (enemyPlane->planeType==2)
{
if (enemyPlane->hp==20)
{
CCArray *array=CCArray::create();
for (int i=1; i<=1; i++)
{
CCString *string=CCString::createWithFormat("enemy2_hit_%i.png",i);
CCSpriteFrame *frame=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(string->getCString());
array->addObject(frame);
}
CCAnimation *animation=CCAnimation::createWithSpriteFrames(array,0.1);
CCAnimate *animate=CCAnimate::create(animation);
CCRepeatForever *ac1=CCRepeatForever::create(animate);
enemyPlane->runAction(ac1);
array->removeAllObjects();
}
}
}
上面中,我们定义了一个碰撞检测的函数collisionDetection,通过intersectsRect函数来判断子弹的矩形区域是否在敌人飞机的矩形区域内,打一下少一滴血,当血小于等于0时,就触发我们的飞机爆炸效果,并且移除死亡的飞机,设置分数显示,否则打击的时候,有打击动画。大体的逻辑就是这样。。。。。
。。。。。。。。。。未完。。。。。。。。。。。。。。。。。。。。。。。。