学习cocos2d-x自带的SimpleGame

来源:互联网 发布:金山办公室软件 编辑:程序博客网 时间:2024/05/07 15:34

作为一个菜鸟,就得从头学起。

cocos2d-x文件目录里面自带了很多例子,其中就有一个SimpleGame。它属于射击类的小小小游戏。

开始学吧

首先新建个cocos2d-x项目,打开终端进入project-creator目录,输入:

./create_project.py -project MySimpleGame -package xxx.com -language cpp

回车,打开刚才建好的MySimpleGame项目,先加入所需的资源:

这些资源直接从自带的SimpleGame工程里面copy过来。我这里加的是HD目录下的。

进到HelloWorldScene.h,添加偷懒的宏定义并修改我们HelloWorldScene类的父类为CCLayerColor:

USING_NS_CC;
class HelloWorld : public CCLayerColor

然后在HelloWorldScene.cppinit(),保留最后的return语句,其他的删掉,为了把游戏的背景设为白色,添加代码:

    if ( !CCLayerColor::initWithColor(ccc4(255, 255, 255, 255)) )    {        return false;    }
接着为类添加两个private变量:

private:    CCSize visibleSize;    CCPoint origin;
init()中用这两个变量保存屏幕的尺寸和坐标,再添加一个玩家精灵:

    visibleSize = CCDirector::sharedDirector()->getVisibleSize();    origin = CCDirector::sharedDirector()->getVisibleOrigin();        CCSprite *player = CCSprite::create("Player.png",CCRectMake(0, 0, 27*2, 40*2));    player->setPosition(ccp(origin.x + player->getContentSize().width/2,origin.y + visibleSize.height/2));    this->addChild(player);
关于屏幕的适配看这里

运行程序看看:




接下来,会随机出现一些幽灵,那么就建一个数组来保存它们,添加成员变量,再增加一个private方法addTarget生产幽灵:

    CCArray *_targets;    void addTarget();
下一步,就是到HelloWorldScene.cpp中实现addTarget方法:

void HelloWorld::addTarget(){    CCSprite *target = CCSprite::create("Target.png", CCRectMake(0,0,27*2,40*2));    //让target出现的高度随机,但不要超出边界    float minY = target->getContentSize().height/2;    float maxY = visibleSize.height - target->getContentSize().height/2;    int rangeY = (int)(maxY - minY);    int actual = (rand() % rangeY) + minY; //这就是随机产生出来的target位置高    target->setPosition(ccp(visibleSize.width + target->getContentSize().width/2,origin.y + actual));    this->addChild(target);        //产生target的速度    int minDuration = 2;    int maxDuration = 4;    int rangeDuration = maxDuration - minDuration;    int actualDuration = (rand() % rangeDuration) + minDuration;        //target在会执行的动作,其实在这里就是直线移动。    CCFiniteTimeAction *actionMove = CCMoveTo::create((float)actualDuration, ccp(-target->getContentSize().width/2, actual));    target->runAction(CCSequence::create(actionMove,CCCallFuncN::create(this,callfuncN_selector(HelloWorld::spriteMoveFinished))));    target->setTag(1);    _targets->addObject(target);}

上面的方法中用到了spriteMoveFinished方法,这是一个回调,下面还得定义两个public方法:

    void spriteMoveFinished(CCObject *pSender);    void gameLogic(float dt);
然后去实现它们:

void HelloWorld::gameLogic(float dt){    this->addTarget();}void HelloWorld::spriteMoveFinished(cocos2d::CCObject *pSender){    }

接着,我们得去init()方法中,为_targets分配内存,再添加一个定时器来执行gameLogic方法:

    _targets = new CCArray();    this->schedule(schedule_selector(HelloWorld::gameLogic),1);

运行我们的程序,就能看到幽灵出来了:




我们得发射子弹了,那就得点击屏幕,就得有Touch事件发生。

添加一个private数组存放子弹,并在init()中为它分配空间:

    CCArray *_projectiles;

    _projectiles = new CCArray;

随后我们得定义两个与Touch有关的public方法:

    void registerWithTouchDispatcher();    virtual void ccTouchesEnded(CCSet *touches,CCEvent *event);

分别再实现它们:

void  HelloWorld::registerWithTouchDispatcher(){    CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);}void  HelloWorld::ccTouchesEnded(cocos2d::CCSet *touches, cocos2d::CCEvent *event){    //获取touch的坐标    CCTouch *touch = (CCTouch*)(touches->anyObject());    CCPoint location = touch->getLocation();        //产生子弹    CCSprite *projectile = CCSprite::create("Projectile.png", CCRectMake(0, 0, 20*2, 20*2));projectile->setPosition( ccp(origin.x+20, origin.y+visibleSize.height/2) );    //子弹偏移float offX = location.x - projectile->getPosition().x;float offY = location.y - projectile->getPosition().y;    // 超边界,不发if (offX <= 0) return;    this->addChild(projectile);        //确定子弹发射位置    float realX = origin.x+visibleSize.width + (projectile->getContentSize().width/2);float ratio = offY / offX;float realY = (realX * ratio) + projectile->getPosition().y;CCPoint realDest = ccp(realX, realY);        //子弹能发射多远    float offRealX = realX - projectile->getPosition().x;float offRealY = realY - projectile->getPosition().y;float length = sqrtf((offRealX * offRealX) + (offRealY*offRealY));float velocity = 480/1; // 480pixels/1secfloat realMoveDuration = length/velocity;        //执行动作    projectile->runAction( CCSequence::create(                                              CCMoveTo::create(realMoveDuration, realDest),                                              CCCallFuncN::create(this,                                                                  callfuncN_selector(HelloWorld::spriteMoveFinished)),                                              NULL) );        projectile->setTag(2);_projectiles->addObject(projectile); //子弹加入数组}

对于registerWithTouchDispatcher的用法可以看这篇博客

运行程序,touch屏幕我们就可发射子弹了:


我们会发现,现在子弹还不能消灭幽灵,let's do it!

添加一个public方法:

    void updateGame(float dt);
然后实现:

void HelloWorld::updateGame(float dt){    CCArray *projectilesToDelete = new CCArray;    CCObject* it = NULL;    CCObject* jt = NULL;    CCARRAY_FOREACH(_projectiles, it){        //算出子弹框CCSprite *projectile = dynamic_cast<CCSprite*>(it);CCRect projectileRect = CCRectMake(                                           projectile->getPosition().x - (projectile->getContentSize().width/2),                                           projectile->getPosition().y - (projectile->getContentSize().height/2),                                           projectile->getContentSize().width,                                           projectile->getContentSize().height);        CCArray* targetsToDelete =new CCArray;                //算出打击的目标框        CCARRAY_FOREACH(_targets, jt){CCSprite *target = dynamic_cast<CCSprite*>(jt);CCRect targetRect = CCRectMake(                                           target->getPosition().x - (target->getContentSize().width/2),                                           target->getPosition().y - (target->getContentSize().height/2),                                           target->getContentSize().width,                                           target->getContentSize().height);                        //表示打中了目标,把这些目标加入到数组中            if (projectileRect.intersectsRect(targetRect)){targetsToDelete->addObject(target);}}        //移除这些被打中的目标        CCARRAY_FOREACH(targetsToDelete, jt){CCSprite *target = dynamic_cast<CCSprite*>(jt);_targets->removeObject(target);this->removeChild(target, true);                       }        if (targetsToDelete->count() > 0){projectilesToDelete->addObject(projectile);}targetsToDelete->release();}        //移除打中目标的子弹    CCARRAY_FOREACH(projectilesToDelete, it){CCSprite* projectile = dynamic_cast<CCSprite*>(it);_projectiles->removeObject(projectile);this->removeChild(projectile, true);}projectilesToDelete->release(); //释放}

我写了点简单的注释,有助于理解。
运行程序以后,对准幽灵发射子弹吧。

我们就会发现,幽灵永远也打不完,这样无休止的打下去,是人都会疯了。

So,我们得有个规则来判断输赢。

win:消灭5个幽灵

lose:幽灵跑到了我们的后面

好,有了规则后,就来执行吧。

首先,新建一个C++类,文件名为GameOverScene,用下面的代码替换GameOverScene.h中的代码:

#ifndef __MySimpleGame__GameOverScene__#define __MySimpleGame__GameOverScene__#include "cocos2d.h"USING_NS_CC;class GameOverLayer : public CCLayerColor{public:    GameOverLayer():_label(NULL) {};    virtual ~GameOverLayer();    bool init();    CREATE_FUNC(GameOverLayer);        void gameOverDone();        CC_SYNTHESIZE_READONLY(CCLabelTTF*, _label, Label);};class GameOverScene : public CCScene{public:    GameOverScene():_layer(NULL) {};    ~GameOverScene();    bool init();    CREATE_FUNC(GameOverScene);        CC_SYNTHESIZE_READONLY(GameOverLayer*, _layer, Layer);};#endif /* defined(__MySimpleGame__GameOverScene__) */

上面的代码,声明了一个布景类和一个场景类,用来显示咱们输赢后的结果。

用下来的代码替换GameoverScene.cpp中的代码:

#include "GameOverScene.h"#include "HelloWorldScene.h"bool GameOverScene::init(){if( CCScene::init() ){this->_layer = GameOverLayer::create();this->_layer->retain();this->addChild(_layer);return true;}else{return false;}}GameOverScene::~GameOverScene(){if (_layer){_layer->release();_layer = NULL;}}bool GameOverLayer::init(){if ( CCLayerColor::initWithColor( ccc4(255,255,255,255) ) ){CCSize winSize = CCDirector::sharedDirector()->getWinSize();this->_label = CCLabelTTF::create("","Artial", 32);_label->retain();_label->setColor( ccc3(0, 0, 0) );_label->setPosition( ccp(winSize.width/2, winSize.height/2) );this->addChild(_label);this->runAction( CCSequence::create(                                            CCDelayTime::create(3),                                            CCCallFunc::create(this,                                                               callfunc_selector(GameOverLayer::gameOverDone)),                                            NULL));return true;}else{return false;}}void GameOverLayer::gameOverDone(){CCDirector::sharedDirector()->replaceScene( HelloWorld::scene() );}GameOverLayer::~GameOverLayer(){if (_label){_label->release();_label = NULL;}}

这里理解起来也没什么难度,所以我就直接用自带的代码了。

接下来,回到HelloWorldScene.h中,添加一个private变量,用来判断消灭了多少幽灵:

    int _projectilesDestroyed;
然后到HelloWorldScene.cpp的开头添加头文件:

#include "GameOverScene.h"
updateGame中找到下面的代码处:

在其后面加上代码:

            _projectilesDestroyed++;if (_projectilesDestroyed >= 5) //移除的目标数目>5,You Win!{GameOverScene *gameOverScene = GameOverScene::create();gameOverScene->getLayer()->getLabel()->setString("You Win!");CCDirector::sharedDirector()->replaceScene(gameOverScene);}

这段代码很明显,当我们消灭了5个幽灵以后,就切换到gameOverScene显示“You Win!”.

那“You Lose”去哪里了?

看一下我们的spriteMoveFinished方法,是空的,为其添加下面的代码:

    CCSprite *sprite = (CCSprite *)pSender;this->removeChild(sprite, true);    if (sprite->getTag() == 1)  // target{_targets->removeObject(sprite);        GameOverScene *gameOverScene = GameOverScene::create();gameOverScene->getLayer()->getLabel()->setString("You Lose");CCDirector::sharedDirector()->replaceScene(gameOverScene);        }else if (sprite->getTag() == 2) // projectile{_projectiles->removeObject(sprite);}

早前我们分别给targetprojectile精灵设置了tag值,现在就可以用这个值来判断传过来的精灵是哪一个了。

编译运行游戏:



Yes,I‘am win.

如果有需要可以点这里下载源码,当然还可以直接看Cocos2d-x自带的SimpleGame代码,几乎是一样的。

0 0
原创粉丝点击