塔防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__
#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); }
开始界面(游戏大厅):
#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); };
#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); } }
关卡选择:
#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); };
#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); } } }
游戏界面:
#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); };
#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)); } } } } } }