学习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.cpp的init(),保留最后的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);}
早前我们分别给target和projectile精灵设置了tag值,现在就可以用这个值来判断传过来的精灵是哪一个了。
编译运行游戏:
Yes,I‘am win.
如果有需要可以点这里下载源码,当然还可以直接看Cocos2d-x自带的SimpleGame代码,几乎是一样的。
- 学习cocos2d-x自带的SimpleGame
- Android跑起Cocos2d-x的SimpleGame
- Cocos2D-X SimpleGame & 初学者教程
- cocos2d-x之SimpleGame分析
- cocos2d-x入门(2)-实现一个简单的游戏SimpleGame
- 【cocos2d-x 2.x 学习与应用总结】10: cocos2d-x自带的shader及其使用
- Cocos2d-x-3. X使用自带的物理引擎
- cocos2d-x 自带动画
- cocos2d-x SimpleGame入门例程笔记
- cocos2d-x SimpleGame(6)百尺竿头,更进一步
- cocos2d-x for android:SimpleGame分析
- Cocos2d-x源代码剖析-SimpleGame代码剖析
- cocos2d-x for android:SimpleGame分析
- cocos2d-x-2.2/samples/Cpp/SimpleGame/ 问题
- Cocos2D-X SimpleGame cocos2d-x完成游戏后的一些锦上添花修饰 (6) ----版本cocos2d-2.0-x-2.0.3 .
- COCOS2D-X自带的DEMO解析和理解
- Cocos2d-x自带的屏幕适配方案
- cocos2d-x SimpleGame(7)关于第六章的第二种解决方案
- multimap排序
- 无法使用命令 /usr/bin/xdpyinfo 自动检查显示器颜色。请检查是否设置了 DISPLAY
- OCP-1Z0-053-200题-12题-96
- UBUNTU下双显示器设置
- 黑马程序员_(7K面试题)交通灯管理系统
- 学习cocos2d-x自带的SimpleGame
- 异常分享
- 40、流量统计--界面设计
- Windows下配置python环境变量
- iframe自适应高度
- OCP-1Z0-053-200题-13题-97
- EXTJS与java后台交互DWR使用
- My python/java notes
- JAVA位运算常见用法