您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x的初步学习二十二之模仿微信打飞机

2013-09-04 00:58 260 查看
最近有人用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时,就触发我们的飞机爆炸效果,并且移除死亡的飞机,设置分数显示,否则打击的时候,有打击动画。大体的逻辑就是这样。。。。。



。。。。。。。。。。未完。。。。。。。。。。。。。。。。。。。。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: