塔防游戏,类似于保卫萝卜的一种。
需要注意的是几点问题是:
- 游戏地图是瓦片地图,设置特定的标记,用来标记哪些点是地图点,哪些是塔点。
- 游戏关卡选择:需要在两个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 instancebool 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.xminy && 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 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.xminy && 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_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_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.y-hight&&touchPoint.y 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 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)); } } } } } }