菜单场景创建
这次我们先把菜单场景创建好,为了跟MoonWarriors html5进行匹配,我们跟html5的文件名尽量起一样的。
在Classes目录下先创建一个SysMenu的C++文件,这是程序的入口跟菜单选项
接下来就是编辑SysMenu.h文件了
这里需要说一下的就是静态方法scene(),肯定有同学想问了,cocos2d-x类的初始化不都是由create()来创建的吗?为什么这里需要一个静态方法呢?直接create()不就行了,呵呵,因为调用了预编译的方法,所以create()只能在类内部使用,如果想切换场景通过外部类来调用的话,这里就需要包装一下,通过scene()来让外部类调用。好了,看一下我们的SysMenu.cpp
#include "SysMenu.h" #include "SimpleAudioEngine.h" using namespace cocos2d; using namespace CocosDenshion; //静态方法,方便类外调用 CCScene* SysMenu::scene(){ // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object SysMenu *layer = SysMenu::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } bool SysMenu::init(){ //初始化标记 bool bRet = false; //场景大小 winSize = CCDirector::sharedDirector()->getWinSize(); //背景图 CCSprite *sp = CCSprite::create("loading.png"); //设置锚点(不清楚的同学可以单独查一下setPosition跟setAnchorPoint的区别,这个在cocos2d中还是比较重要的知识点) sp->setAnchorPoint(ccp(0, 0)); this->addChild(sp, 0, 1); //logo图片 CCSprite *logo = CCSprite::create("logo.png"); logo->setAnchorPoint(ccp(0, 0)); logo->setPosition(ccp(0, 250)); this->addChild(logo, 10, 1); //新游戏 菜单 CCSprite *newGameNormal = CCSprite::create("menu.png", CCRect(0, 0, 126, 33)); CCSprite *newGameSelected = CCSprite::create("menu.png", CCRect(0, 33, 126, 33)); CCSprite *newGameDisabled = CCSprite::create("menu.png", CCRect(0, 66, 126, 33)); //设置 菜单 CCSprite *gameSettingsNormal = CCSprite::create("menu.png", CCRect(126, 0, 126, 33)); CCSprite *gameSettingsSelected = CCSprite::create("menu.png", CCRect(126, 33, 126, 33)); CCSprite *gameSettingsDisabled = CCSprite::create("menu.png", CCRect(126, 66, 126, 33)); //关于 菜单 CCSprite *aboutNormal = CCSprite::create("menu.png", CCRect(252, 0, 126, 33)); CCSprite *aboutSelected = CCSprite::create("menu.png", CCRect(252, 33, 126, 33)); CCSprite *aboutDisable = CCSprite::create("menu.png", CCRect(252, 66, 126, 33)); CCMenuItemSprite *newGame = CCMenuItemSprite::create(newGameNormal, newGameSelected, newGameDisabled,this, NULL); CCMenuItemSprite *gameSettings = CCMenuItemSprite::create(gameSettingsNormal, gameSettingsSelected, gameSettingsDisabled,this, NULL); CCMenuItemSprite *about = CCMenuItemSprite::create(aboutNormal, aboutSelected, aboutDisable, this, NULL); CCMenu *menu = CCMenu::create(newGame, gameSettings, about, NULL); //每个菜单间隔10px(不知道是像素还是其他单位) menu->alignItemsVerticallyWithPadding(10); //居中 menu->setPosition(ccp(winSize.width/2, winSize.height/2-80)); this->addChild(menu); bRet = true; return bRet; }
这里面创建了很多精灵类,背景,logo,还有菜单都是精灵类,这里着重要说明的是菜单,CCMenu通过CCMenuItemSprite将CCSprinte一层层包装起来,
这样我们点击的时候就会调用不同的CCSprinte来显示,cocos2d将菜单包装得还是不错的,因为游戏除了界面就是菜单这几种元素。
OK,这里我们就可以跑一下看一下效果了
对了,如果你的屏幕是横向显示的,这就需要你在rootViewController.mm里找到以下代码,将它们改成
意思就是只支持横屏,原来以为cocos2D-x会在程序里支持转屏,但看了一下代码,2.0以后就不支持了,所以建议游戏开发者一开始就设定好游戏是横屏还是竖屏的。
接下来就是创建不停飞行的飞机,这就需要程序不停地刷屏了。
这里在init()方法底部加入
//创建贴图 CCTexture2D *tmp = CCTextureCache::sharedTextureCache()->addImage("ship01.png"); //创建飞船 _ship = CCSprite::createWithTexture(tmp, CCRect(0, 45, 60, 38)); //飞船贴图大小 CCSize shipSize = _ship->getContentSize(); //随机位置 CCPoint pos = ccp(CCRANDOM_0_1()*winSize.width, 0); _ship->setPosition(pos); //运动轨迹,从当前位置向上移动到窗口外 _ship->runAction(CCMoveTo::create(2.0, ccp(CCRANDOM_0_1()*winSize.width, pos.y + winSize.height + shipSize.height))); this->addChild(_ship, 0, 4); //这里只能调用一次运作,所以如果想让飞机不停地进入界面飞行的话就需要不停的刷新 //刷新界面 this->schedule(schedule_selector(SysMenu::update), 0.1);
通过调用update不停地刷新屏幕
void SysMenu::update(){ //如果飞船飞出窗口,我们就重新定位飞船的位置,重新飞入界面 if (_ship->getPosition().y > winSize.height) { CCPoint pos = ccp(CCRANDOM_0_1()*winSize.width, 10); _ship->setPosition(pos); _ship->runAction(CCMoveTo::create(floor(CCRANDOM_0_1()*5), ccp(CCRANDOM_0_1()*winSize.width, pos.y + winSize.height))); } }
这样就实现了飞船不停地进行界面飞行的效果。可是有没有感觉坏坏的味道?init()这个方法是不是太大了?我们可以将它进行分解,还有就是图片,我们可以初始的时候一次性加载图片放入贴图缓存,这样就不需要重复加载图片了,还有就是先加载大图,再加载小图(为什么?看这边http://article.ityran.com/archives/2310)因此我们进行重构
新代码如下:
#include "cocos2d.h" using namespace cocos2d; class SysMenu:CCLayer { private: //场景大小 CCSize winSize; //飞船精灵,因为菜单中需要飞船运动,所以将飞船设定为全局变量 CCSprite* _ship; CCTexture2D *_texture[10]; public: //初始化 virtual bool init(); //场景 static CCScene* scene(); //更新场景 virtual void update(); //加入背景 void addBackground(); //加入logo void addLogo(); //加入菜单 void addMenu(); //加入飞船 void addShipWithAction(); //加入背景音乐 void addMusic(); //调用预编译方法创建create()方法 CREATE_FUNC(SysMenu); };
SysMenu.cpp
#include "SysMenu.h" #include "SimpleAudioEngine.h" using namespace cocos2d; using namespace CocosDenshion; //静态方法,方便类外调用 CCScene* SysMenu::scene(){ // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object SysMenu *layer = SysMenu::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } bool SysMenu::init(){ //初始化标记 bool bRet = false; //场景大小 winSize = CCDirector::sharedDirector()->getWinSize(); CCTextureCache *textureCache = CCTextureCache::sharedTextureCache(); _texture[0] = textureCache->addImage("loading.png"); _texture[1] = textureCache->addImage("logo.png"); _texture[2] = textureCache->addImage("menu.png"); _texture[3] = textureCache->addImage("ship01.png"); this->addBackground(); this->addLogo(); this->addMenu(); this->addShipWithAction(); this->addMusic(); //这里只能调用一次运作,所以如果想让飞机不停地进入界面飞行的话就需要不停的刷新 //刷新界面 this->schedule(schedule_selector(SysMenu::update), 0.1); bRet = true; return bRet; } void SysMenu::update(){ //如果飞船飞出窗口,我们就重新定位飞船的位置,重新飞入界面 if (_ship->getPosition().y > winSize.height) { CCPoint pos = ccp(CCRANDOM_0_1()*winSize.width, 10); _ship->setPosition(pos); _ship->runAction(CCMoveTo::create(floor(CCRANDOM_0_1()*5), ccp(CCRANDOM_0_1()*winSize.width, pos.y + winSize.height))); } } void SysMenu::addBackground(){ //背景图 CCSprite *sp = CCSprite::createWithTexture(_texture[0]); //设置锚点(不清楚的同学可以单独查一下setPosition跟setAnchorPoint的区别,这个在cocos2d中还是比较重要的知识点) sp->setAnchorPoint(ccp(0, 0)); this->addChild(sp, 0, 1); } void SysMenu::addLogo(){ //logo图片 CCSprite *logo = CCSprite::createWithTexture(_texture[1]); logo->setAnchorPoint(ccp(0, 0)); logo->setPosition(ccp(0, 250)); this->addChild(logo, 10, 1); } void SysMenu::addMenu(){ //新游戏 菜单 CCSprite *newGameNormal = CCSprite::createWithTexture(_texture[2], CCRect(0, 0, 126, 33)); CCSprite *newGameSelected = CCSprite::createWithTexture(_texture[2], CCRect(0, 33, 126, 33)); CCSprite *newGameDisabled = CCSprite::createWithTexture(_texture[2], CCRect(0, 66, 126, 33)); //设置 菜单 CCSprite *gameSettingsNormal = CCSprite::createWithTexture(_texture[2], CCRect(126, 0, 126, 33)); CCSprite *gameSettingsSelected = CCSprite::createWithTexture(_texture[2], CCRect(126, 33, 126, 33)); CCSprite *gameSettingsDisabled = CCSprite::createWithTexture(_texture[2], CCRect(126, 66, 126, 33)); //关于 菜单 CCSprite *aboutNormal = CCSprite::createWithTexture(_texture[2], CCRect(252, 0, 126, 33)); CCSprite *aboutSelected = CCSprite::createWithTexture(_texture[2], CCRect(252, 33, 126, 33)); CCSprite *aboutDisable = CCSprite::createWithTexture(_texture[2], CCRect(252, 66, 126, 33)); CCMenuItemSprite *newGame = CCMenuItemSprite::create(newGameNormal, newGameSelected, newGameDisabled,this, NULL); CCMenuItemSprite *gameSettings = CCMenuItemSprite::create(gameSettingsNormal, gameSettingsSelected, gameSettingsDisabled,this, NULL); CCMenuItemSprite *about = CCMenuItemSprite::create(aboutNormal, aboutSelected, aboutDisable, this, NULL); CCMenu *menu = CCMenu::create(newGame, gameSettings, about, NULL); //每个菜单间隔10px(不知道是像素还是其他单位) menu->alignItemsVerticallyWithPadding(10); //居中 menu->setPosition(ccp(winSize.width/2, winSize.height/2-80)); this->addChild(menu); } void SysMenu::addShipWithAction(){ //创建飞船 _ship = CCSprite::createWithTexture(_texture[3], CCRect(0, 45, 60, 38)); //飞船贴图大小 CCSize shipSize = _ship->getContentSize(); //随机位置 CCPoint pos = ccp(CCRANDOM_0_1()*winSize.width, 0); _ship->setPosition(pos); //运动轨迹,从当前位置向上移动到窗口外 _ship->runAction(CCMoveTo::create(2.0, ccp(CCRANDOM_0_1()*winSize.width, pos.y + winSize.height + shipSize.height))); this->addChild(_ship, 0, 4); } void SysMenu::addMusic(){ SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.7); SimpleAudioEngine::sharedEngine()->playBackgroundMusic("mainMainMusic.mp3", true); }
代码下载