元始天尊 发表于 2014-6-19 22:18:58

自己动手写魔塔游戏

花了一个礼拜,学了cocos2dx   1000行c++代码的魔塔,麻雀虽小五脏俱全,甚至比原版魔塔有创新的地方。
比如支持直接点选怪物查看其属性,楼层切换动画,,打怪时允许撤离,,等,代码如下,注释已经写得很清楚,自行研究。
里面lambda表达式是我的得意之处,对于动画的过程回调我也着重研究了一番。做什么东西都不是那么容易的,嘴说说就可以做出来的,
这个魔塔也是,因为做的时候,你才会发现哪里要怎么写才好实现。现在仍有bug,不过已经无伤大雅了。现在做了4个关卡,有兴趣的,可以自己在做

AppDelegate.cpp

#include "AppDelegate.h"
#include "MagicTower.h"
USING_NS_CC;
AppDelegate::AppDelegate() {
}
AppDelegate::~AppDelegate()
{
}
bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
      glview = GLView::create("My Game");
      director->setOpenGLView(glview);
    }
    // turn on display FPS
    director->setDisplayStats(true);
    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0 / 60);
    // create a scene. it's an autorelease object
    auto scene = MagicTowerLayerManager::getInstance().getScene();
    // run
    director->runWithScene(scene);
    return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();
    // if you use SimpleAudioEngine, it must be pause
    // SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();
    // if you use SimpleAudioEngine, it must resume here
    // SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}



AppDelegate.h

#ifndef_APP_DELEGATE_H_
#define_APP_DELEGATE_H_
#include "cocos2d.h"
/**
@brief    The cocos2d Application.
The reason for implement as private inheritance is to hide some interface call by Director.
*/
classAppDelegate : private cocos2d::Application
{
public:
    AppDelegate();
    virtual ~AppDelegate();
    /**
    @brief    Implement Director and Scene init code here.
    @return true    Initialize success, app continue.
    @return false   Initialize failed, app terminate.
    */
    virtual bool applicationDidFinishLaunching();
    /**
    @briefThe function be called when the application enter background
    @paramthe pointer of the application
    */
    virtual void applicationDidEnterBackground();
    /**
    @briefThe function be called when the application enter foreground
    @paramthe pointer of the application
    */
    virtual void applicationWillEnterForeground();
};
#endif // _APP_DELEGATE_H_



MagicTower.cpp

#include "MagicTower.h"
#include "..\external\win32-specific\icon\include\iconv.h"
#pragma comment(lib,"libiconv.lib")
USING_NS_CC;
using namespace CocosDenshion;
bool IConvConvert(const char *from_charset, const char *to_charset, const char *inbuf, int inlen, char *outbuf, int outlen)
{
iconv_t cd = iconv_open(to_charset, from_charset);
if (cd == 0) return false;
const char **pin = &inbuf;
char **pout = &outbuf;
memset(outbuf,0,outlen);
size_t ret = iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
iconv_close(cd);
return ret == (size_t)(-1) ? false : true;
}
std::string IConvConvert_GBKToUTF8(const std::string& str)
{
const char* textIn = str.c_str();
char textOut;
bool ret = IConvConvert("gb2312", "utf-8", textIn, strlen(textIn),textOut, 256);
return ret ? std::string(textOut) : std::string();
}
// on "init" you need to initialize your instance
MagicTower::MagicTower(int level)
{
thislevel=level;
auto director=Director::getInstance();
//director->getOpenGLView()->setFrameSize(416,416);
    //////////////////////////////
    // 1. super init first
    Layer::init();
    Size visibleSize = director->getVisibleSize();
    Vec2 origin = director->getVisibleOrigin();
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.
    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(MagicTower::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                              origin.y + closeItem->getContentSize().height/2));
    // create menu, it's an autorelease object
    auto menuclose = Menu::create(closeItem, NULL);
    menuclose->setPosition(Vec2::ZERO);
    this->addChild(menuclose, 1);
    /////////////////////////////
    // 3. add your codes below...
InitMap();
InitHero();
FlushBoard();
//初始换方向键回调
auto listener=EventListenerKeyboard::create();
listener->onKeyPressed=CC_CALLBACK_2(MagicTower::OnMove,this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}

void MagicTower::InitMap()
{
//加载地图背景
auto director=Director::getInstance();
Size visibleSize = director->getVisibleSize();
char mapname;
sprintf(mapname,"%d.tmx",thislevel);
map=TMXTiledMap::create(mapname);
map->setAnchorPoint(Vec2(0.5f,0.5f));
board.board=TMXTiledMap::create("background.tmx");
board.board->setAnchorPoint(Vec2(0.5f,0.5f));
map->setPosition(visibleSize.width/2,visibleSize.height/2+board.board->getContentSize().height/2);
board.board->setPosition(visibleSize.width/2,visibleSize.height/2-map->getContentSize().height/2);
addChild(map);
addChild(board.board);
InitBoard();
//初始化地图元素
Vector<SpriteFrame*> animFrames(4);
auto enemylayer=map->getLayer("enemy");
auto enemyTexture=enemylayer->getTexture();
for(int i=0;i<map->getMapSize().width;i++)
{
for(int j=0;j<map->getMapSize().height;j++)
{
   int id=enemylayer->getTileGIDAt(Vec2(i,j));
   if(id)
   {
    int index=(id-ENEMY_BEGIN)/4;
    auto frame0=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*0,blocksize*index,blocksize,blocksize));
    auto frame1=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*1,blocksize*index,blocksize,blocksize));
    auto frame2=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*2,blocksize*index,blocksize,blocksize));
    auto frame3=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*3,blocksize*index,blocksize,blocksize));
    animFrames.pushBack(frame0);
    animFrames.pushBack(frame1);
    animFrames.pushBack(frame2);
    animFrames.pushBack(frame3);
    auto animation=Animation::createWithSpriteFrames(animFrames,0.1f);
    animFrames.clear();
    auto cursprite=enemylayer->getTileAt(Vec2(i,j));
    if(!cursprite)
   return;
    cursprite->runAction(RepeatForever::create(Animate::create(animation)));
    cursprite->setUserData(ObjManager::getInstance().InitEnemyByType(id));
   }
}
}
//初始化点击事件
auto listener=EventListenerTouchOneByOne::create();
listener->onTouchBegan=(Touch* touch,Event* event)
{
Vec2 tilepos;
WorldPosToTilePos(Vec2(touch->getLocation().x-blocksize/2,touch->getLocation().y-blocksize/2),tilepos);
if(tilepos.x >= 0 && tilepos.y >=0 &&
   tilepos.x < enemylayer->getLayerSize().width && tilepos.y < enemylayer->getLayerSize().height)
{
   Sprite* node=enemylayer->getTileAt(tilepos);
   if(node)
   {
    SelectSprite(node);
   }
}
//根据位置获取单元格,设置为选中状态并刷新数据到面板
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,enemylayer);
auto itemlayer=map->getLayer("item");
for(int i=0;i<map->getMapSize().width;i++)
{
for(int j=0;j<map->getMapSize().height;j++)
{
   int id=itemlayer->getTileGIDAt(Vec2(i,j));
   auto cursprite=enemylayer->getTileAt(Vec2(i,j));
   //if(id && cursprite)
   //{
   // cursprite->setUserData(ObjManager::getInstance().InitItemByType(id));
   //}
}
}
//初始化门动画
auto doorTexture=map->getLayer("door")->getTexture();
int doordata[]={0,1,2,3};
char* doorname[]={"DOOR_YELLOW","DOOR_BLUE","DOOR_RED","DOOR_GREEN"};
for(int i=0;i<getNum(doordata);i++)
{
doordata;
auto frame0=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*0,blocksize,blocksize));
auto frame1=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*1,blocksize,blocksize));
auto frame2=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*2,blocksize,blocksize));
auto frame3=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*3,blocksize,blocksize));
animFrames.pushBack(frame0);
animFrames.pushBack(frame1);
animFrames.pushBack(frame2);
animFrames.pushBack(frame3);
auto animation=Animation::createWithSpriteFrames(animFrames,0.05f);
animFrames.clear();
AnimationCache::getInstance()->addAnimation(animation,doorname);
}
}
void MagicTower::InitBoard()
{
//初始化面板
char title;
sprintf(title,"魔塔 第%d层",thislevel);
board.maintitle=Label::createWithSystemFont(IConvConvert_GBKToUTF8(title),"黑体",30);
board.maintitle->setColor(Color3B::GREEN);
board.maintitle->setAnchorPoint(Vec2(0.5f,0.5f));
board.maintitle->setPosition(board.board->getContentSize().width/2,blocksize*5+16);
board.board->addChild(board.maintitle);
board.heroname=Label::createWithSystemFont(IConvConvert_GBKToUTF8("英雄"),"黑体",24);
board.heroname->setColor(Color3B::RED);
board.heroname->setAnchorPoint(Vec2(0.5f,0.5f));
board.heroname->setPosition(board.board->getContentSize().width/4,blocksize*5-16);
board.board->addChild(board.heroname);
board.enemyname=Label::createWithSystemFont(IConvConvert_GBKToUTF8("敌方"),"黑体",24);
board.enemyname->setColor(Color3B::RED);
board.enemyname->setAnchorPoint(Vec2(0.5f,0.5f));
board.enemyname->setPosition(board.board->getContentSize().width*7/8,blocksize*5-16);
board.board->addChild(board.enemyname);
board.life_hero=Label::createWithBMFont("myfont.fnt","life");
board.life_hero->setAnchorPoint(Vec2(0,0));
board.life_hero->setScale(0.4f);
board.life_hero->setPosition(blocksize*1,blocksize*3+5);
board.board->addChild(board.life_hero);
board.offense_hero=Label::createWithBMFont("myfont.fnt","offense");
board.offense_hero->setAnchorPoint(Vec2(0,0));
board.offense_hero->setScale(0.4f);
board.offense_hero->setPosition(blocksize*1,blocksize*2+5);
board.board->addChild(board.offense_hero);
board.defense_hero=Label::createWithBMFont("myfont.fnt","defense");
board.defense_hero->setAnchorPoint(Vec2(0,0));
board.defense_hero->setScale(0.4f);
board.defense_hero->setPosition(blocksize*1,blocksize*1+5);
board.board->addChild(board.defense_hero);
board.money_hero=Label::createWithBMFont("myfont.fnt","money");
board.money_hero->setAnchorPoint(Vec2(0,0));
board.money_hero->setScale(0.4f);
board.money_hero->setPosition(blocksize*1,blocksize*0+5);
board.board->addChild(board.money_hero);
board.yellowkey=Label::createWithBMFont("myfont.fnt","yellowkey");
board.yellowkey->setAnchorPoint(Vec2(0,0));
board.yellowkey->setScale(0.4f);
board.yellowkey->setPosition(blocksize*4,blocksize*3+5);
board.board->addChild(board.yellowkey);
board.bluekey=Label::createWithBMFont("myfont.fnt","bluekey");
board.bluekey->setAnchorPoint(Vec2(0,0));
board.bluekey->setScale(0.4f);
board.bluekey->setPosition(blocksize*4,blocksize*2+5);
board.board->addChild(board.bluekey);
board.redkey=Label::createWithBMFont("myfont.fnt","redkey");
board.redkey->setAnchorPoint(Vec2(0,0));
board.redkey->setScale(0.4f);
board.redkey->setPosition(blocksize*4,blocksize*1+5);
board.board->addChild(board.redkey);
board.life_enemy=Label::createWithBMFont("myfont.fnt","life");
board.life_enemy->setAnchorPoint(Vec2(0,0));
board.life_enemy->setScale(0.4f);
board.life_enemy->setPosition(blocksize*11,blocksize*3+5);
board.board->addChild(board.life_enemy);
board.offense_enemy=Label::createWithBMFont("myfont.fnt","offense");
board.offense_enemy->setAnchorPoint(Vec2(0,0));
board.offense_enemy->setScale(0.4f);
board.offense_enemy->setPosition(blocksize*11,blocksize*2+5);
board.board->addChild(board.offense_enemy);
board.defense_enemy=Label::createWithBMFont("myfont.fnt","defense");
board.defense_enemy->setAnchorPoint(Vec2(0,0));
board.defense_enemy->setScale(0.4f);
board.defense_enemy->setPosition(blocksize*11,blocksize*1+5);
board.board->addChild(board.defense_enemy);
}
void MagicTower::InitHero()
{
ismoving=false;
//加载英雄图片
auto director=Director::getInstance();
Size visibleSize = director->getVisibleSize();
auto heroTexture=Director::getInstance()->getTextureCache()->addImage("hero.png");
auto frame0=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*0,blocksize*1,blocksize,blocksize));
hero.heroSprite=Sprite::createWithSpriteFrame(frame0);
hero.heroSprite->setAnchorPoint(Vec2(0,0));
MoveUnitInTile(hero.nexttilepos,hero.heroSprite);
addChild(hero.heroSprite);
//存储英雄移动动画
std::string dirname[]={"down","left","right","up"};
Vector<SpriteFrame*> animFrames(4);
for(int i=0;i<4;i++)
{
auto frame0=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*0,blocksize*i,blocksize,blocksize));
auto frame1=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*1,blocksize*i,blocksize,blocksize));
auto frame2=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*2,blocksize*i,blocksize,blocksize));
auto frame3=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*3,blocksize*i,blocksize,blocksize));
animFrames.pushBack(frame0);
animFrames.pushBack(frame1);
animFrames.pushBack(frame2);
animFrames.pushBack(frame3);
auto animation=Animation::createWithSpriteFrames(animFrames,0.05f);
animation->setRestoreOriginalFrame(false);
AnimationCache::getInstance()->addAnimation(animation,dirname);
animFrames.clear();
}
//初始化攻击动画
auto attackTexture= Director::getInstance()->getTextureCache()->addImage("attack.png");
Size unitsize=attackTexture->getContentSizeInPixels();
for(int i=0;i<25;i++)
{
auto frame0=SpriteFrame::createWithTexture(attackTexture,
   Rect(i/5*unitsize.width/5,i%5*unitsize.height/5,unitsize.width/5,unitsize.height/5));
animFrames.pushBack(frame0);
}
AnimationCache::getInstance()->addAnimation(Animation::createWithSpriteFrames(animFrames,0.05f),"attack");
animFrames.clear();
}
void MagicTower::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif
    Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}
void MagicTower::OnMove(EventKeyboard::KeyCode keyCode, Event* event)
{
auto animCache=AnimationCache::getInstance();
Animation* curanimation=NULL;
Vec2 delta;
switch(keyCode)
{
case EventKeyboard::KeyCode::KEY_UP_ARROW:
   curanimation=animCache->getAnimation("up");
   delta.setPoint(0,blocksize);
   break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
   curanimation=animCache->getAnimation("down");
   delta.setPoint(0,-blocksize);
   break;
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
   curanimation=animCache->getAnimation("left");
   delta.setPoint(-blocksize,0);
   break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
   curanimation=animCache->getAnimation("right");
   delta.setPoint(blocksize,0);
   break;
default:
   return DefaultKeyboardDispatcher(keyCode);
}
//判断英雄位置是否可以移动
if(curanimation && !ismoving)
{
MoveHero(hero.heroSprite->getPosition()+delta,curanimation,keyCode);
}
}
void MagicTower::PlayHeroMovement(const Vec2& newpos,Animation* anim,EventKeyboard::KeyCode keyCode,
         const std::function<void(void)>& afteraction)
{//anim:帧动画afteraction:状态更新回调
hero.heroSprite->setSpriteFrame(anim->getFrames().at(0)->getSpriteFrame());

//移动动画和帧动画同时进行
auto spawn=Spawn::createWithTwoActions(Animate::create(anim),MoveTo::create(0.2f,newpos));
//帧动画+移动动画 -> 状态更新 -> 可通行 -> 连击检测
hero.heroSprite->runAction(Sequence::create(spawn,CallFuncN::create((Node* node)
{//所有回调函数需要写一起,否则单另作为Sequence依次执行会失效,不知道是不是bug
afteraction();
ismoving=false;
CCLog("ismoving");
FlushBoard();
if(!ismoving)
{
   if((keyCode == EventKeyboard::KeyCode::KEY_UP_ARROW && GetKeyState(VK_UP) < 0) ||
    (keyCode == EventKeyboard::KeyCode::KEY_DOWN_ARROW && GetKeyState(VK_DOWN) < 0) ||
    (keyCode == EventKeyboard::KeyCode::KEY_LEFT_ARROW && GetKeyState(VK_LEFT) < 0) ||
    (keyCode == EventKeyboard::KeyCode::KEY_RIGHT_ARROW && GetKeyState(VK_RIGHT) < 0))
   {
    OnMove(keyCode,NULL);
   }
}
}),NULL));
}
void MagicTower::MoveHero(const Vec2& newpos,Animation* anim,EventKeyboard::KeyCode keyCode)
{//若成功,则捡物品或者攻击
ismoving=true;
Vec2 tilepos;
WorldPosToTilePos(newpos,tilepos);
if(map->getLayer("floor")->getTileGIDAt(tilepos) == FLOOR_WALL)
{//禁止通行
ismoving=false;
return;
}
//若是地板则进行上层判断
auto layer=map->getLayer("item");
switch(layer->getTileGIDAt(tilepos))
{
case ITEM_REDDIAMOND:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.offense += 100;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
case ITEM_BLUEDIAMOND:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.defense += 50;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
case ITEM_REDBLOOD:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.life += 400;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
case ITEM_BLUEBLOOD:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.life += 200;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
case ITEM_YELLOWKEY:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.keyyellow++;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
case ITEM_BLUEKEY:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.keyblue++;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
case ITEM_REDKEY:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.keyred++;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
default://若为空,执行上层判断
   break;
}
layer=map->getLayer("enemy");
if(layer->getTileGIDAt(tilepos))
{//若有敌人
PlayHeroMovement(newpos,anim,keyCode,()
{
   auto animation=AnimationCache::getInstance()->getAnimation("attack");
   auto attacksprite=Sprite::createWithSpriteFrame(animation->getFrames().at(0)->getSpriteFrame());
   attacksprite->setAnchorPoint(Vec2(0,0));
   attacksprite->setPosition(-attacksprite->getContentSize().width/4,-attacksprite->getContentSize().height/4);
   //开始攻击动画+音乐
   hero.heroSprite->addChild(attacksprite);
   attackEnemy(layer,tilepos,attacksprite,Animate::create(animation));
});
return;
}
//若为空,执行上层判断
layer=map->getLayer("door");
switch(layer->getTileGIDAt(tilepos))
{
case DOOR_YELLOW:
   {
    hero.keyyellow--;
    auto animation=AnimationCache::getInstance()->getAnimation("DOOR_YELLOW");
    auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
   CallFuncN::create((Node*){
      layer->removeChild(layer->getTileAt(tilepos),true);
    })),CallFuncN::create([](Node*){
   SimpleAudioEngine::getInstance()->playEffect("open.mp3");
    }));
    layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
   CallFuncN::create((Node*){
      PlayHeroMovement(newpos,anim,keyCode,[](){});
    })));   
   }
   return;
case DOOR_BLUE:
   {
    hero.keyblue--;
    auto animation=AnimationCache::getInstance()->getAnimation("DOOR_BLUE");
    auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
   CallFuncN::create((Node*){
      layer->removeChild(layer->getTileAt(tilepos),true);
    })),CallFuncN::create([](Node*){
   SimpleAudioEngine::getInstance()->playEffect("open.mp3");
    }));
    layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
   CallFuncN::create((Node*){
      PlayHeroMovement(newpos,anim,keyCode,[](){});
    })));
   }
   return;
case DOOR_RED:
   {
    hero.keyred--;
    auto animation=AnimationCache::getInstance()->getAnimation("DOOR_RED");
    auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
   CallFuncN::create((Node*){
      layer->removeChild(layer->getTileAt(tilepos),true);
    })),CallFuncN::create([](Node*){
   SimpleAudioEngine::getInstance()->playEffect("open.mp3");
    }));
    layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
   CallFuncN::create((Node*){
      PlayHeroMovement(newpos,anim,keyCode,[](){});
    })));
   }
   return;

case DOOR_GREEN:
   ismoving=false;
   return;
case DOOR_UPSTAIRS:
   {
    //更新地图
    Director::getInstance()->setDepthTest(false);
    hero.nexttilepos=Vec2(HeroInitPos[(thislevel+1)*4],HeroInitPos[(thislevel+1)*4+1]);
    auto trans=TransitionCrossFade::create(0.5,MagicTowerLayerManager::getInstance().getScene(thislevel+1));
    if(trans)
   Director::getInstance()->replaceScene(trans);
    ismoving=false;
   }
   return;
case DOOR_DOWNSTAIRS:
   {
    //更新地图
    Director::getInstance()->setDepthTest(false);
    hero.nexttilepos=Vec2(HeroInitPos[(thislevel-1)*4+2],HeroInitPos[(thislevel-1)*4+3]);
    auto trans=TransitionCrossFade::create(0.5,MagicTowerLayerManager::getInstance().getScene(thislevel-1));
    if(trans)
   Director::getInstance()->replaceScene(trans);
    ismoving=false;
   }
   return;
}
//若无对象存在,则移动英雄
PlayHeroMovement(newpos,anim,keyCode,[](){});
//在执行PlayerHeroMovement的地方,ismoving交给该函数处理
}
void MagicTower::attackEnemy(TMXLayer* layer,Vec2 tilepos,Sprite* attacksprite,Animate* animate)
{
//判断英雄是否移动了,如果移动则去除animate并结束
Vec2 herointile;
WorldPosToTilePos(hero.heroSprite->getPosition(),herointile);
if(herointile != tilepos)
{
attacksprite->stopAllActions();
hero.heroSprite->removeChild(attacksprite,true);
return;
}
attacksprite->runAction(Sequence::create(animate,CallFuncN::create((Node* attacksprite)
{
ValueMap* val=static_cast<ValueMap*>(layer->getTileAt(tilepos)->getUserData());
int enemylife=(*val)["life"].asInt();
int enemyoffense=(*val)["offense"].asInt();
int enemydefense=(*val)["defense"].asInt();
int harmetoh=(hero.defense>enemyoffense)?0:enemyoffense-hero.defense;//enemy对hero造成的伤害,如果hero的防>enemy的攻,则无伤害
int harmhtoe=(enemydefense>hero.offense)?0:hero.offense-enemydefense;
hero.life -= harmetoh;
enemylife -= harmhtoe;
SimpleAudioEngine::getInstance()->playEffect("fight.mp3");
(*val)["life"]=enemylife;
FlushBoard(val);
if(enemylife < 0 || hero.life < 0)
{
   if(hero.life < 0)
   {//英雄挂了
   }
   else
   {
    attacksprite->stopAllActions();
    hero.money += (*val)["money"].asInt();
    hero.heroSprite->removeChild(attacksprite,true);
    layer->removeChild(layer->getTileAt(tilepos),true);
    FlushBoard(val);
    //刷新面板
   }
}
else
{
   attackEnemy(layer,tilepos,static_cast<Sprite*>(attacksprite),animate);
}
}),NULL));
}
void MagicTower::DefaultKeyboardDispatcher(EventKeyboard::KeyCode keycode)
{//处理其他键盘事件

}
void MagicTower::WorldPosToTilePos(const Vec2& pos,Vec2& objpos)
{//pos为世界坐标系,相对于窗口左下角,目标锚点位于左下角
float rex=map->getContentSize().width/2+(pos.x+blocksize/2-map->getPosition().x);
float rey=map->getContentSize().height/2-(pos.y+blocksize/2-map->getPosition().y);
objpos.setPoint(int(rex/blocksize),int(rey/blocksize));
}
void MagicTower::TilePosToWorldPos(const Vec2& pos,Vec2& objpos)
{//pos为Tile坐标系,相对于窗口左上角
float rex=pos.x*blocksize-map->getContentSize().width/2+map->getPosition().x;
float rey=map->getContentSize().height/2-pos.y*blocksize+map->getPosition().y;
objpos.setPoint(rex,rey);
}
void MagicTower::MoveUnitInTile(const Vec2& pos,Sprite* obj)
{//pos为Tile坐标系,相对于左上角
float rex=pos.x*blocksize-map->getContentSize().width/2+map->getPosition().x;
float rey=map->getContentSize().height/2-pos.y*blocksize+map->getPosition().y-blocksize;
obj->setPosition(rex,rey);
}
void MagicTower::FlushBoard(ValueMap* obj)
{
char str;
sprintf(str,"魔塔 第%d层",thislevel);
board.maintitle->setString(IConvConvert_GBKToUTF8(str));
board.heroname->setString(IConvConvert_GBKToUTF8(hero.name));
sprintf(str,"%d",hero.life);
board.life_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.offense);
board.offense_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.defense);
board.defense_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.money);
board.money_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.keyyellow);
board.yellowkey->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.keyblue);
board.bluekey->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.keyred);
board.redkey->setString(IConvConvert_GBKToUTF8(str));
if(obj)
{
int category=(*obj)["category"].asInt();
if(category == TYPE_ENEMY)
{
   board.enemyname->setString(IConvConvert_GBKToUTF8((*obj)["name"].asString()));
   sprintf(str,"%d",(*obj)["life"].asInt());
   board.life_enemy->setString(IConvConvert_GBKToUTF8(str));
   sprintf(str,"%d",(*obj)["offense"].asInt());
   board.offense_enemy->setString(IConvConvert_GBKToUTF8(str));
   sprintf(str,"%d",(*obj)["defense"].asInt());
   board.defense_enemy->setString(IConvConvert_GBKToUTF8(str));
}
else if(category == TYPE_ITEM)
{
}
}
}
void MagicTower::SelectSprite(Sprite* sprite)
{
auto data=static_cast<ValueMap*>(sprite->getUserData());
if((*data)["selected"].asBool())
{
sprite->removeChildByTag('sel');
(*data)["selected"]=false;
}
else
{
auto texture=map->getLayer("enemy")->getTexture();
int hei=texture->getContentSize().height;
auto selsprite=Sprite::createWithTexture(texture,Rect(0,texture->getContentSize().height-blocksize,blocksize,blocksize));//设置为最后一个
selsprite->setAnchorPoint(Vec2(0,0));
selsprite->setPosition(0,0);
sprite->addChild(selsprite,selsprite->getLocalZOrder(),'sel');
FlushBoard(data);
(*data)["selected"]=true;
}
}
//MagicTowerLayerManager管理场景切换
MagicTowerLayerManager& MagicTowerLayerManager::getInstance()
{
static MagicTowerLayerManager manager;
return manager;
}
Scene* MagicTowerLayerManager::getScene(int layer)
{
curlayer=layer;
auto curscene=Scene::create();
auto curlayer=new MagicTower(layer);
if (curscene && curlayer)
{
curscene->addChild(curlayer);
curlayer->autorelease();
}
return curscene;
}
Hero MagicTower::hero;
Board MagicTower::board;
MagicTowerLayerManager::MagicTowerLayerManager()
{
curlayer=1;
MagicTower::hero.name="勇士";
MagicTower::hero.life=1000;
MagicTower::hero.offense=200;
MagicTower::hero.defense=200;
MagicTower::hero.keyyellow=10;
MagicTower::hero.keyblue=10;
MagicTower::hero.keyred=10;
MagicTower::hero.money=1000;
MagicTower::hero.nexttilepos=Vec2(6,11);//初始化
}




MagicTower.h

#include "MagicTower.h"
#include "..\external\win32-specific\icon\include\iconv.h"
#pragma comment(lib,"libiconv.lib")
USING_NS_CC;
using namespace CocosDenshion;
bool IConvConvert(const char *from_charset, const char *to_charset, const char *inbuf, int inlen, char *outbuf, int outlen)
{
iconv_t cd = iconv_open(to_charset, from_charset);
if (cd == 0) return false;
const char **pin = &inbuf;
char **pout = &outbuf;
memset(outbuf,0,outlen);
size_t ret = iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
iconv_close(cd);
return ret == (size_t)(-1) ? false : true;
}
std::string IConvConvert_GBKToUTF8(const std::string& str)
{
const char* textIn = str.c_str();
char textOut;
bool ret = IConvConvert("gb2312", "utf-8", textIn, strlen(textIn),textOut, 256);
return ret ? std::string(textOut) : std::string();
}
// on "init" you need to initialize your instance
MagicTower::MagicTower(int level)
{
thislevel=level;
auto director=Director::getInstance();
//director->getOpenGLView()->setFrameSize(416,416);
    //////////////////////////////
    // 1. super init first
    Layer::init();
    Size visibleSize = director->getVisibleSize();
    Vec2 origin = director->getVisibleOrigin();
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.
    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(MagicTower::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                              origin.y + closeItem->getContentSize().height/2));
    // create menu, it's an autorelease object
    auto menuclose = Menu::create(closeItem, NULL);
    menuclose->setPosition(Vec2::ZERO);
    this->addChild(menuclose, 1);
    /////////////////////////////
    // 3. add your codes below...
InitMap();
InitHero();
FlushBoard();
//初始换方向键回调
auto listener=EventListenerKeyboard::create();
listener->onKeyPressed=CC_CALLBACK_2(MagicTower::OnMove,this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}

void MagicTower::InitMap()
{
//加载地图背景
auto director=Director::getInstance();
Size visibleSize = director->getVisibleSize();
char mapname;
sprintf(mapname,"%d.tmx",thislevel);
map=TMXTiledMap::create(mapname);
map->setAnchorPoint(Vec2(0.5f,0.5f));
board.board=TMXTiledMap::create("background.tmx");
board.board->setAnchorPoint(Vec2(0.5f,0.5f));
map->setPosition(visibleSize.width/2,visibleSize.height/2+board.board->getContentSize().height/2);
board.board->setPosition(visibleSize.width/2,visibleSize.height/2-map->getContentSize().height/2);
addChild(map);
addChild(board.board);
InitBoard();
//初始化地图元素
Vector<SpriteFrame*> animFrames(4);
auto enemylayer=map->getLayer("enemy");
auto enemyTexture=enemylayer->getTexture();
for(int i=0;i<map->getMapSize().width;i++)
{
for(int j=0;j<map->getMapSize().height;j++)
{
   int id=enemylayer->getTileGIDAt(Vec2(i,j));
   if(id)
   {
    int index=(id-ENEMY_BEGIN)/4;
    auto frame0=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*0,blocksize*index,blocksize,blocksize));
    auto frame1=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*1,blocksize*index,blocksize,blocksize));
    auto frame2=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*2,blocksize*index,blocksize,blocksize));
    auto frame3=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*3,blocksize*index,blocksize,blocksize));
    animFrames.pushBack(frame0);
    animFrames.pushBack(frame1);
    animFrames.pushBack(frame2);
    animFrames.pushBack(frame3);
    auto animation=Animation::createWithSpriteFrames(animFrames,0.1f);
    animFrames.clear();
    auto cursprite=enemylayer->getTileAt(Vec2(i,j));
    if(!cursprite)
   return;
    cursprite->runAction(RepeatForever::create(Animate::create(animation)));
    cursprite->setUserData(ObjManager::getInstance().InitEnemyByType(id));
   }
}
}
//初始化点击事件
auto listener=EventListenerTouchOneByOne::create();
listener->onTouchBegan=(Touch* touch,Event* event)
{
Vec2 tilepos;
WorldPosToTilePos(Vec2(touch->getLocation().x-blocksize/2,touch->getLocation().y-blocksize/2),tilepos);
if(tilepos.x >= 0 && tilepos.y >=0 &&
   tilepos.x < enemylayer->getLayerSize().width && tilepos.y < enemylayer->getLayerSize().height)
{
   Sprite* node=enemylayer->getTileAt(tilepos);
   if(node)
   {
    SelectSprite(node);
   }
}
//根据位置获取单元格,设置为选中状态并刷新数据到面板
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,enemylayer);
auto itemlayer=map->getLayer("item");
for(int i=0;i<map->getMapSize().width;i++)
{
for(int j=0;j<map->getMapSize().height;j++)
{
   int id=itemlayer->getTileGIDAt(Vec2(i,j));
   auto cursprite=enemylayer->getTileAt(Vec2(i,j));
   //if(id && cursprite)
   //{
   // cursprite->setUserData(ObjManager::getInstance().InitItemByType(id));
   //}
}
}
//初始化门动画
auto doorTexture=map->getLayer("door")->getTexture();
int doordata[]={0,1,2,3};
char* doorname[]={"DOOR_YELLOW","DOOR_BLUE","DOOR_RED","DOOR_GREEN"};
for(int i=0;i<getNum(doordata);i++)
{
doordata;
auto frame0=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*0,blocksize,blocksize));
auto frame1=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*1,blocksize,blocksize));
auto frame2=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*2,blocksize,blocksize));
auto frame3=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*3,blocksize,blocksize));
animFrames.pushBack(frame0);
animFrames.pushBack(frame1);
animFrames.pushBack(frame2);
animFrames.pushBack(frame3);
auto animation=Animation::createWithSpriteFrames(animFrames,0.05f);
animFrames.clear();
AnimationCache::getInstance()->addAnimation(animation,doorname);
}
}
void MagicTower::InitBoard()
{
//初始化面板
char title;
sprintf(title,"魔塔 第%d层",thislevel);
board.maintitle=Label::createWithSystemFont(IConvConvert_GBKToUTF8(title),"黑体",30);
board.maintitle->setColor(Color3B::GREEN);
board.maintitle->setAnchorPoint(Vec2(0.5f,0.5f));
board.maintitle->setPosition(board.board->getContentSize().width/2,blocksize*5+16);
board.board->addChild(board.maintitle);
board.heroname=Label::createWithSystemFont(IConvConvert_GBKToUTF8("英雄"),"黑体",24);
board.heroname->setColor(Color3B::RED);
board.heroname->setAnchorPoint(Vec2(0.5f,0.5f));
board.heroname->setPosition(board.board->getContentSize().width/4,blocksize*5-16);
board.board->addChild(board.heroname);
board.enemyname=Label::createWithSystemFont(IConvConvert_GBKToUTF8("敌方"),"黑体",24);
board.enemyname->setColor(Color3B::RED);
board.enemyname->setAnchorPoint(Vec2(0.5f,0.5f));
board.enemyname->setPosition(board.board->getContentSize().width*7/8,blocksize*5-16);
board.board->addChild(board.enemyname);
board.life_hero=Label::createWithBMFont("myfont.fnt","life");
board.life_hero->setAnchorPoint(Vec2(0,0));
board.life_hero->setScale(0.4f);
board.life_hero->setPosition(blocksize*1,blocksize*3+5);
board.board->addChild(board.life_hero);
board.offense_hero=Label::createWithBMFont("myfont.fnt","offense");
board.offense_hero->setAnchorPoint(Vec2(0,0));
board.offense_hero->setScale(0.4f);
board.offense_hero->setPosition(blocksize*1,blocksize*2+5);
board.board->addChild(board.offense_hero);
board.defense_hero=Label::createWithBMFont("myfont.fnt","defense");
board.defense_hero->setAnchorPoint(Vec2(0,0));
board.defense_hero->setScale(0.4f);
board.defense_hero->setPosition(blocksize*1,blocksize*1+5);
board.board->addChild(board.defense_hero);
board.money_hero=Label::createWithBMFont("myfont.fnt","money");
board.money_hero->setAnchorPoint(Vec2(0,0));
board.money_hero->setScale(0.4f);
board.money_hero->setPosition(blocksize*1,blocksize*0+5);
board.board->addChild(board.money_hero);
board.yellowkey=Label::createWithBMFont("myfont.fnt","yellowkey");
board.yellowkey->setAnchorPoint(Vec2(0,0));
board.yellowkey->setScale(0.4f);
board.yellowkey->setPosition(blocksize*4,blocksize*3+5);
board.board->addChild(board.yellowkey);
board.bluekey=Label::createWithBMFont("myfont.fnt","bluekey");
board.bluekey->setAnchorPoint(Vec2(0,0));
board.bluekey->setScale(0.4f);
board.bluekey->setPosition(blocksize*4,blocksize*2+5);
board.board->addChild(board.bluekey);
board.redkey=Label::createWithBMFont("myfont.fnt","redkey");
board.redkey->setAnchorPoint(Vec2(0,0));
board.redkey->setScale(0.4f);
board.redkey->setPosition(blocksize*4,blocksize*1+5);
board.board->addChild(board.redkey);
board.life_enemy=Label::createWithBMFont("myfont.fnt","life");
board.life_enemy->setAnchorPoint(Vec2(0,0));
board.life_enemy->setScale(0.4f);
board.life_enemy->setPosition(blocksize*11,blocksize*3+5);
board.board->addChild(board.life_enemy);
board.offense_enemy=Label::createWithBMFont("myfont.fnt","offense");
board.offense_enemy->setAnchorPoint(Vec2(0,0));
board.offense_enemy->setScale(0.4f);
board.offense_enemy->setPosition(blocksize*11,blocksize*2+5);
board.board->addChild(board.offense_enemy);
board.defense_enemy=Label::createWithBMFont("myfont.fnt","defense");
board.defense_enemy->setAnchorPoint(Vec2(0,0));
board.defense_enemy->setScale(0.4f);
board.defense_enemy->setPosition(blocksize*11,blocksize*1+5);
board.board->addChild(board.defense_enemy);
}
void MagicTower::InitHero()
{
ismoving=false;
//加载英雄图片
auto director=Director::getInstance();
Size visibleSize = director->getVisibleSize();
auto heroTexture=Director::getInstance()->getTextureCache()->addImage("hero.png");
auto frame0=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*0,blocksize*1,blocksize,blocksize));
hero.heroSprite=Sprite::createWithSpriteFrame(frame0);
hero.heroSprite->setAnchorPoint(Vec2(0,0));
MoveUnitInTile(hero.nexttilepos,hero.heroSprite);
addChild(hero.heroSprite);
//存储英雄移动动画
std::string dirname[]={"down","left","right","up"};
Vector<SpriteFrame*> animFrames(4);
for(int i=0;i<4;i++)
{
auto frame0=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*0,blocksize*i,blocksize,blocksize));
auto frame1=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*1,blocksize*i,blocksize,blocksize));
auto frame2=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*2,blocksize*i,blocksize,blocksize));
auto frame3=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*3,blocksize*i,blocksize,blocksize));
animFrames.pushBack(frame0);
animFrames.pushBack(frame1);
animFrames.pushBack(frame2);
animFrames.pushBack(frame3);
auto animation=Animation::createWithSpriteFrames(animFrames,0.05f);
animation->setRestoreOriginalFrame(false);
AnimationCache::getInstance()->addAnimation(animation,dirname);
animFrames.clear();
}
//初始化攻击动画
auto attackTexture= Director::getInstance()->getTextureCache()->addImage("attack.png");
Size unitsize=attackTexture->getContentSizeInPixels();
for(int i=0;i<25;i++)
{
auto frame0=SpriteFrame::createWithTexture(attackTexture,
   Rect(i/5*unitsize.width/5,i%5*unitsize.height/5,unitsize.width/5,unitsize.height/5));
animFrames.pushBack(frame0);
}
AnimationCache::getInstance()->addAnimation(Animation::createWithSpriteFrames(animFrames,0.05f),"attack");
animFrames.clear();
}
void MagicTower::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif
    Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}
void MagicTower::OnMove(EventKeyboard::KeyCode keyCode, Event* event)
{
auto animCache=AnimationCache::getInstance();
Animation* curanimation=NULL;
Vec2 delta;
switch(keyCode)
{
case EventKeyboard::KeyCode::KEY_UP_ARROW:
   curanimation=animCache->getAnimation("up");
   delta.setPoint(0,blocksize);
   break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
   curanimation=animCache->getAnimation("down");
   delta.setPoint(0,-blocksize);
   break;
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
   curanimation=animCache->getAnimation("left");
   delta.setPoint(-blocksize,0);
   break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
   curanimation=animCache->getAnimation("right");
   delta.setPoint(blocksize,0);
   break;
default:
   return DefaultKeyboardDispatcher(keyCode);
}
//判断英雄位置是否可以移动
if(curanimation && !ismoving)
{
MoveHero(hero.heroSprite->getPosition()+delta,curanimation,keyCode);
}
}
void MagicTower::PlayHeroMovement(const Vec2& newpos,Animation* anim,EventKeyboard::KeyCode keyCode,
         const std::function<void(void)>& afteraction)
{//anim:帧动画afteraction:状态更新回调
hero.heroSprite->setSpriteFrame(anim->getFrames().at(0)->getSpriteFrame());

//移动动画和帧动画同时进行
auto spawn=Spawn::createWithTwoActions(Animate::create(anim),MoveTo::create(0.2f,newpos));
//帧动画+移动动画 -> 状态更新 -> 可通行 -> 连击检测
hero.heroSprite->runAction(Sequence::create(spawn,CallFuncN::create((Node* node)
{//所有回调函数需要写一起,否则单另作为Sequence依次执行会失效,不知道是不是bug
afteraction();
ismoving=false;
CCLog("ismoving");
FlushBoard();
if(!ismoving)
{
   if((keyCode == EventKeyboard::KeyCode::KEY_UP_ARROW && GetKeyState(VK_UP) < 0) ||
    (keyCode == EventKeyboard::KeyCode::KEY_DOWN_ARROW && GetKeyState(VK_DOWN) < 0) ||
    (keyCode == EventKeyboard::KeyCode::KEY_LEFT_ARROW && GetKeyState(VK_LEFT) < 0) ||
    (keyCode == EventKeyboard::KeyCode::KEY_RIGHT_ARROW && GetKeyState(VK_RIGHT) < 0))
   {
    OnMove(keyCode,NULL);
   }
}
}),NULL));
}
void MagicTower::MoveHero(const Vec2& newpos,Animation* anim,EventKeyboard::KeyCode keyCode)
{//若成功,则捡物品或者攻击
ismoving=true;
Vec2 tilepos;
WorldPosToTilePos(newpos,tilepos);
if(map->getLayer("floor")->getTileGIDAt(tilepos) == FLOOR_WALL)
{//禁止通行
ismoving=false;
return;
}
//若是地板则进行上层判断
auto layer=map->getLayer("item");
switch(layer->getTileGIDAt(tilepos))
{
case ITEM_REDDIAMOND:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.offense += 100;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
case ITEM_BLUEDIAMOND:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.defense += 50;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
case ITEM_REDBLOOD:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.life += 400;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
case ITEM_BLUEBLOOD:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.life += 200;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
case ITEM_YELLOWKEY:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.keyyellow++;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
case ITEM_BLUEKEY:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.keyblue++;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
case ITEM_REDKEY:
   PlayHeroMovement(newpos,anim,keyCode,()
   {//刷新+音乐+物品动画
    hero.keyred++;
    layer->removeChild(layer->getTileAt(tilepos),true);
    SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
   });
   return;
   
default://若为空,执行上层判断
   break;
}
layer=map->getLayer("enemy");
if(layer->getTileGIDAt(tilepos))
{//若有敌人
PlayHeroMovement(newpos,anim,keyCode,()
{
   auto animation=AnimationCache::getInstance()->getAnimation("attack");
   auto attacksprite=Sprite::createWithSpriteFrame(animation->getFrames().at(0)->getSpriteFrame());
   attacksprite->setAnchorPoint(Vec2(0,0));
   attacksprite->setPosition(-attacksprite->getContentSize().width/4,-attacksprite->getContentSize().height/4);
   //开始攻击动画+音乐
   hero.heroSprite->addChild(attacksprite);
   attackEnemy(layer,tilepos,attacksprite,Animate::create(animation));
});
return;
}
//若为空,执行上层判断
layer=map->getLayer("door");
switch(layer->getTileGIDAt(tilepos))
{
case DOOR_YELLOW:
   {
    hero.keyyellow--;
    auto animation=AnimationCache::getInstance()->getAnimation("DOOR_YELLOW");
    auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
   CallFuncN::create((Node*){
      layer->removeChild(layer->getTileAt(tilepos),true);
    })),CallFuncN::create([](Node*){
   SimpleAudioEngine::getInstance()->playEffect("open.mp3");
    }));
    layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
   CallFuncN::create((Node*){
      PlayHeroMovement(newpos,anim,keyCode,[](){});
    })));   
   }
   return;
case DOOR_BLUE:
   {
    hero.keyblue--;
    auto animation=AnimationCache::getInstance()->getAnimation("DOOR_BLUE");
    auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
   CallFuncN::create((Node*){
      layer->removeChild(layer->getTileAt(tilepos),true);
    })),CallFuncN::create([](Node*){
   SimpleAudioEngine::getInstance()->playEffect("open.mp3");
    }));
    layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
   CallFuncN::create((Node*){
      PlayHeroMovement(newpos,anim,keyCode,[](){});
    })));
   }
   return;
case DOOR_RED:
   {
    hero.keyred--;
    auto animation=AnimationCache::getInstance()->getAnimation("DOOR_RED");
    auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
   CallFuncN::create((Node*){
      layer->removeChild(layer->getTileAt(tilepos),true);
    })),CallFuncN::create([](Node*){
   SimpleAudioEngine::getInstance()->playEffect("open.mp3");
    }));
    layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
   CallFuncN::create((Node*){
      PlayHeroMovement(newpos,anim,keyCode,[](){});
    })));
   }
   return;

case DOOR_GREEN:
   ismoving=false;
   return;
case DOOR_UPSTAIRS:
   {
    //更新地图
    Director::getInstance()->setDepthTest(false);
    hero.nexttilepos=Vec2(HeroInitPos[(thislevel+1)*4],HeroInitPos[(thislevel+1)*4+1]);
    auto trans=TransitionCrossFade::create(0.5,MagicTowerLayerManager::getInstance().getScene(thislevel+1));
    if(trans)
   Director::getInstance()->replaceScene(trans);
    ismoving=false;
   }
   return;
case DOOR_DOWNSTAIRS:
   {
    //更新地图
    Director::getInstance()->setDepthTest(false);
    hero.nexttilepos=Vec2(HeroInitPos[(thislevel-1)*4+2],HeroInitPos[(thislevel-1)*4+3]);
    auto trans=TransitionCrossFade::create(0.5,MagicTowerLayerManager::getInstance().getScene(thislevel-1));
    if(trans)
   Director::getInstance()->replaceScene(trans);
    ismoving=false;
   }
   return;
}
//若无对象存在,则移动英雄
PlayHeroMovement(newpos,anim,keyCode,[](){});
//在执行PlayerHeroMovement的地方,ismoving交给该函数处理
}
void MagicTower::attackEnemy(TMXLayer* layer,Vec2 tilepos,Sprite* attacksprite,Animate* animate)
{
//判断英雄是否移动了,如果移动则去除animate并结束
Vec2 herointile;
WorldPosToTilePos(hero.heroSprite->getPosition(),herointile);
if(herointile != tilepos)
{
attacksprite->stopAllActions();
hero.heroSprite->removeChild(attacksprite,true);
return;
}
attacksprite->runAction(Sequence::create(animate,CallFuncN::create((Node* attacksprite)
{
ValueMap* val=static_cast<ValueMap*>(layer->getTileAt(tilepos)->getUserData());
int enemylife=(*val)["life"].asInt();
int enemyoffense=(*val)["offense"].asInt();
int enemydefense=(*val)["defense"].asInt();
int harmetoh=(hero.defense>enemyoffense)?0:enemyoffense-hero.defense;//enemy对hero造成的伤害,如果hero的防>enemy的攻,则无伤害
int harmhtoe=(enemydefense>hero.offense)?0:hero.offense-enemydefense;
hero.life -= harmetoh;
enemylife -= harmhtoe;
SimpleAudioEngine::getInstance()->playEffect("fight.mp3");
(*val)["life"]=enemylife;
FlushBoard(val);
if(enemylife < 0 || hero.life < 0)
{
   if(hero.life < 0)
   {//英雄挂了
   }
   else
   {
    attacksprite->stopAllActions();
    hero.money += (*val)["money"].asInt();
    hero.heroSprite->removeChild(attacksprite,true);
    layer->removeChild(layer->getTileAt(tilepos),true);
    FlushBoard(val);
    //刷新面板
   }
}
else
{
   attackEnemy(layer,tilepos,static_cast<Sprite*>(attacksprite),animate);
}
}),NULL));
}
void MagicTower::DefaultKeyboardDispatcher(EventKeyboard::KeyCode keycode)
{//处理其他键盘事件

}
void MagicTower::WorldPosToTilePos(const Vec2& pos,Vec2& objpos)
{//pos为世界坐标系,相对于窗口左下角,目标锚点位于左下角
float rex=map->getContentSize().width/2+(pos.x+blocksize/2-map->getPosition().x);
float rey=map->getContentSize().height/2-(pos.y+blocksize/2-map->getPosition().y);
objpos.setPoint(int(rex/blocksize),int(rey/blocksize));
}
void MagicTower::TilePosToWorldPos(const Vec2& pos,Vec2& objpos)
{//pos为Tile坐标系,相对于窗口左上角
float rex=pos.x*blocksize-map->getContentSize().width/2+map->getPosition().x;
float rey=map->getContentSize().height/2-pos.y*blocksize+map->getPosition().y;
objpos.setPoint(rex,rey);
}
void MagicTower::MoveUnitInTile(const Vec2& pos,Sprite* obj)
{//pos为Tile坐标系,相对于左上角
float rex=pos.x*blocksize-map->getContentSize().width/2+map->getPosition().x;
float rey=map->getContentSize().height/2-pos.y*blocksize+map->getPosition().y-blocksize;
obj->setPosition(rex,rey);
}
void MagicTower::FlushBoard(ValueMap* obj)
{
char str;
sprintf(str,"魔塔 第%d层",thislevel);
board.maintitle->setString(IConvConvert_GBKToUTF8(str));
board.heroname->setString(IConvConvert_GBKToUTF8(hero.name));
sprintf(str,"%d",hero.life);
board.life_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.offense);
board.offense_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.defense);
board.defense_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.money);
board.money_hero->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.keyyellow);
board.yellowkey->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.keyblue);
board.bluekey->setString(IConvConvert_GBKToUTF8(str));
sprintf(str,"%d",hero.keyred);
board.redkey->setString(IConvConvert_GBKToUTF8(str));
if(obj)
{
int category=(*obj)["category"].asInt();
if(category == TYPE_ENEMY)
{
   board.enemyname->setString(IConvConvert_GBKToUTF8((*obj)["name"].asString()));
   sprintf(str,"%d",(*obj)["life"].asInt());
   board.life_enemy->setString(IConvConvert_GBKToUTF8(str));
   sprintf(str,"%d",(*obj)["offense"].asInt());
   board.offense_enemy->setString(IConvConvert_GBKToUTF8(str));
   sprintf(str,"%d",(*obj)["defense"].asInt());
   board.defense_enemy->setString(IConvConvert_GBKToUTF8(str));
}
else if(category == TYPE_ITEM)
{
}
}
}
void MagicTower::SelectSprite(Sprite* sprite)
{
auto data=static_cast<ValueMap*>(sprite->getUserData());
if((*data)["selected"].asBool())
{
sprite->removeChildByTag('sel');
(*data)["selected"]=false;
}
else
{
auto texture=map->getLayer("enemy")->getTexture();
int hei=texture->getContentSize().height;
auto selsprite=Sprite::createWithTexture(texture,Rect(0,texture->getContentSize().height-blocksize,blocksize,blocksize));//设置为最后一个
selsprite->setAnchorPoint(Vec2(0,0));
selsprite->setPosition(0,0);
sprite->addChild(selsprite,selsprite->getLocalZOrder(),'sel');
FlushBoard(data);
(*data)["selected"]=true;
}
}
//MagicTowerLayerManager管理场景切换
MagicTowerLayerManager& MagicTowerLayerManager::getInstance()
{
static MagicTowerLayerManager manager;
return manager;
}
Scene* MagicTowerLayerManager::getScene(int layer)
{
curlayer=layer;
auto curscene=Scene::create();
auto curlayer=new MagicTower(layer);
if (curscene && curlayer)
{
curscene->addChild(curlayer);
curlayer->autorelease();
}
return curscene;
}
Hero MagicTower::hero;
Board MagicTower::board;
MagicTowerLayerManager::MagicTowerLayerManager()
{
curlayer=1;
MagicTower::hero.name="勇士";
MagicTower::hero.life=1000;
MagicTower::hero.offense=200;
MagicTower::hero.defense=200;
MagicTower::hero.keyyellow=10;
MagicTower::hero.keyblue=10;
MagicTower::hero.keyred=10;
MagicTower::hero.money=1000;
MagicTower::hero.nexttilepos=Vec2(6,11);//初始化
}



common.cpp


#include "common.h"
#include "cocos2d.h"
#include <iostream>
USING_NS_CC;
struct ENEMY globalEnemyData[]=
{
{TYPE_ENEMY,ENEMY_KULOUREN,"骷髅人","骷髅人",110,25,5,110},
{TYPE_ENEMY,ENEMY_KULOUSHIBING,"骷髅士兵","骷髅士兵",150,40,20,150},
{TYPE_ENEMY,ENEMY_XIAOBIANFU,"小蝙蝠","小蝙蝠",100,20,5,100},
{TYPE_ENEMY,ENEMY_LVTOUGUAI,"绿头怪","绿头怪",50,20,1,50},
{TYPE_ENEMY,ENEMY_HONGTOUGUAI,"红头怪","红头怪",70,15,2,70},
{TYPE_ENEMY,ENEMY_CHUJIFASHI,"初级法师","初级法师",125,50,25,125},
};
struct ITEM globalItemData[]=
{
{TYPE_ITEM,ITEM_REDDIAMOND,"红宝石","增加攻击力"},
{TYPE_ITEM,ITEM_BLUEDIAMOND,"蓝宝石","增加防御力"},
{TYPE_ITEM,ITEM_REDBLOOD,"红血瓶","增加大量生命"},
{TYPE_ITEM,ITEM_BLUEBLOOD,"蓝血瓶","增加少量生命"},
{TYPE_ITEM,ITEM_YELLOWKEY,"黄钥匙","开启黄色门"},
{TYPE_ITEM,ITEM_BLUEKEY,"蓝钥匙","开启蓝色门"},
{TYPE_ITEM,ITEM_REDKEY,"红钥匙","开启红色门"},
};
ObjManager& ObjManager::getInstance()
{
static ObjManager manager;
return manager;
}
ValueMap* ObjManager::InitEnemyByType(int type)
{
ValueMap* curmap=new ValueMap(enemytemp);
enemies.push_back(curmap);
return curmap;
}
ValueMap* ObjManager::InitItemByType(int type)
{
return &itemtemp;
}
ObjManager::ObjManager()
{
ValueMap curmap;
for(ENEMY eny:globalEnemyData)
{
curmap["category"]=eny.category;
curmap["type"]=eny.type;
curmap["name"]=eny.name;
curmap["desc"]=eny.desc;
curmap["life"]=eny.life;
curmap["offense"]=eny.offense;
curmap["defense"]=eny.defense;
curmap["money"]=eny.money;
curmap["selected"]=false;
enemytemp=curmap;
curmap.clear();
}
for(ITEM item:globalItemData)
{
curmap["category"]=item.category;
curmap["type"]=item.type;
curmap["name"]=item.name;
curmap["desc"]=item.desc;
curmap["selected"]=false;
itemtemp=curmap;
curmap.clear();
}
}
ObjManager::~ObjManager()
{
for(ValueMap* pt:enemies)
{
delete pt;
}
for(ValueMap* pt:items)
{
delete pt;
}
}

int HeroInitPos[]=
{//in*2 out*2分别代表从楼下到此层的初始位置和从楼上到此层的初始位置
//   第一层   第二层   第三层   第四层
-1,-1,-1,-1,    6,10,2,1,    2,1,1,10,    2,11,10,11,    11,10,1,10
};




common.h


#pragma once
#include "cocos2d.h"
#include <iostream>
USING_NS_CC;
#ifndef __HELLOWORLD_MANAGER_H__
#define __HELLOWORLD_MANAGER_H__
#define blocksize 32
enum direction
{
kDown=0,
kLeft=1,
kRight=2,
kUp=3,
};
enum category
{
TYPE_FLOOR,
TYPE_ITEM,
TYPE_ENEMY,
TYPE_DOOR,
};
//对应于tileid
enum floor//floor层对象
{
FLOOR_BEGIN=0,
FLOOR_WALL=FLOOR_BEGIN+7,//墙体
FLOOR_FLOOR=FLOOR_BEGIN+12,//地板
};
enum item//item层对象
{
ITEM_BEGIN=72,
ITEM_REDDIAMOND=ITEM_BEGIN+1,//红宝石
ITEM_BLUEDIAMOND=ITEM_BEGIN+2,//蓝宝石
ITEM_REDBLOOD=ITEM_BEGIN+5,//红血瓶
ITEM_BLUEBLOOD=ITEM_BEGIN+6,//蓝血瓶
ITEM_YELLOWKEY=ITEM_BEGIN+17,//黄钥匙
ITEM_BLUEKEY=ITEM_BEGIN+18,//蓝钥匙
ITEM_REDKEY=ITEM_BEGIN+19,//红钥匙
};
enum enemy
{
ENEMY_BEGIN=136,
ENEMY_KULOUREN=ENEMY_BEGIN+1,//骷髅人
ENEMY_KULOUSHIBING=ENEMY_BEGIN+5,//骷髅士兵
ENEMY_XIAOBIANFU=ENEMY_BEGIN+17,//小蝙蝠
ENEMY_LVTOUGUAI=ENEMY_BEGIN+33,//绿头怪
ENEMY_HONGTOUGUAI=ENEMY_BEGIN+37,//红头怪
ENEMY_CHUJIFASHI=ENEMY_BEGIN+49,//初级法师
};
enum door
{
DOOR_BEGIN=392,
DOOR_YELLOW=DOOR_BEGIN+1,//黄门
DOOR_BLUE=DOOR_BEGIN+2,//蓝门
DOOR_RED=DOOR_BEGIN+3,//红门
DOOR_GREEN=DOOR_BEGIN+4,//绿门
DOOR_UPSTAIRS=DOOR_BEGIN+17,//上楼梯
DOOR_DOWNSTAIRS=DOOR_BEGIN+18,//下楼梯
};
struct ENEMY
{
int category;
int type;
std::string name;//名称
std::string desc;//描述
int life;
int offense;//攻击
int defense;//防御
int money;//金钱
};
struct ITEM
{
int category;
int type;
std::string name;//名称
std::string desc;//描述
};
typedef std::unordered_map<int,ValueMap> ObjMap;
#define getNum(x) (sizeof(x)/(sizeof(x)))
class ObjManager
{//用来设置怪物动画
public:
static ObjManager& getInstance();
ValueMap* InitEnemyByType(int type);
ValueMap* InitItemByType(int type);
private:
ObjMap enemytemp;
ObjMap itemtemp;
std::vector<ValueMap*> enemies;
std::vector<ValueMap*> items;
private:
ObjManager();//单例模式
virtual ~ObjManager();
};
struct Hero
{
Sprite* heroSprite;
std::string name;
int life;
int offense;
int defense;
int keyyellow;
int keyblue;
int keyred;
int money;
Vec2 nexttilepos;
};
struct Board
{
TMXTiledMap* board;
Label* maintitle;
//hero
Label* heroname;
Label* life_hero;
Label* offense_hero;
Label* defense_hero;
Label* money_hero;
Label* yellowkey;
Label* bluekey;
Label* redkey;
Label* weapon;
Label* shield;
//enemy
Label* enemyname;
Label* life_enemy;
Label* offense_enemy;
Label* defense_enemy;
};
int HeroInitPos[];

#endif




元始天尊 发表于 2014-6-19 22:22:38



游戏文件在群共享里

元始天尊 发表于 2014-6-19 22:22:41



游戏文件在群共享里

0xAA55 发表于 2014-6-20 00:03:36

元始天尊 发表于 2014-6-19 14:22
游戏文件在群共享里

加群链接:<a target="_blank" href="http://shang.qq.com/wpa/qunwpa?idkey=99877993d1bb0705c42287e6a05242c065b88ac531ddc632169abeb1ed8552e3"><img border="0" src="http://pub.idqqimg.com/wpa/images/group.png" alt="编程交流及书籍分享" title="编程交流及书籍分享"></a>

元始天尊 发表于 2014-6-22 16:45:51

改进代码以便在android环境下运行:
android版本在交流群共享里


#include "MagicTower.h"
#include "..\external\win32-specific\icon\include\iconv.h"

USING_NS_CC;
using namespace CocosDenshion;

extern int HeroInitPos[];

#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#pragma comment(lib,"libiconv.lib")
bool IConvConvert(const char *from_charset, const char *to_charset, const char *inbuf, int inlen, char *outbuf, int outlen)
{
        iconv_t cd = iconv_open(to_charset, from_charset);
        if (cd == 0) return false;
        const char **pin = &inbuf;
        char **pout = &outbuf;
        memset(outbuf,0,outlen);
        size_t ret = iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
        iconv_close(cd);
        return ret == (size_t)(-1) ? false : true;
}

std::string IConvConvert_GBKToUTF8(const std::string& str)
{
        const char* textIn = str.c_str();
        char textOut;
        bool ret = IConvConvert("gb2312", "utf-8", textIn, strlen(textIn),textOut, 256);
        return ret ? std::string(textOut) : std::string();
}
#else
std::string IConvConvert_GBKToUTF8(const std::string& str)
{
        return str;
}
#endif

// on "init" you need to initialize your instance
MagicTower::MagicTower(int level)
{
        CCLog("Enter MagicTower");
        thislevel=level;
        auto director=Director::getInstance();
        //director->getOpenGLView()->setFrameSize(416,416);
    //////////////////////////////
    // 1. super init first
    Layer::init();

    Size visibleSize = director->getVisibleSize();
    Vec2 origin = director->getVisibleOrigin();
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(MagicTower::menuCloseCallback, this));
        closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                              origin.y + closeItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    auto menuclose = Menu::create(closeItem, NULL);
    menuclose->setPosition(Vec2::ZERO);
    this->addChild(menuclose, 1);

    /////////////////////////////
    // 3. add your codes below...
        InitMap();
        InitHero();
        FlushBoard();

#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
        //初始换方向键回调
        auto listener=EventListenerKeyboard::create();
        listener->onKeyPressed=CC_CALLBACK_2(MagicTower::OnMove,this);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
#else
        //初始化触摸滑动
        auto listener=EventListenerTouchAllAtOnce::create();
        listener->onTouchesMoved=(const std::vector<Touch*>& touches,Event* event)
        {
                auto touch=touches;
                map->setPosition(map->getPosition()+touch->getDelta());
        };
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
#endif
        CCLog("Leave MagicTower");
}


void MagicTower::InitMap()
{
        CCLog("Enter InitMap");
        //加载地图背景
        auto director=Director::getInstance();
        Size visibleSize = director->getVisibleSize();
        char mapname;
        sprintf(mapname,"%d.tmx",thislevel);
        map=TMXTiledMap::create(mapname);
        map->setAnchorPoint(Vec2(0.5f,0.5f));
//#if(CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
        map->setScale(1.5);
//#endif
        board.board=TMXTiledMap::create("background.tmx");
        board.board->setAnchorPoint(Vec2(0.5f,0.5f));
        map->setPosition(visibleSize.width/2,visibleSize.height/2+board.board->getContentSize().height/2);
        board.board->setPosition(visibleSize.width/2,board.board->getContentSize().height/2);
        addChild(map);
        addChild(board.board);
        auto listenerm=EventListenerTouchAllAtOnce::create();
        listenerm->onTouchesMoved=(const std::vector<Touch*>& touches, Event*event)
        {
                auto touch=touches;
                auto diff=touch->getDelta();
                map->setPosition(map->getPosition()+diff);
        };
//        _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerm,map);

        auto arrowright=Sprite::create("arrow.png");
        auto arrowdown=Sprite::create("arrow.png");
        auto arrowleft=Sprite::create("arrow.png");
        auto arrowup=Sprite::create("arrow.png");
        arrowright->setAnchorPoint(Vec2(0,0.5));
        arrowright->setScale(3);
        arrowdown->setAnchorPoint(Vec2(0,0.5));
        arrowdown->setRotation(90);
        arrowdown->setScale(3);
        arrowleft->setAnchorPoint(Vec2(0,0.5));
        arrowleft->setRotation(180);
        arrowleft->setScale(3);
        arrowup->setAnchorPoint(Vec2(0,0.5));
        arrowup->setRotation(270);
        arrowup->setScale(3);
        arrowright->setPosition(visibleSize.width/2,visibleSize.height/2);
        arrowdown->setPosition(visibleSize.width/2,visibleSize.height/2);
        arrowleft->setPosition(visibleSize.width/2,visibleSize.height/2);
        arrowup->setPosition(visibleSize.width/2,visibleSize.height/2);
        addChild(arrowright,240,24);
        arrowright->setTag(24);
        addChild(arrowdown,260,26);
        arrowdown->setTag(26);
        addChild(arrowleft,230,23);
        arrowleft->setTag(23);
        addChild(arrowup,250,25);
        arrowup->setTag(25);

        //初始化点击事件
        auto listenerll=EventListenerTouchOneByOne::create();
        listenerll->setSwallowTouches(true);
        listenerll->onTouchEnded=[=](Touch* touch,Event* event)
        {
                auto animCache=AnimationCache::getInstance();
                Animation* curanimation=NULL;
                Vec2 delta;
                auto target = static_cast<Sprite*>(event->getCurrentTarget());

                switch(target->getTag())
                {
                        case 25:
                                curanimation=animCache->getAnimation("up");
                                delta.setPoint(0,blocksize);
                                break;

                        case 26:
                                curanimation=animCache->getAnimation("down");
                                delta.setPoint(0,-blocksize);
                                break;

                        case 23:
                                curanimation=animCache->getAnimation("left");
                                delta.setPoint(-blocksize,0);
                                break;

                        case 24:
                                curanimation=animCache->getAnimation("right");
                                delta.setPoint(blocksize,0);
                                break;
                }
                if(curanimation && !ismoving)
                {
                        MoveHero(hero.heroSprite->getPosition()+delta,curanimation,target->getTag());
                }
        };

        listenerll->onTouchBegan=[](Touch* touch,Event* event)
        {
                CCLog("Touch Began!");
                auto target = static_cast<Sprite*>(event->getCurrentTarget());
                Vec2 locationInNode=target->convertToNodeSpace(touch->getLocation());
                Size s=target->getContentSize();
                Rect rect=Rect(0,0,s.width,s.height);
                if(!rect.containsPoint(locationInNode))
                        return false;
                return true;
        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerll,arrowright);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerll->clone(),arrowdown);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerll->clone(),arrowleft);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerll->clone(),arrowup);


        InitBoard();

        //初始化地图元素
        Vector<SpriteFrame*> animFrames(4);
        auto enemylayer=map->getLayer("enemy");
        auto enemyTexture=enemylayer->getTexture();

        for(int i=0;i<map->getMapSize().width;i++)
        {
                for(int j=0;j<map->getMapSize().height;j++)
                {
                        int id=enemylayer->getTileGIDAt(Vec2(i,j));
                        if(id)
                        {
                                int index=(id-ENEMY_BEGIN)/4;
                                auto frame0=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*0,blocksize*index,blocksize,blocksize));
                                auto frame1=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*1,blocksize*index,blocksize,blocksize));
                                auto frame2=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*2,blocksize*index,blocksize,blocksize));
                                auto frame3=SpriteFrame::createWithTexture(enemyTexture,Rect(blocksize*3,blocksize*index,blocksize,blocksize));
                                animFrames.pushBack(frame0);
                                animFrames.pushBack(frame1);
                                animFrames.pushBack(frame2);
                                animFrames.pushBack(frame3);
                                auto animation=Animation::createWithSpriteFrames(animFrames,0.1f);
                                animFrames.clear();
                                CCLog("x=%d,y=%d",i,j);
                                auto cursprite=enemylayer->getTileAt(Vec2(i,j));
                                if(!cursprite)
                                        return;
                                cursprite->runAction(RepeatForever::create(Animate::create(animation)));
                                cursprite->setUserData(ObjManager::getInstance().InitEnemyByType(id));
                        }
                }
        }

       
        //初始化点击事件
        auto listener=EventListenerTouchOneByOne::create();
        listener->onTouchBegan=(Touch* touch,Event* event)
        {
                CCLog("Touch Began!");
                Vec2 locationInNode=enemylayer->convertToNodeSpace(touch->getLocation());
                Size s=enemylayer->getContentSize();
                Rect rect=Rect(0,0,s.width,s.height);
                if(!rect.containsPoint(locationInNode))
                        return false;

                Vec2 tilepos;
                MapPosToTilePos(Vec2(locationInNode.x,locationInNode.y),tilepos);
                if(tilepos.x >= 0 && tilepos.y >=0 &&
                        tilepos.x < enemylayer->getLayerSize().width && tilepos.y < enemylayer->getLayerSize().height)
                {
                        Sprite* node=enemylayer->getTileAt(tilepos);
                        if(node)
                        {
                                SelectSprite(node);
                        }
                }
                //根据位置获取单元格,设置为选中状态并刷新数据到面板
                return true;
        };
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,enemylayer);
       

        auto itemlayer=map->getLayer("item");
        for(int i=0;i<map->getMapSize().width;i++)
        {
                for(int j=0;j<map->getMapSize().height;j++)
                {
                        int id=itemlayer->getTileGIDAt(Vec2(i,j));
                        CCLog("x=%d,y=%d",i,j);
                        auto cursprite=enemylayer->getTileAt(Vec2(i,j));
                        //if(id && cursprite)
                        //{
                        //        cursprite->setUserData(ObjManager::getInstance().InitItemByType(id));
                        //}
                }
        }

        //初始化门动画
        auto doorTexture=map->getLayer("door")->getTexture();
        int doordata[]={0,1,2,3};
        std::string doorname[]={"DOOR_YELLOW","DOOR_BLUE","DOOR_RED","DOOR_GREEN"};
        for(int i=0;i<getNum(doordata);i++)
        {
                doordata;
                auto frame0=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*0,blocksize,blocksize));
                auto frame1=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*1,blocksize,blocksize));
                auto frame2=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*2,blocksize,blocksize));
                auto frame3=SpriteFrame::createWithTexture(doorTexture,Rect(blocksize*doordata,blocksize*3,blocksize,blocksize));
                animFrames.pushBack(frame0);
                animFrames.pushBack(frame1);
                animFrames.pushBack(frame2);
                animFrames.pushBack(frame3);
                auto animation=Animation::createWithSpriteFrames(animFrames,0.05f);
                animFrames.clear();
                AnimationCache::getInstance()->addAnimation(animation,doorname);
        }

        CCLog("Leave InitMap");
}

void MagicTower::InitBoard()
{
        CCLog("Enter InitBoard");
        //初始化面板
        char title;
#if(CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
        sprintf(title,"魔塔 第%d层",thislevel);
#else
        sprintf(title,"MagicTower %dth",thislevel);
#endif
        board.maintitle=Label::createWithSystemFont(IConvConvert_GBKToUTF8(title),"黑体",30);
        board.maintitle->setColor(Color3B::GREEN);
        board.maintitle->setAnchorPoint(Vec2(0.5f,0.5f));
        board.maintitle->setPosition(board.board->getContentSize().width/2,blocksize*5+16);
        board.board->addChild(board.maintitle);

        board.heroname=Label::createWithSystemFont(IConvConvert_GBKToUTF8(hero.name),"黑体",24);
        board.heroname->setColor(Color3B::RED);
        board.heroname->setAnchorPoint(Vec2(0.5f,0.5f));
        board.heroname->setPosition(board.board->getContentSize().width/4,blocksize*5-16);
        board.board->addChild(board.heroname);

        board.enemyname=Label::createWithSystemFont(IConvConvert_GBKToUTF8("敌方"),"黑体",24);
        board.enemyname->setColor(Color3B::RED);
        board.enemyname->setAnchorPoint(Vec2(0.5f,0.5f));
        board.enemyname->setPosition(board.board->getContentSize().width*7/8,blocksize*5-16);
        board.board->addChild(board.enemyname);

        board.life_hero=Label::createWithBMFont("myfont.fnt","life");
        board.life_hero->setAnchorPoint(Vec2(0,0));
        board.life_hero->setScale(0.4f);
        board.life_hero->setPosition(blocksize*1,blocksize*3+5);
        board.board->addChild(board.life_hero);

        board.offense_hero=Label::createWithBMFont("myfont.fnt","offense");
        board.offense_hero->setAnchorPoint(Vec2(0,0));
        board.offense_hero->setScale(0.4f);
        board.offense_hero->setPosition(blocksize*1,blocksize*2+5);
        board.board->addChild(board.offense_hero);

        board.defense_hero=Label::createWithBMFont("myfont.fnt","defense");
        board.defense_hero->setAnchorPoint(Vec2(0,0));
        board.defense_hero->setScale(0.4f);
        board.defense_hero->setPosition(blocksize*1,blocksize*1+5);
        board.board->addChild(board.defense_hero);

        board.money_hero=Label::createWithBMFont("myfont.fnt","money");
        board.money_hero->setAnchorPoint(Vec2(0,0));
        board.money_hero->setScale(0.4f);
        board.money_hero->setPosition(blocksize*1,blocksize*0+5);
        board.board->addChild(board.money_hero);

        board.yellowkey=Label::createWithBMFont("myfont.fnt","yellowkey");
        board.yellowkey->setAnchorPoint(Vec2(0,0));
        board.yellowkey->setScale(0.4f);
        board.yellowkey->setPosition(blocksize*4,blocksize*3+5);
        board.board->addChild(board.yellowkey);

        board.bluekey=Label::createWithBMFont("myfont.fnt","bluekey");
        board.bluekey->setAnchorPoint(Vec2(0,0));
        board.bluekey->setScale(0.4f);
        board.bluekey->setPosition(blocksize*4,blocksize*2+5);
        board.board->addChild(board.bluekey);

        board.redkey=Label::createWithBMFont("myfont.fnt","redkey");
        board.redkey->setAnchorPoint(Vec2(0,0));
        board.redkey->setScale(0.4f);
        board.redkey->setPosition(blocksize*4,blocksize*1+5);
        board.board->addChild(board.redkey);

        board.life_enemy=Label::createWithBMFont("myfont.fnt","life");
        board.life_enemy->setAnchorPoint(Vec2(0,0));
        board.life_enemy->setScale(0.4f);
        board.life_enemy->setPosition(blocksize*11,blocksize*3+5);
        board.board->addChild(board.life_enemy);

        board.offense_enemy=Label::createWithBMFont("myfont.fnt","offense");
        board.offense_enemy->setAnchorPoint(Vec2(0,0));
        board.offense_enemy->setScale(0.4f);
        board.offense_enemy->setPosition(blocksize*11,blocksize*2+5);
        board.board->addChild(board.offense_enemy);

        board.defense_enemy=Label::createWithBMFont("myfont.fnt","defense");
        board.defense_enemy->setAnchorPoint(Vec2(0,0));
        board.defense_enemy->setScale(0.4f);
        board.defense_enemy->setPosition(blocksize*11,blocksize*1+5);
        board.board->addChild(board.defense_enemy);

        CCLog("Leave InitBoard");
}

void MagicTower::InitHero()
{
        CCLog("Enter InitHero");
        ismoving=false;
        //加载英雄图片
        auto director=Director::getInstance();
        Size visibleSize = director->getVisibleSize();
        auto heroTexture=Director::getInstance()->getTextureCache()->addImage("hero.png");
        auto frame0=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*0,blocksize*1,blocksize,blocksize));
        hero.heroSprite=Sprite::createWithSpriteFrame(frame0);
        hero.heroSprite->setAnchorPoint(Vec2(0,0));
        MoveUnitInTile(hero.nexttilepos,hero.heroSprite);

        map->addChild(hero.heroSprite);

        //存储英雄移动动画
        std::string dirname[]={"down","left","right","up"};
        Vector<SpriteFrame*> animFrames(4);
        for(int i=0;i<4;i++)
        {
                auto frame0=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*0,blocksize*i,blocksize,blocksize));
                auto frame1=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*1,blocksize*i,blocksize,blocksize));
                auto frame2=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*2,blocksize*i,blocksize,blocksize));
                auto frame3=SpriteFrame::createWithTexture(heroTexture,Rect(blocksize*3,blocksize*i,blocksize,blocksize));
                animFrames.pushBack(frame0);
                animFrames.pushBack(frame1);
                animFrames.pushBack(frame2);
                animFrames.pushBack(frame3);
                auto animation=Animation::createWithSpriteFrames(animFrames,0.05f);
                animation->setRestoreOriginalFrame(false);
                AnimationCache::getInstance()->addAnimation(animation,dirname);
                animFrames.clear();
        }

        //初始化攻击动画
        auto attackTexture= Director::getInstance()->getTextureCache()->addImage("attack.png");
        Size unitsize=attackTexture->getContentSizeInPixels();
        for(int i=0;i<25;i++)
        {
                auto frame0=SpriteFrame::createWithTexture(attackTexture,
                        Rect(i/5*unitsize.width/5,i%5*unitsize.height/5,unitsize.width/5,unitsize.height/5));
                animFrames.pushBack(frame0);
        }
        AnimationCache::getInstance()->addAnimation(Animation::createWithSpriteFrames(animFrames,0.05f),"attack");
        animFrames.clear();

        CCLog("Leave InitHero");
}

void MagicTower::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
        MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
void MagicTower::OnMove(EventKeyboard::KeyCode keyCode, Event* event)
{
        CCLog("Enter OnMove");
        auto animCache=AnimationCache::getInstance();
        Animation* curanimation=NULL;
        Vec2 delta;
        int direction;

        switch(keyCode)
        {
                case EventKeyboard::KeyCode::KEY_UP_ARROW:
                        curanimation=animCache->getAnimation("up");
                        delta.setPoint(0,blocksize);
                        direction=25;
                        break;

                case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
                        curanimation=animCache->getAnimation("down");
                        delta.setPoint(0,-blocksize);
                        direction=26;
                        break;

                case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
                        curanimation=animCache->getAnimation("left");
                        delta.setPoint(-blocksize,0);
                        direction=23;
                        break;

                case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
                        curanimation=animCache->getAnimation("right");
                        delta.setPoint(blocksize,0);
                        direction=24;
                        break;

                default:
                        DefaultKeyboardDispatcher(keyCode);
                        return;
        }

        //判断英雄位置是否可以移动
        if(curanimation && !ismoving)
        {
                MoveHero(hero.heroSprite->getPosition()+delta,curanimation,direction);
        }
        CCLog("Leave OnMove");
}
#endif

void MagicTower::PlayHeroMovement(const Vec2& newpos,Animation* anim,int direction,const std::function<void(void)>& afteraction)
{//anim:帧动画afteraction:状态更新回调
        CCLog("Enter PlayeHeroMovement");
        hero.heroSprite->setSpriteFrame(anim->getFrames().at(0)->getSpriteFrame());
       
        //移动动画和帧动画同时进行
        auto spawn=Spawn::createWithTwoActions(Animate::create(anim),MoveTo::create(0.2f,newpos));

        //帧动画+移动动画->状态更新->可通行->连击
        hero.heroSprite->runAction(Sequence::create(spawn,CallFuncN::create((Node* node)
        {//如果有回调函数需要写一起,否则单另作为Sequence依次执行会失效,不知道是不是bug
                afteraction();
                ismoving=false;
                CCLog("ismoving");
                FlushBoard();
        }),NULL));
        CCLog("Leave PlayeHeroMovement");
}

void MagicTower::MoveHero(const Vec2& newpos,Animation* anim,int direction)
{//若成功,则捡物品或攻击
        CCLog("Enter MoveHero");

        ismoving=true;

        Vec2 tilepos;
        MapPosToTilePos(newpos+Vec2(blocksize/2,blocksize/2),tilepos);

        if(map->getLayer("floor")->getTileGIDAt(tilepos) == FLOOR_WALL)
        {//禁止通行
                ismoving=false;
                return;
        }

        //若是地板则进行上层判断
        auto layer=map->getLayer("item");
        switch(layer->getTileGIDAt(tilepos))
        {
                case ITEM_REDDIAMOND:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.offense += 100;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;

                case ITEM_BLUEDIAMOND:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.defense += 50;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;

                case ITEM_REDBLOOD:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.life += 400;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;

                case ITEM_BLUEBLOOD:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.life += 200;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;
                       
                case ITEM_YELLOWKEY:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.keyyellow++;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;
                       
                case ITEM_BLUEKEY:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.keyblue++;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;
                       
                case ITEM_REDKEY:
                        PlayHeroMovement(newpos,anim,direction,()
                        {//刷新+音乐+物品动画
                                hero.keyred++;
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                SimpleAudioEngine::getInstance()->playEffect("eat.mp3");
                        });
                        return;
                       
                default://若为空,执行上层判断
                        break;
        }

        layer=map->getLayer("enemy");
        if(layer->getTileGIDAt(tilepos))
        {//若有敌人
                PlayHeroMovement(newpos,anim,direction,()
                {
                        auto animation=AnimationCache::getInstance()->getAnimation("attack");
                        auto attacksprite=Sprite::createWithSpriteFrame(animation->getFrames().at(0)->getSpriteFrame());
                        attacksprite->setAnchorPoint(Vec2(0,0));
                        attacksprite->setPosition(-attacksprite->getContentSize().width/4,-attacksprite->getContentSize().height/4);
                        //初始化攻击动画+音乐
                        hero.heroSprite->addChild(attacksprite);
                        attackEnemy(layer,tilepos,attacksprite,Animate::create(animation));       
                });
                return;
        }
        //若为空,执行上层判断

        layer=map->getLayer("door");
        switch(layer->getTileGIDAt(tilepos))
        {
                case DOOR_YELLOW:
                        {
                                hero.keyyellow--;
                                auto animation=AnimationCache::getInstance()->getAnimation("DOOR_YELLOW");
                                auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
                                        CallFuncN::create((Node*){
                                        CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                        layer->removeChild(layer->getTileAt(tilepos),true);
                                })),CallFuncN::create([](Node*){
                                        SimpleAudioEngine::getInstance()->playEffect("open.mp3");
                                }));
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
                                        CallFuncN::create((Node*){
                                                PlayHeroMovement(newpos,anim,direction,[](){});
                                })));                       
                        }
                        return;

                case DOOR_BLUE:
                        {
                                hero.keyblue--;
                                auto animation=AnimationCache::getInstance()->getAnimation("DOOR_BLUE");
                                auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
                                        CallFuncN::create((Node*){
                                        CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                        layer->removeChild(layer->getTileAt(tilepos),true);
                                })),CallFuncN::create([](Node*){
                                        SimpleAudioEngine::getInstance()->playEffect("open.mp3");
                                }));
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
                                        CallFuncN::create((Node*){
                                                PlayHeroMovement(newpos,anim,direction,[](){});
                                })));               
                        }
                        return;

                case DOOR_RED:
                        {
                                hero.keyred--;
                                auto animation=AnimationCache::getInstance()->getAnimation("DOOR_RED");
                                auto spawn=Spawn::createWithTwoActions(Sequence::createWithTwoActions(Animate::create(animation),
                                        CallFuncN::create((Node*){
                                        CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                        layer->removeChild(layer->getTileAt(tilepos),true);
                                })),CallFuncN::create([](Node*){
                                        SimpleAudioEngine::getInstance()->playEffect("open.mp3");
                                }));
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->getTileAt(tilepos)->runAction(Sequence::createWithTwoActions(spawn,
                                        CallFuncN::create((Node*){
                                                PlayHeroMovement(newpos,anim,direction,[](){});
                                })));       
                        }
                        return;
               
                case DOOR_GREEN:
                        ismoving=false;
                        return;

                case DOOR_UPSTAIRS:
                        {
                                //更新地图
                                Director::getInstance()->setDepthTest(false);
                                hero.nexttilepos=Vec2(HeroInitPos[(thislevel+1)*4],HeroInitPos[(thislevel+1)*4+1]);
                                auto trans=TransitionCrossFade::create(0.5,MagicTowerLayerManager::getInstance().getScene(thislevel+1));
                                if(trans)
                                        Director::getInstance()->replaceScene(trans);
                                ismoving=false;
                        }
                        return;

                case DOOR_DOWNSTAIRS:
                        {
                                //更新地图
                                Director::getInstance()->setDepthTest(false);
                                hero.nexttilepos=Vec2(HeroInitPos[(thislevel-1)*4+2],HeroInitPos[(thislevel-1)*4+3]);
                                auto trans=TransitionCrossFade::create(0.5,MagicTowerLayerManager::getInstance().getScene(thislevel-1));
                                if(trans)
                                        Director::getInstance()->replaceScene(trans);
                                ismoving=false;
                        }
                        return;
        }

        //若无对象存在,则移动英雄
        PlayHeroMovement(newpos,anim,direction,[](){});
        //在执行PlayerHeroMovement的地方,ismoving交给该函数处理
        CCLog("Leave MoveHero");
}

void MagicTower::attackEnemy(TMXLayer* layer,Vec2 tilepos,Sprite* attacksprite,Animate* animate)
{
        CCLog("Enter attackEnemy");

        //判断英雄是否移动了,如果移动则去除animate并结束
        Vec2 herointile;
        MapPosToTilePos(hero.heroSprite->getPosition()+Vec2(blocksize/2,blocksize/2),herointile);
        CCLog("hero:(%f %f)",herointile.x,herointile.y);
        if(herointile != tilepos)
        {
                attacksprite->stopAllActions();
                hero.heroSprite->removeChild(attacksprite,true);
                return;
        }

        attacksprite->runAction(Sequence::create(animate,CallFuncN::create((Node* attacksprite)
        {
                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                ValueMap* val=static_cast<ValueMap*>(layer->getTileAt(tilepos)->getUserData());
                int enemylife=(*val)["life"].asInt();
                int enemyoffense=(*val)["offense"].asInt();
                int enemydefense=(*val)["defense"].asInt();
                int harmetoh=(hero.defense>enemyoffense)?0:enemyoffense-hero.defense;
                //enemy对hero造成的伤害,如果hero的防>enemy的攻,则无伤害
                int harmhtoe=(enemydefense>hero.offense)?0:hero.offense-enemydefense;
                hero.life -= harmetoh;
                enemylife -= harmhtoe;
                SimpleAudioEngine::getInstance()->playEffect("fight.mp3");       
                (*val)["life"]=enemylife;
                FlushBoard(val);

                if(enemylife < 0 || hero.life < 0)
                {
                        if(hero.life < 0)
                        {//英雄挂了
                        }
                        else
                        {
                                attacksprite->stopAllActions();
                                hero.money += (*val)["money"].asInt();
                                hero.heroSprite->removeChild(attacksprite,true);
                                CCLog("x=%d,y=%d",tilepos.x,tilepos.y);
                                layer->removeChild(layer->getTileAt(tilepos),true);
                                FlushBoard(val);
                                //刷新面板
                        }
                }
                else
                {
                        attackEnemy(layer,tilepos,static_cast<Sprite*>(attacksprite),animate);
                }
        }),NULL));

        CCLog("Leave attackEnemy");
}

void MagicTower::DefaultKeyboardDispatcher(EventKeyboard::KeyCode keycode)
{//处理其他键盘事件
       
}

void MagicTower::TilePosToMapPos(const Vec2& pos,Vec2& objpos)
{//pos为Tile坐标系,相对于窗口左上角
        float rex=pos.x*blocksize;
        float rey=map->getContentSize().height-pos.y*blocksize;
        objpos.setPoint(rex,rey);
}

void MagicTower::MapPosToTilePos(const Vec2& pos,Vec2& objpos)
{//pos为map坐标系,相对于左下角
        float rex=pos.x/(blocksize);
        float rey=(map->getContentSize().height-pos.y)/(blocksize);
        objpos.setPoint(int(rex),int(rey));
}

void MagicTower::MoveUnitInTile(const Vec2& pos,Sprite* obj)
{//pos为Tile坐标系,相对于左上角
        float rex=pos.x*blocksize;
        float rey=map->getContentSize().height-pos.y*blocksize-blocksize;
        obj->setPosition(rex,rey);
}

void MagicTower::FlushBoard(ValueMap* obj)
{
        CCLog("Enter FlushBoard");
        char title;
#if(CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
        sprintf(title,"魔塔 第%d层",thislevel);
#else
        sprintf(title,"MagicTower %dth",thislevel);
#endif
        board.maintitle->setString(IConvConvert_GBKToUTF8(title));
        board.heroname->setString(IConvConvert_GBKToUTF8(hero.name));
        sprintf(title,"%d",hero.life);
        board.life_hero->setString(IConvConvert_GBKToUTF8(title));
        sprintf(title,"%d",hero.offense);
        board.offense_hero->setString(IConvConvert_GBKToUTF8(title));
        sprintf(title,"%d",hero.defense);
        board.defense_hero->setString(IConvConvert_GBKToUTF8(title));
        sprintf(title,"%d",hero.money);
        board.money_hero->setString(IConvConvert_GBKToUTF8(title));
        sprintf(title,"%d",hero.keyyellow);
        board.yellowkey->setString(IConvConvert_GBKToUTF8(title));
        sprintf(title,"%d",hero.keyblue);
        board.bluekey->setString(IConvConvert_GBKToUTF8(title));
        sprintf(title,"%d",hero.keyred);
        board.redkey->setString(IConvConvert_GBKToUTF8(title));

        if(obj)
        {
                int category=(*obj)["category"].asInt();
                if(category == TYPE_ENEMY)
                {
                        board.enemyname->setString(IConvConvert_GBKToUTF8((*obj)["name"].asString()));
                        sprintf(title,"%d",(*obj)["life"].asInt());
                        board.life_enemy->setString(IConvConvert_GBKToUTF8(title));
                        sprintf(title,"%d",(*obj)["offense"].asInt());
                        board.offense_enemy->setString(IConvConvert_GBKToUTF8(title));
                        sprintf(title,"%d",(*obj)["defense"].asInt());
                        board.defense_enemy->setString(IConvConvert_GBKToUTF8(title));
                }
                else if(category == TYPE_ITEM)
                {
                }
        }
        CCLog("Leave FlushBoard");

}

void MagicTower::SelectSprite(Sprite* sprite)
{
        CCLog("Enter SelectSprite");
        auto data=static_cast<ValueMap*>(sprite->getUserData());
        if((*data)["selected"].asBool())
        {
                sprite->removeChildByTag(1000);
                (*data)["selected"]=false;
        }
        else
        {
                auto texture=map->getLayer("enemy")->getTexture();
                int hei=texture->getContentSize().height;
                auto selsprite=Sprite::createWithTexture(texture,Rect(0,texture->getContentSize().height-blocksize,blocksize,blocksize));
                //设置为最后一个
                selsprite->setAnchorPoint(Vec2(0,0));
                selsprite->setPosition(0,0);
                sprite->addChild(selsprite,selsprite->getLocalZOrder(),1000);
                FlushBoard(data);
                (*data)["selected"]=true;
        }
        CCLog("Leave SelectSprite");
}

//MagicTowerLayerManager管理场景切换
MagicTowerLayerManager& MagicTowerLayerManager::getInstance()
{
        static MagicTowerLayerManager manager;
        return manager;
}

Scene* MagicTowerLayerManager::getScene(int layer)
{
        curlayer=layer;
        auto curscene=Scene::create();
        auto curlayer=new MagicTower(layer);
        if (curscene && curlayer)
        {
                curscene->addChild(curlayer);
                curlayer->autorelease();
        }
        return curscene;
}

Hero MagicTower::hero;
Board MagicTower::board;

MagicTowerLayerManager::MagicTowerLayerManager()
{
        curlayer=1;
        MagicTower::hero.name="勇士";
        MagicTower::hero.life=1000;
        MagicTower::hero.offense=200;
        MagicTower::hero.defense=200;
        MagicTower::hero.keyyellow=10;
        MagicTower::hero.keyblue=10;
        MagicTower::hero.keyred=10;
        MagicTower::hero.money=1000;
        MagicTower::hero.nexttilepos=Vec2(6,10);//初始位置
        SimpleAudioEngine::getInstance()->playBackgroundMusic("background.mp3",true);
}



0xAA55 发表于 2014-6-22 18:26:40

又一使用cocos2b的家伙。
这画质你敢拿出来给人看?

元始天尊 发表于 2014-6-22 18:34:24

几年前的魔塔就是这画质,照样很多人玩,至少比dos画质好画质这玩意,还是要有清晰图片的

0xAA55 发表于 2014-6-22 18:55:25

元始天尊 发表于 2014-6-22 10:34
几年前的魔塔就是这画质,照样很多人玩,至少比dos画质好画质这玩意,还是要有清晰图片的
...

画质可不比DOS好。你知道画质的意思么?作为一个艺术品,我能说沙罗曼蛇的画质比雷电2好么?

元始天尊 发表于 2014-6-22 21:15:12

0xAA55 发表于 2014-6-22 18:55
画质可不比DOS好。你知道画质的意思么?作为一个艺术品,我能说沙罗曼蛇的画质比雷电2好么? ...

我不需要知道这2游戏画质怎样,因为我不那么关心画质,我更关心程序逻辑,画质的话,2d程序主要还是靠图片,魔塔坐到这个程度基本上逻辑已经出来了,剩下的美工什么的对我来说都不是重点,因为我不做这方面东西,画质这种东西是可以慢慢调的,至于说你要不要用3d方式显卡渲染,和怎么内部实现都是个人喜好。我可以不用粒子效果,我可以不用物理引擎。你既然会3d编程都能编出一个命令行2048呢,我没学过图像编程,我用游戏引擎编出一个几年前的魔塔有啥不行的,我没学过,因此我有理由做到这个程度。当然要有时间我也会去改善画质

元始天尊 发表于 2014-6-22 21:21:10

0xAA55 发表于 2014-6-22 18:55
画质可不比DOS好。你知道画质的意思么?作为一个艺术品,我能说沙罗曼蛇的画质比雷电2好么? ...

另外,别说什么cocos2dx没人用之类的话,先搞懂cocos2d cocos2dx区别,不懂就乱说,现在这东西本来就很火。你觉得不好可以不用,谁又没逼着你用cocos2d,谁也没逼着我用热门的游戏引擎。我倒是觉得,如果没有曾经做出过几个小游戏,然后就去实现渲染引擎这种东西,那是筑高台于浮沙,这东西额都是循序渐进的,最开始写东西无论游戏还是什么,可能会写的画质不好,不过慢慢的会用了,就会好的,不是说一下子自己实现个引擎,然后就直接实现一个世人无法直视的游戏,显然不现实,就像你研究dos系统以为可以用到windows内核里去一样,试问可能么,你编出来有用的东西了吗

0xAA55 发表于 2014-6-23 12:30:12

元始天尊 发表于 2014-6-22 13:21
另外,别说什么cocos2dx没人用之类的话,先搞懂cocos2d cocos2dx区别,不懂就乱说,现在这东西本来就很火 ...

小学初中的时候我做出个各种各样的小游戏,高中的时候,都删了。所以到了大学我意识到游戏引擎的重要性。此外你搞混了我研究DOS的的初衷,我是为了搞到Windows内核里去?
装逼够了给我滚出去。

0xAA55 发表于 2014-6-23 12:31:36

元始天尊 发表于 2014-6-22 13:15
我不需要知道这2游戏画质怎样,因为我不那么关心画质,我更关心程序逻辑,画质的话,2d程序主要还是靠图 ...

你关心这个你关心那个,你知道你的玩家关心什么?
改天我让喷神James给你的游戏做一个视频。
另外你难道还不能理解一个论坛的坛主为什么要编写控制台游戏?是因为水平限制?

0xAA55 发表于 2014-6-23 12:36:44

你发这个帖子就是为了秀一下代码?你没看我的帖子基本都是教程么
谁会看你的代码。

元始天尊 发表于 2014-6-23 15:07:00

0xAA55 发表于 2014-6-23 12:36
你发这个帖子就是为了秀一下代码?你没看我的帖子基本都是教程么
谁会看你的代码。 ...

要说编码中间遇到什么问题,那就多了去了,总结起来没个一天搞不定,你那些相对来说量比较小,所以可以吧整个探索过程呈现出来,我只好只展示结果了

0xAA55 发表于 2014-6-23 15:23:29

元始天尊 发表于 2014-6-23 07:07
要说编码中间遇到什么问题,那就多了去了,总结起来没个一天搞不定,你那些相对来说量比较小,所以可以吧 ...

还是希望你能把过程说一下,要点说一下。这样比较好
页: [1]
查看完整版本: 自己动手写魔塔游戏