坦克大战实现

先将常用的函数与头文件,宏定义等写到一个公共类中

#ifndef __Common_H__
    #define __Common_H__
    #include "cocos2d.h"
    #include "SimpleAudioEngine.h"
    #include "cocos-ext.h"
    USING_NS_CC;
    USING_NS_CC_EXT;

    #define winSize CCDirector::sharedDirector()->getWinSize()
    #define TANK_SPEED 2
    #define BULLET_SPEED 4
    #define TANK_CREATE_INTERVAL 3
    #define TANK_SHOOT_INTERVAL 1
    #define TIME_OVER 300
    #define TANK_BOMB "TANK_BOMB"
    class Common
    {
    public:
        enum DIRECTION
        {
            UP,RIGHT,DOWN,LEFT,INVALID_DIR
        };
        enum TileType
        {
            NONE,BLOCK,STEEL,HOME
        };
        enum 
        {
            ZO_LAYER_0=100,ZO_BULLET,ZO_TANK,ZO_LAYER_1,ZO_ITEM,ZO_LAYER_SETUP
        };
        static TileType getTileType(int gid)
        {
            if (gid==5||gid==6||gid==11||gid==12)
            {
                return STEEL;
            }
            if (gid==13||gid==14||gid==19||gid==20)
            {
                return BLOCK;
            }
            if (gid==17||gid==18||gid==23||gid==24)
            {
                return HOME;
            }

             return NONE;

        }
        static CCScene* scene(cclayer *layer)
        {
            CCScene *s=CCScene::create();
            s->addChild(layer);
            return s;
        }

        static const char* format(int v,const char *prefix="",const char *suffix="")
        {
            static char buf[1024];
            sprintf(buf,"%s%d%s",prefix,v,suffix);
            return buf;
        }

        static void moveNodeX(CCNode *n,int dx)
        {
            n->setPositionX(n->getPositionX()+dx);
        }
        static void moveNodeY(CCNode *n,int dy)
        {
            n->setPositionY(n->getPositionY()+dy);
        }
        static void moveNode(CCNode*n,CCPoint pt)
        {
            moveNodeX(n,pt.x);
            moveNodeY(n,pt.y);
        }

        static const CCPoint Map2PointLB(CCTMXTiledMap *_map,CCPoint ptTile)
        {
            ptTile.y=_map->getMapSize().height-1-ptTile.y;
            return ccp(ptTile.x*_map->getTileSize().width,ptTile.y*_map->getTileSize().height);
        }

        static CCPoint Point2Tile(CCTMXTiledMap *_map,CCPoint ptMap)
        {
            int dx=_map->getTileSize().width;
            int dy=_map->getTileSize().height;
            //CCPoint ptMap=_map->convertToNodeSpace(ptGL);
            int x=ptMap.x/dx;
            int y=ptMap.y/dy;
            y=_map->getMapSize().height-1-y;


            return ccp(x,y);
        }


    };
    #endif

开始界面与选择界面非常简单,可以略过,游戏主界面包含的方法如下

#ifndef __LayerGame_H__
    #define __LayerGame_H__
    #include "Common.h"
    #include "TankFriend.h"
    #include "MenuCtrl.h"
    #include "AI.h"
    #include "LayerSetup.h"
    class Item;

    class LayerGame:public cclayer
    {
    public:
        //CREATE_FUNC(LayerGame);
        void onExit();
        static LayerGame*create(unsigned int index)
        {
            LayerGame *pRt=new LayerGame();
            if (pRt&&pRt->init(index))
            {
                pRt->autorelease();
                return pRt;
            }else
            {
                delete pRt;
                pRt=NULL;
                return pRt;

            }
        }
        bool init(unsigned int index);
        void update(float);

        CCTMXTiledMap *_map;
        TankFriend *_tankFriend;

        void DirCtrlPress(CCObject*);
        void Shoot(CCObject*);
        void Setup(CCObject*);
        void TimeOut(float);
        void setGodMode(int interval)
        {
            _godMode=true;
            CCDelayTime*delay=CCDelayTime::create(interval);
            CCCallFunc *callFunc=CCCallFunc::create(this,callfunc_selector(LayerGame::unSetGodMode));
            this->runAction(CCSequence::createWithTwoActions(delay,callFunc));
        }
        void unSetGodMode()
        {
            _godMode=false;
        }

        void addItem();
        void eatItem(Item*);
        void eatItemBomb();
        void eatItemSteel();
        void setPause()
        {
            CCDirector::sharedDirector()->pause();
        }
        enum FAILURE_REASON
        {
            TIME_OUT,HOME_DESTORY,TANK_DIE
        };
        static void gameOver(FAILURE_REASON reason);
        CCArray *_bullets;
        CCArray *_items;
        AI *_ai;
        int _victoryCount;
        int _curCount;
        int _index;
        int _life;
        bool _godMode;

    };

    #endif

添加友军坦克

 class TankFriend:public CCSprite { public: CREATE_FUNC(TankFriend); bool init(); CCTMXTiledMap *getMap(); void setTileSize(int tileSize); int _tileSize; void Move(Common::DIRECTION dir); void doMove(); void Turn(Common::DIRECTION dir); bool canMove(Common::DIRECTION dir); Bullet *Shoot(); Common::DIRECTION _dir; int _damage; };

添加控制按钮,控制坦克的前进,后退与发射

其中前进,后退是按着一直走,发射子弹是按一下,发射一下

bool MenuCtrl::init()
    {
        Ccmenu::init();
        schedule(schedule_selector(MenuCtrl::CheckActive));
        return true;
    }

    void MenuCtrl::CheckActive(float)
    {
        if (this->m_pSelectedItem&&m_eState==kCcmenuStateTrackingTouch)
        {
            m_pSelectedItem->activate();
        }
    }

以上重写了menu方法,使得可以按着按钮一直运动

添加子弹层

class Bullet:public CCSprite
    {
    public:
        CREATE_FUNC(Bullet);
        bool init();

        void setPicture(const char *filename);

        static void CheckBullets(CCTMXTiledMap *_map,CCArray *_bullets);
        int _damage;
    };

敌军坦克由电脑随机生成

敌军坦克类继承友军坦克

bool TankEnemy::init()
{

    CCSprite::initWithFile("tank/armor/armor2U.png");
    _tileSize=0;
    _dir=Common::UP;
    this->setZOrder(Common::ZO_TANK);

    Turn(Common::DOWN);

    return true;
}

随机产生敌军坦克方法

#ifndef __AI_H__
    #define __AI_H__
    #include "Common.h"
    class AI:public CCNode
    {
    public:
        CREATE_FUNC(AI);
        bool init();
        void onExit();
        CCTMXTiledMap *getMap()
        {
            return (CCTMXTiledMaP*)getParent();
        }
        //generate enemy tank
        void createTank(float);
        bool _createFlag;
        CCArray *_tanks;
        CCArray *_bullets;
        //move enemy tank
        void moveTank(float);
        //make enemy tank shoot bullet
        void Shoot(float);
        //collision detection
        void update(float);

        bool _pause;
        void pause();
        void resume();

    };
    #endif

添加 多种道具,当打死一坦克时就会有一定概率产生一个道具

class Item:public CCSprite
    {
    public:
        enum ItemType
        {
            IT_ACTIVE,IT_BOMB,IT_MINTANK,IT_STAR,IT_STEEL,IT_TIMER,IT_COUNT
        };
        CREATE_FUNC(Item);
        bool init();
        void setPosition();
        ItemType _type;
    };

添加控制按钮,产生模态对话框,控制音量与音效

#ifndef __LayerSetup_H__
    #define __LayerSetup_H__
    #include "Common.h"
 class MyCCControlSlider : public CCControlSlider { public: static MyCCControlSlider* create(const char* bgFile,const char* progressFile,const char* thumbFile) { // Prepare background for slider CCSprite *backgroundSprite = CCSprite::create(bgFile); // Prepare progress for slider CCSprite *progresssprite = CCSprite::create(progressFile); // Prepare thumb (menuItem) for slider CCSprite *thumbSprite = CCSprite::create(thumbFile); MyCCControlSlider *pRet = new MyCCControlSlider(); pRet->initWithSprites(backgroundSprite,progresssprite,thumbSprite); pRet->autorelease(); return pRet; } bool ccTouchBegan(CCTouch*t,CCEvent*e) { return CCControlSlider::ccTouchBegan(t,e); } void ccTouchEnded(CCTouch*t,CCEvent*e) { CCControlSlider::ccTouchEnded(t,e); } void ccTouchMoved(CCTouch*t,CCEvent*e) { CCControlSlider::ccTouchMoved(t,e); } void ccTouchCancelled(CCTouch*t,CCEvent*e) { CCControlSlider::ccTouchCancelled(t,e); } }; class LayerSetup:public cclayer { public: CREATE_FUNC(LayerSetup); bool init(); void ChangeBGVolume(CCObject*,CCControlEvent); void ChangeEffectVolume(CCObject*,CCControlEvent); void Close(CCObject*); bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent); void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent); void ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent); void ccTouchCancelled(CCTouch *pTouch,CCEvent *pEvent); Ccmenu *_menu; bool _bMenuItemClicked; MyCCControlSlider* _volumeBG; bool _bVolumeBGClicked; MyCCControlSlider* _volumeEffect; bool _bVolumeEffectClicked; }; #endif // !--

由于CCControlSlider中有些成员变量是保护的,需要将CCControlSlider重写,才可以进行。

注意:当在实现暂停道具的时候,由于要暂停与重启,重启时报错

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention

原先用//scheduleOnce(schedule_selector(AI::resume),1);来调用resume函数,老是报错,帧循环发生错误,后来改成
CCDelayTime* delay=CCDelayTime::create(5.0f);
CCCallFunc* callFunc = CCCallFunc::create(this,callfunc_selector(AI::resume));
this->runAction(CCSequence::create(delay,callFunc,NULL));

就成功了,原因暂且不明。

运行结果

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...