塔防cocos2d

塔防游戏,类似于保卫萝卜的一种。

需要注意的是几点问题是:

  • 游戏地图是瓦片地图,设置特定的标记,用来标记哪些点是地图点,哪些是塔点。
  • 游戏关卡选择:需要在两个cpp文件传参,用的是静态成员变量。
  • 每一关的不同点是地图的不一样,根据关卡使用不同地图,无需写重复的game1.cpp,game2.cpp。
  • 每个塔对于在它范围内的物体进行攻击,一个双重循环。

展示一下效果吧:

公司Logo:

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
using namespace cocos2d;

class HelloWorld : public cocos2d::CCLayer
{
private:
    CCSprite* LG;
public:
    virtual bool init();  
    void BG();
    
    virtual void registerWithTouchDispatcher(void);
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

    static cocos2d::CCScene* scene();

    void menuCloseCallback(CCObject* pSender);

    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.h
#include "HelloWorldScene.h"
#include "hall.h"

USING_NS_CC;

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

void HelloWorld::BG() {
    CCPoint _center = ccp(1120/2, 640/2);
    CCSprite* bg = CCSprite::create("bg.png");
    this->addChild(bg);
    bg->setPosition(_center);
    LG = CCSprite::create("logo.png");
    this->addChild(LG);
    LG->setPosition(ccp(1120/2,640));

    LG->runAction(
        CCMoveTo::create(1,_center)
        );

    

}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{

    if ( !CCLayer::init() )
    {
        return false;
    }
    BG();


    
    this->setTouchEnabled(true);
    return true;
}


void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
#endif
}

void HelloWorld::registerWithTouchDispatcher(void) {
    //参数:作用范围,优先级,是否被吞噬
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
    return true;
}
void HelloWorld::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {

}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
        // 切换场景
        CCScene* pGameScene = hall::scene();
        pGameScene = CCTransitionFade::create(1.0f,pGameScene);
        CCDirector::sharedDirector()->replaceScene(pGameScene);

}
HelloWorldScene.cpp

开始界面(游戏大厅):

#ifndef _hall_H_
#endif

#define _hall_H_
#include "cocos2d.h"

using namespace cocos2d;
class hall : public CCLayer
{
private:
    CCSprite* start;
public:
    virtual bool init();
    void BG();
    static CCScene* scene();

    virtual void registerWithTouchDispatcher(void);
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

    CREATE_FUNC(hall);
};
hall.h
#include "hall.h"
#include "Customs.h"

USING_NS_CC;


CCScene* hall::scene()
{
    CCScene* pScene = CCScene::create();
    hall* pLayer = hall::create();
    pScene->addChild(pLayer);
    return pScene;
}

void hall::BG() {
    CCPoint _center = ccp(1120*0.5f, 640*0.5f);
    CCSprite* bg = CCSprite::create("background/start.png");
    this->addChild(bg);
    bg->setPosition(_center);
    
    
    start = CCSprite::create("start.png");
    this->addChild(start);
    start->setPosition(ccp(1120*0.5f,640*0.5f-150));
    
    CCSprite* fish = CCSprite::create("fish/hall.png");
    this->addChild(fish);
    fish->setScale(0.2f);
    fish->setPosition(ccp(1120,640/2));

    fish->runAction(
        CCRepeatForever::create(
            CCSequence::create(
                CCMoveTo::create(3,ccp(0,640/2)),
                CCFlipX::create(true),
                CCMoveTo::create(3,ccp(1120,640/2)),
                CCFlipX::create(false),
                NULL
                )
        )
    );
    
}

bool hall::init()
{
    if (!CCLayer::init())
    {
        return true;
    }
    BG();
    this->setTouchEnabled(true);
    return true;
}


void hall::registerWithTouchDispatcher(void) {
    //参数:作用范围,优先级,是否被吞噬
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
bool hall::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
    CCPoint touchPoint = pTouch->getLocation();
    float minx = start->getPositionX() - 275 / 2.0f;
    float maxx = start->getPositionX() + 275 / 2.0f;
    float miny = start->getPositionY() - 212 / 2.0f;
    float maxy = start->getPositionY() + 212 / 2.0f;
    if(touchPoint.x>minx && touchPoint.x<maxx && touchPoint.y > miny && touchPoint.y < maxy) {
        start->setScale(2.0f);

    }

    return true;
}
void hall::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {

}
void hall::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
    // 切换场景
    CCPoint touchPoint = pTouch->getLocation();
    float minx = start->getPositionX() - 275 / 2.0f;
    float maxx = start->getPositionX() + 275 / 2.0f;
    float miny = start->getPositionY() - 212 / 2.0f;
    float maxy = start->getPositionY() + 212 / 2.0f;
    if(touchPoint.x>minx && touchPoint.x<maxx && touchPoint.y > miny && touchPoint.y < maxy) {
        start->setScale(1.0f);
        CCScene* pGameScene = Customs::scene();
        pGameScene = CCTransitionFade::create(1.0f,pGameScene);
        CCDirector::sharedDirector()->replaceScene(pGameScene);

    }
    
}
hall.cpp

关卡选择:

#ifndef _Customs_H_
#endif

#define _Customs_H_
#include "cocos2d.h"

using namespace cocos2d;
class Customs : public CCLayer
{
private:
    CCSprite* customs[10];
public:
    virtual bool init();
    void BG();
    static CCScene* scene();
    static int lv;

    virtual void registerWithTouchDispatcher(void);
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

    CREATE_FUNC(Customs);
};
Customs.h
#include "Customs.h"
#include "game1.h"


USING_NS_CC;

CCScene* Customs::scene()
{
    CCScene* pScene = CCScene::create();
    Customs* pLayer = Customs::create();
    pScene->addChild(pLayer);
    return pScene;
}

void Customs::BG() {
    CCPoint _center = ccp(1120/2, 640/2);
    CCSprite* bg = CCSprite::create("choice.png");
    this->addChild(bg);
    bg->setPosition(_center);
    
    
    
    int k=320-150;
    char tmp[50];
    for(int i=0; i<5; i++){
        sprintf(tmp,"customs/%d.png",i+1);
        customs[i] = CCSprite::create(tmp);
        this->addChild(customs[i]);
        customs[i]->setPosition(ccp(k, 420));
        k+=150;
    }

}

int Customs::lv = 1;

bool Customs::init()
{
    if (!CCLayer::init())
    {
        return true;
    }
    
    BG();
    this->setTouchEnabled(true);
    return true;
}


void Customs::registerWithTouchDispatcher(void) {
    //参数:作用范围,优先级,是否被吞噬
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
bool Customs::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {

    return true;
}
void Customs::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {

}
void Customs::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
    // 切换场景
    
    CCPoint touchPoint = pTouch->getLocation();

    for(int i = 0 ; i < 5; i ++) {
        float minx = customs[i]->getPositionX() - 20 / 2.0f;
        float maxx = customs[i]->getPositionX() + 20 / 2.0f;
        float miny = customs[i]->getPositionY() - 40 / 2.0f;
        float maxy = customs[i]->getPositionY() + 40 / 2.0f;
        

        if(touchPoint.x>minx && touchPoint.x<maxx && touchPoint.y > miny && touchPoint.y < maxy) {
            customs[i]->setScale(1.6f);
            Customs::lv = i+1;
            CCScene* pGameScene = game1::scene();
            
            pGameScene = CCTransitionFade::create(1.0f,pGameScene);
            CCDirector::sharedDirector()->replaceScene(pGameScene);

        }
    }
    
}
Customs.cpp

 

 游戏界面:

#ifndef _game1_H_
#endif

#define _game1_H_
#include "cocos2d.h"

using namespace cocos2d;
using namespace std;




struct WayPoint {
    CCPoint pos;
    int index;
    bool operator < (const WayPoint & rhs) const {
        return index < rhs.index;
    }
};

//
struct Cannon {
    CCPoint pos;
    int width,hight;
    bool flag;
    int kind;
};

//怪物
struct Monster {
    CCSprite * sp;
    int flag;
};


class game1 : public CCLayer
{
private:
    void findPath(CCTMXTiledMap* tmxMap);
    //A关节点
    list<WayPoint> _listPoint_;
    
    //炮塔
    Cannon cannon[50];
    //炮塔个数
    int cnt;

    Monster spEnemy[50];
    int cntMonster;

    int wave;
    int wave_cnt;

    int FlagVic;
    //返回键
    CCSprite * back;
public:
    virtual bool init();
    static CCScene* scene();
    
    //背景
    void BG();
    //运动序列
    CCSequence* createMoveAction();
    virtual void registerWithTouchDispatcher(void);
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

    //默认调度器
    //void update(float dt);
    void shoot(float dt);

    CREATE_FUNC(game1);
};
game1.h
#include "game1.h"
#include "Customs.h"


USING_NS_CC;

#include "SimpleAudioEngine.h"
using namespace CocosDenshion;

CCScene* game1::scene()
{
    CCScene* pScene = CCScene::create();
    game1* pLayer = game1::create();
    pScene->addChild(pLayer);
    return pScene;
}

void game1::findPath(CCTMXTiledMap* tmxMap) {
    this->cnt = 0;
    CCTMXObjectGroup* object = tmxMap->objectGroupNamed("object");
    CCArray* objectsArray = object->getObjects();
    for(int i = 0; i < (int)objectsArray->count(); i++) {
        // 字典  map  key-value
        CCDictionary* item = (CCDictionary*)objectsArray->objectAtIndex(i);
        CCString* strX = (CCString*)item->valueForKey("x");
        CCString* strY = (CCString*)item->valueForKey("y");
        CCString* strWidth = (CCString*)item->valueForKey("width");
        CCString* strHeight = (CCString*)item->valueForKey("height");
        CCString* strWayPoint = (CCString*)item->valueForKey("waypointA");
        int index = strWayPoint->intValue();

        if(index!=0) {
            float x = strX->floatValue()+40;
            float y = strY->floatValue()+40;
            WayPoint wayPoint;
            wayPoint.pos = CCPoint(x,y);
            wayPoint.index = index;
            _listPoint_.push_back(wayPoint);
        }

        CCString *strBuild = (CCString*)item->valueForKey("build");
        int build = strBuild->intValue();
        if(build!=0) {
            float x = strX->floatValue()+40;
            float y = strY->floatValue()+40;
            cannon[this->cnt].pos = CCPoint(x,y);
            cannon[this->cnt].width =  strWidth->intValue();
            cannon[this->cnt].hight = strHeight->intValue();
            cannon[this->cnt].flag = false;
            this->cnt++;
        }

    }

    _listPoint_.sort();
    //放房子

    CCSprite* start_Point = CCSprite::create("house/house1.png");
    CCSprite* end_Point = CCSprite::create("house/house2.png");
    this->addChild(start_Point);
    start_Point->setScale(0.2);
    this->addChild(end_Point);
    end_Point->setScale(0.2);
    start_Point->setPosition(_listPoint_.begin()->pos);
    end_Point->setPosition((--_listPoint_.end())->pos);
}


// 创建寻路动作
CCSequence* game1::createMoveAction()
{
    // 临时链表
    list<WayPoint> _listPoint = this->_listPoint_;
    // 动作数组
    CCArray* actionArray = CCArray::create();
    while (_listPoint.size() > 1)
    {
        WayPoint frontPoint = _listPoint.front();
        // 删除第一个点
        _listPoint.pop_front();
        // 创建动作
        float speed = 80;
        // 计算两点之间的距离
        WayPoint nextPoint = _listPoint.front();
        float x = (frontPoint.pos.x - nextPoint.pos.x);
        float y = (frontPoint.pos.y - nextPoint.pos.y);
        float dis = sqrt(x*x + y*y);
        float t = dis / speed;
        // 创建动作
        CCMoveTo* moveTo = CCMoveTo::create(t, nextPoint.pos);
        // 将动作添加到数组
        actionArray->addObject(moveTo);
    }
    return CCSequence::create(actionArray);
}


void game1::BG() {
    CCPoint _center = ccp(1120*0.5f,640*0.5f);
    char bgtmp[50];
    sprintf(bgtmp,"background/level%d.png",Customs::lv);
    CCSprite* bg = CCSprite::create(bgtmp);
    this->addChild(bg);
    bg->setPosition(_center);
    //1.创建地图对象
    char tmp[50];
    sprintf(tmp,"tmx/map%d.tmx",Customs::lv);
    CCTMXTiledMap* tmxMap = CCTMXTiledMap::create(tmp);
    //2.绘制地图
    this->addChild(tmxMap);
    findPath(tmxMap);

    //音乐
    // 播放背景音乐
    SimpleAudioEngine::sharedEngine()
        ->playBackgroundMusic("music/backgroundmusic1.mp3",true);
    
    back = CCSprite::create("back.png");
    this->addChild(back);
    back->setPosition(ccp(1120-50,640-50));

    wave = 5;
    wave_cnt = 3;
    FlagVic = 0;
    
}

bool game1::init()
{
    if (!CCLayer::init())
    {
        return true;
    }
    
    BG();

    WayPoint wayPoint = _listPoint_.front();
    char fishtmp[50];
    cntMonster = 0;
    for(int j = 0; j < wave; j++) {
        for (int i = 0; i < wave_cnt; i++)
        {
            // 创建一个怪物
            sprintf(fishtmp,"fish/%d.png",(i+j)%12+1);
            spEnemy[cntMonster].sp = CCSprite::create(fishtmp);
            spEnemy[cntMonster].sp->setFlipX(true);
            this->addChild(spEnemy[cntMonster].sp);
            spEnemy[cntMonster].sp->setVisible(false);
            spEnemy[cntMonster].sp->setPosition(wayPoint.pos);
            spEnemy[cntMonster].flag = 10;
            spEnemy[cntMonster].sp->runAction(CCSequence::create(
                CCDelayTime::create(i*0.8f+j*10),
                CCShow::create(),
                createMoveAction(),
                CCHide::create(),
                NULL));
            cntMonster++;
        }
    }


    this->setTouchEnabled(true);
    this->schedule(schedule_selector(game1::shoot),0.5f);
    return true;
}


void game1::registerWithTouchDispatcher(void) {
    //参数:作用范围,优先级,是否被吞噬
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
bool game1::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
    return true;
}
void game1::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {

}
void game1::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
    CCPoint touchPoint = pTouch->getLocation();
    
    for(int i = 0; i < this->cnt; i++) {
        CCPoint center = cannon[i].pos;
        int wight = cannon[i].width/2;
        int hight = cannon[i].hight/2;
        if(touchPoint.x>center.x-wight&&touchPoint.x<center.x+wight&&touchPoint.y>center.y-hight&&touchPoint.y<center.y+hight) {
            CCSprite* town = CCSprite::create("cannon.png");
            this->addChild(town);
            town->setScale(0.5);
            town->setPosition(center);
            //标记该炮塔有塔了
            cannon[i].flag = true;
            //音效
            SimpleAudioEngine::sharedEngine()->playEffect("music/di.mp3");
        }
    }
    //返回选择关卡
    float minx = back->getPositionX() - 40;
    float maxx = back->getPositionX() + 40;
    float miny = back->getPositionY() - 40;
    float maxy = back->getPositionY() + 40;
    if(touchPoint.x>minx && touchPoint.x<maxx && touchPoint.y > miny && touchPoint.y < maxy) {
        back->setScale(1.1f);
        CCScene* pGameScene = Customs::scene();
        pGameScene = CCTransitionFade::create(1.0f,pGameScene);
        CCDirector::sharedDirector()->replaceScene(pGameScene);
        FlagVic = 0;
        //关闭背景音乐
        SimpleAudioEngine::sharedEngine()->stopBackgroundMusic(true);
    }
}


void game1::shoot(float dt) {
    
    for(int i = 0; i < cntMonster; i++) {
        if(spEnemy[i].flag) {
        for(int j = 0; j < cnt; j++) {
            if(cannon[j].flag) {

                CCPoint Cannon_center = cannon[j].pos;
                int hight = cannon[j].hight;
                int wight = cannon[j].width;
                //在射程范围内
                if(cannon[j].pos.getDistance(spEnemy[i].sp->getPosition())<100) {
                    CCSprite* tmp = CCSprite::create("bullet/BulletLizi_0.png");
                    this->addChild(tmp);
                    tmp->setPosition(cannon[j].pos);
                    SimpleAudioEngine::sharedEngine()->playEffect("music/bumm1.mp3");
                    tmp->runAction(CCSequence::create(CCMoveTo::create(0.1f,spEnemy[i].sp->getPosition()),CCHide::create(),NULL
                        ));
                    spEnemy[i].flag--;
                    if(!spEnemy[i].flag) {
                        SimpleAudioEngine::sharedEngine()->playEffect("music/bumm2.mp3");
                        FlagVic++;
                        spEnemy[i].sp->setVisible(false);
                    }
                    if(FlagVic==wave*wave_cnt) {
                        CCSprite* k = CCSprite::create("congratulate.png");
                        this->addChild(k);
                        k->setPosition(ccp(1120/2, 640/2));
                    }
                    //CCLOG("dist = %d",spEnemy[i].sp->getPosition().getDistance(cannon[j].pos));
                }
            }
        }
    }
    }

    

}
game1.cpp

原文地址:https://www.cnblogs.com/TreeDream/p/9316101.html