cocos2d-x 3.2 |飞机大战:碰撞与分数

来源:互联网 发布:windows系统常用命令 编辑:程序博客网 时间:2024/05/22 11:30
cocos2d-x 3.2 |碰撞与分数
前情提要:飞机大战第五篇 实现碰撞分数
思路:游戏里物体与物体的碰撞每帧都会检测 这里我们利用前面讲过的贪吃蛇移动原理 利用update方法来实时检测
如下:新建类----->Game
第一步:Game类(实现主要的游戏逻辑模块)
Game.h

//引入需要用到的类
#include <stdio.h>#include "cocos2d.h"#include "cocos-ext.h"#include "cocosGUI.h"#include "Bullet.h"#include "Enemy.h"#include "Boom.h"#include "Tool.h"USING_NS_CC;using namespace cocos2d;class Game:Layer{public:    Vector<Bullet *> allBullet;//集合:子弹    float startX,startY;    CREATE_FUNC(Game);    static Scene * CreateScene();    bool init();    virtual bool onTouchBegan(Touch *touch, Event *unused_event);//触摸检测 按下    virtual void onTouchMoved(Touch *touch, Event *unused_event);<span style="font-family: Arial, Helvetica, sans-serif;">//触摸检测 移动</span>    void newBullet(float t);//产生子弹    void moveBullet(float t);//移动子弹    Vector<Enemy *> allEnemy;//<span style="font-family: Arial, Helvetica, sans-serif;">集合:</span><span style="font-family: Arial, Helvetica, sans-serif;">敌机</span>    void newEnemy(float t);//产生敌机    void moveEnemy(float t);//移动敌机    void update(float t);//游戏逻辑 碰撞检测    int m_score;    void reCallBack(Ref * obj);    Vector<Tool *> allTool;//集合:道具};
Game.cpp
#include "Game.h"#include "BackGround.h"#include "Plane.h"#include "MainMenu.h"#include "SimpleAudioEngine.h"#include "cocosGUI.h"#include "GameOver.h"#include "Tool.h"#include "Enemy.h"using namespace ui;using namespace CocosDenshion;USING_NS_CC;Scene * Game::CreateScene(){    auto scene=Scene::create();    auto layer=Game::create();    scene->addChild(layer);    return scene;}bool Game::init(){    if (!Layer::init())    {        return false;    }        //创建 返回 按钮    auto menurt=MenuItemLabel::create(Label::createWithSystemFont("返回", "", 32),CC_CALLBACK_1(Game::reCallBack, this));    menurt->setAnchorPoint(Vec2::ZERO);    menurt->setPosition(600-30,Director::getInstance()->getWinSize().height-36);    menurt->setColor(Color3B::GREEN);        //创建菜单    auto menu=Menu::create(menurt,nullptr);    menu->setPosition(Vec2::ZERO);    this->addChild(menu,2);        //添加背景    auto bk=BackGround::create();    this->addChild(bk);    //添加飞机    auto fly1=Plane::create();    this->addChild(fly1,1);    fly1->moveTo(100,100);    fly1->setTag(10);        //处理飞机的HP    for (int i=0; i<fly1->hp; i++)    {        auto sphp=Sprite::create("hp_1.png");        sphp->setTag(1000+i);        this->addChild(sphp);        sphp->setAnchorPoint(Vec2(0,1));        sphp->setPosition(Vec2(i*sphp->getContentSize().width+3*i,Director::getInstance()->getWinSize().height));    }    //控制飞机飞行    auto listener=EventListenerTouchOneByOne::create();//创建侦听    listener->onTouchBegan=CC_CALLBACK_2(Game::onTouchBegan, this);//定义侦听的回调    listener->onTouchMoved=CC_CALLBACK_2(Game::onTouchMoved, this);    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);//将侦听添加到事件分发器中        //产生子弹 计划任务    this->schedule(schedule_selector(Game::newBullet),0.2);//每隔200毫秒产生一次子弹    this->schedule(schedule_selector(Game::moveBullet),0.01);        //产生敌机    this->schedule(schedule_selector(Game::newEnemy),1);    this->schedule(schedule_selector(Game::moveEnemy),0.01);        //实现游戏逻辑    this->scheduleUpdate();    //分数显示器1    this->m_score=0;    auto tscore=TextAtlas::create("0000", "img_num_dis.png",17 , 22, "0");    this->addChild(tscore,12);    tscore->setTag(210);    tscore->setPosition(Vec2(Director::getInstance()->getWinSize().width/2,                             Director::getInstance()->getWinSize().height-64));        //分数显示2//    auto scoreLb = Label::createWithSystemFont(StringUtils::format("分数:%d",score), "", 32);//    scoreLb->setAnchorPoint(Vec2::ZERO);//    scoreLb->setColor(Color3B::GREEN);//    scoreLb->setPosition(0,Director::getInstance()->getWinSize().height-36);//    scoreLb->setTag(123);//    this->addChild(scoreLb,2);    return true;}//返回主菜单void Game::reCallBack(Ref * obj){    auto scene=MainMenu::CreateScene();    Director::getInstance()->replaceScene(scene);}//按下bool Game::onTouchBegan(Touch *touch, Event *unused_event){    this->startX=touch->getLocation().x;    this->startY=touch->getLocation().y;    return true;}//移动void Game::onTouchMoved(Touch *touch, Event *unused_event){    float mx=touch->getLocation().x-startX;    float my=touch->getLocation().y-startY;    auto fly1=(Plane *)this->getChildByTag(10);    fly1->moveTo(fly1->px+mx, fly1->py+my);    this->startX=touch->getLocation().x;    this->startY=touch->getLocation().y;}void Game::newBullet(float t)//产生子弹{    auto fly1=(Plane *)this->getChildByTag(10);    Bullet * bt=Bullet::newBullet(1, 0,fly1->px,fly1->py);    allBullet.pushBack(bt);    this->addChild(bt);    //子弹音效    SimpleAudioEngine::getInstance()->playEffect("launch_1.wav");}void Game::moveBullet(float t)//移动子弹{    for (int i=0;i<allBullet.size();i++)    {        Bullet * nowB=allBullet.at(i);        nowB->moveTo(nowB->px, nowB->py+15);        if (nowB->py>Director::getInstance()->getWinSize().height)        {            allBullet.erase(i);            this->removeChild(nowB);            i--;        }    }    }void Game::newEnemy(float t){    int type=random()%10;    if (type < 3)    {        type = 1;    }    else if (type > 8)    {        type = 2;    }else    {        type = 1;    }    int ex=random()%(int)Director::getInstance()->getWinSize().width;    Enemy * news=Enemy::createEnemy(type, ex, Director::getInstance()->getWinSize().height+200);    allEnemy.pushBack(news);//将新产生的敌机添加到集合    this->addChild(news);   //在当前GAME图层添加敌机层}void Game::moveEnemy(float t){    for (int i=0; i<allEnemy.size(); i++)    {        //获取第i架敌机        Enemy * nowE=allEnemy.at(i);        nowE->moveTo(nowE->ex, nowE->ey-5);        if (nowE->ey<-nowE->eSprite->getContentSize().height)        {            allEnemy.erase(i);            this->removeChild(nowE);            i--;        }    }}void Game::update(float t){    //创建一个Label层 获取计数器标签    //auto scoreLb = (Label *)this->getChildByTag(123);    //碰撞检测    if (allEnemy.size()==0 || allBullet.size()==0)    {        return;    }    auto fly1=(Plane *)this->getChildByTag(10);    //判断飞机和道具    for (int j = 0; j<allTool.size(); j++)    {        //得到第j架敌机        Tool * nowTool=allTool.at(j);        Rect br(fly1->px,                fly1->py,                fly1->getChildByTag(10)->getContentSize().width,                fly1->getChildByTag(10)->getContentSize().height);        //敌机的矩形大小        Rect er(nowTool->tx,                nowTool->ty,                nowTool->sp->getContentSize().width,                nowTool->sp->getContentSize().height);        if (br.intersectsRect(er))        {//碰撞检测到两个矩形相交            //判断吃到哪种道具            switch (nowTool->type) {                case 1://hp                {                    fly1->hp++;                    int i=fly1->hp-1;                    auto sphp=Sprite::create("hp_1.png");                    sphp->setTag(1000+i);                    this->addChild(sphp);                    sphp->setAnchorPoint(Vec2(0,1));                    sphp->setPosition(Vec2(i*sphp->getContentSize().width+3*i,Director::getInstance()->getWinSize().height));                }                    break;                case 2://炸雷                {                    //所有敌机都销毁                    while (allEnemy.size()>0)                    {                        Enemy * nowEnemy=allEnemy.at(0);                        Boom * boom=Boom::createBoom(2, nowEnemy->ex, nowEnemy->ey);                        this->addChild(boom,10);                        //爆炸一次 总增加分数                        this->m_score+=300;                        allEnemy.eraseObject(nowEnemy);                        nowEnemy->removeFromParentAndCleanup(true);                    }                    //播放音效                    SimpleAudioEngine::getInstance()->playEffect("launch_1.wav");                    //播放爆炸粒子                    Boom *  boom=Boom::createBoom(2,                                               Director::getInstance()->getWinSize().width/2,                                               Director::getInstance()->getWinSize().height/2);                    this->addChild(boom,15);                }                                        break;                case 3://激光                                        break;                case 4://散弹                                        break;                                }            //敌机消失            nowTool->unscheduleAllSelectors();            nowTool->removeFromParentAndCleanup(true);            allTool.eraseObject(nowTool);            j--;        }        }        for (int j = 0; j<allEnemy.size(); j++)    {        //得到第j架敌机        Enemy * nowEnemy=allEnemy.at(j);        //子弹的矩形大小        Rect br(fly1->px,                fly1->py,                fly1->getChildByTag(10)->getContentSize().width,                fly1->getChildByTag(10)->getContentSize().height);        //敌机的矩形大小         Rect er(nowEnemy->ex,                nowEnemy->ey,                nowEnemy->eSprite->getContentSize().width,                nowEnemy->eSprite->getContentSize().height);        if (br.intersectsRect(er))        {//碰撞检测到两个矩形相交            //敌机消失            allEnemy.eraseObject(nowEnemy);            nowEnemy->removeFromParentAndCleanup(true);            j--;            //掉血音效            SimpleAudioEngine::getInstance()->playEffect("skill_1.wav");            //我方Hp--            if (fly1->hp>0)            {                this->removeChildByTag(1000+fly1->hp-1);                fly1->hp=fly1->hp-1;            }            if(fly1->hp<=0)            {//Game Over                //创建一个场景                auto scene=GameOver::createScene();                                //将场景覆盖到Game Over 并释放之前场景                Director::getInstance()->replaceScene(scene);            }        }    }    //判断子弹 是否碰到敌机    for (int i=0; i<allBullet.size(); i++)    {                //得到第i颗子弹        Bullet * nowBullet=allBullet.at(i);        for (int j = 0; j<allEnemy.size(); j++)        {            //得到第j架敌机            Enemy * nowEnemy=allEnemy.at(j);            //子弹的矩形大小            Rect br(nowBullet->px,                    nowBullet->py,                    nowBullet->bt->getContentSize().width,                    nowBullet->bt->getContentSize().height);            //敌机的矩形大小            Rect er(nowEnemy->ex,                    nowEnemy->ey,                    nowEnemy->eSprite->getContentSize().width,                    nowEnemy->eSprite->getContentSize().height);            if (br.intersectsRect(er))            {                    //检测到两个矩形相交 子弹消失                    allBullet.eraseObject(nowBullet);                    nowBullet->removeFromParentAndCleanup(true);                    i--;                    nowEnemy->hp=nowEnemy->hp-1;                    if(nowEnemy->hp<=0)                    {                        //爆炸                        if(nowEnemy->type==1)                        {                            Boom * boom=Boom::createBoom(1, nowEnemy->ex, nowEnemy->ey);                            this->addChild(boom);                            //scoreLb->setString(StringUtils::format("分数:%d",score+=40));                            //增加分数                            this->m_score+=40;                        }                        else                        {                            Boom * boom=Boom::createBoom(2, nowEnemy->ex, nowEnemy->ey);                            this->addChild(boom);                            //scoreLb->setString(StringUtils::format("分数:%d",score+=60));                            this->m_score+=60;                        }                        //分数增加器                        auto score1=(TextAtlas *)this->getChildByTag(210);                        score1->setString(StringUtils::format("%d",m_score));                                                //爆炸音效                        SimpleAudioEngine::getInstance()->playEffect("launch_2.wav");                                                //道具处理                        if (nowEnemy->toolID>0) {                            //掉落道具                            auto tool=Tool::newTool(nowEnemy->toolID,nowEnemy->ex,nowEnemy->ey);                            this->addChild(tool);                            allTool.pushBack(tool);                        }                                                allEnemy.eraseObject(nowEnemy);                        nowEnemy->removeFromParentAndCleanup(true);                        j--;                                            }                    break;//退出这次循环            }        }    }}

总结:至此利用5个篇章简单实现了一下飞机大战的主要核心内容,希望对读者有帮
后期还有两个番外篇:游戏分数保存+安卓导出调试(因为安卓实在是让人蛋疼)
ps:游戏中用到的素材与音效请自行替换。


0 0
原创粉丝点击