Cocos2dx游戏教程(十二):“见缝插针”,游戏结算界面和音效
前面游戲主場景已經(jīng)可以試玩了吧,但是是不是感覺很單調(diào)呢,如何進入下一關呢?要不要配置些音樂呢,在我的BGM中是不是有些無敵的感覺呢
首先我們來看一下需要添加的文件
我們可以看到,在這一節(jié)新增了GameFailedLayer,GameSuccessLayer,GameMusic,GameLevel四個類。
我們都知道如何創(chuàng)建一個層,我們首先來看一下勝利失敗的界面吧
下面帶領大家看看下如何實現(xiàn)界面
一、創(chuàng)建結(jié)算層
1、勝利層
頭文件GameSuccessLayer.h
類文件 GameSuccessLayer.cpp
#include "GameSuccessLayer.h" #include "GameLevelScene.h" #include "Defines.h" #include "GameMenuScene.h" #include "GameScene.h" #include "GameDataManage.h" #include "GlobalManage.h"bool GameSuccessLayer::init() {if(!Layer::init()) { return false;}//勝利對話框initWinLayer();return true; }//勝利對話框 void GameSuccessLayer::initWinLayer() {//大背景auto bg = Sprite::create("scene/bg.jpg");bg->setPosition(WINSIZE / 2);this->addChild(bg);//過關背景auto bg2 = Sprite::create("win_or_lose/success.png");bg2->setPosition(Vec2(WINSIZE / 2));this->addChild(bg2, 1);//過關光效auto light = Sprite::create("win_or_lose/success_light.png");light->setPosition(Vec2(WINSIZE.width / 2, WINSIZE.height / 2 + bg2->getContentSize().height / 2 + light->getContentSize().height / 2 - 130));this->addChild(light);//過關文字auto title = Sprite::create("win_or_lose/success_title.png");title->setPosition(Vec2(WINSIZE.width / 2 - 30, WINSIZE.height / 2 + bg2->getContentSize().height / 2 + title->getContentSize().height / 2 - 30));this->addChild(title);//關卡auto level = Sprite::create("scene/level.png");level->setPosition(bg2->getContentSize().width / 2, 280);bg2->addChild(level);//關卡數(shù)auto levelTTF = Label::createWithCharMap("fonts/label/label_level_1.png", 31, 42, '0');levelTTF->setString(StringUtils::format("%d", GlobalManage::getInstance()->currentLevel));levelTTF->setPosition(level->getContentSize() / 2);level->addChild(levelTTF);//按鈕auto selectItem = MenuItemImage::create("win_or_lose/select.png", "win_or_lose/select.png");selectItem->initWithCallback(CC_CALLBACK_1(GameSuccessLayer::onReturnToSelectSceneBtnPressed, this));selectItem->setPosition(Vec2(200, 146));auto nextItem = MenuItemImage::create("win_or_lose/next.png", "win_or_lose/next.png");nextItem->initWithCallback(CC_CALLBACK_1(GameSuccessLayer::onNextLevelBtnPressed, this));nextItem->setPosition(Vec2(520, 146));auto menu = Menu::create(selectItem, nextItem, NULL);menu->setPosition(Vec2::ZERO);bg2->addChild(menu); }//返回開始菜單 void GameSuccessLayer::onReturnToMenuSceneBtnPressed(Ref* pSender) {GameDataManage::getInstance()->setCurrentMaxLevel(GlobalManage::getInstance()->currentLevel + 1);Director::getInstance()->replaceScene(GameMenuScene::createScene()); }//返回選關 void GameSuccessLayer::onReturnToSelectSceneBtnPressed(Ref* pSender) {Director::getInstance()->replaceScene(GameLevelScene::createScene()); }//分享 void GameSuccessLayer::onShareBtnPressed(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #endif }//重新開始 void GameSuccessLayer::onNextLevelBtnPressed(Ref* pSender) {if(GlobalManage::getInstance()->currentLevel >= GameDataManage::getInstance()->totalRow) {//跳轉(zhuǎn)到主菜單界面Director::getInstance()->replaceScene(GameMenuScene::createScene());} else {GameDataManage::getInstance()->setCurrentMaxLevel(GlobalManage::getInstance()->currentLevel + 1);GlobalManage::getInstance()->currentLevel = GlobalManage::getInstance()->currentLevel + 1;//初始化下一關GameDataManage::getInstance()->loadGameData(GlobalManage::getInstance()->currentLevel);Director::getInstance()->replaceScene(GameScene::createScene());} }2、失敗層
頭文件GameFailedLayer.h
類文件GameFailedLayer.cpp
#include "GameFailedLayer.h" #include "GameLevelScene.h" #include "Defines.h" #include "GameMenuScene.h" #include "GameScene.h" #include "GlobalManage.h"bool GameFailedLayer::init() {if(!Layer::init()) { return false;}//失敗對話框initFailedLayer();return true; }//勝利對話框 void GameFailedLayer::initFailedLayer() {//背景auto bg = Sprite::create("scene/bg.jpg");bg->setPosition(WINSIZE / 2);this->addChild(bg);//過關背景auto bg2 = Sprite::create("win_or_lose/failed.png");bg2->setPosition(Vec2(WINSIZE / 2));this->addChild(bg2, 1);//過關光效auto light = Sprite::create("win_or_lose/failed_light.png");light->setPosition(Vec2(WINSIZE.width / 2, WINSIZE.height / 2 + bg2->getContentSize().height / 2 + light->getContentSize().height / 2 - 130));this->addChild(light);//過關文字auto title = Sprite::create("win_or_lose/failed_title.png");title->setPosition(Vec2(WINSIZE.width / 2 - 30, WINSIZE.height / 2 + bg2->getContentSize().height / 2 + title->getContentSize().height / 2 - 30));this->addChild(title);//關卡auto level = Sprite::create("scene/level.png");level->setPosition(bg2->getContentSize().width / 2, 280);bg2->addChild(level);//關卡數(shù)auto levelTTF = Label::createWithCharMap("fonts/label/label_level_1.png", 31, 42, '0');levelTTF->setString(StringUtils::format("%d", GlobalManage::getInstance()->currentLevel));if (type == LanguageType::CHINESE) {levelTTF->setPosition(level->getContentSize() / 2);}else {levelTTF->setPosition(level->getContentSize().width, level->getContentSize().height / 2);}level->addChild(levelTTF);//按鈕auto selectItem = MenuItemImage::create("win_or_lose/select.png", "win_or_lose/select.png");selectItem->initWithCallback(CC_CALLBACK_1(GameFailedLayer::onReturnToSelectSceneBtnPressed, this));selectItem->setPosition(Vec2(200, 146));auto replayItem = MenuItemImage::create("win_or_lose/replay.png", "win_or_lose/replay.png");replayItem->initWithCallback(CC_CALLBACK_1(GameFailedLayer::onRestartBtnPressed, this));replayItem->setPosition(Vec2(520, 146));auto menu = Menu::create(selectItem, replayItem, NULL);menu->setPosition(Vec2::ZERO);bg2->addChild(menu);}//返回開始菜單 void GameFailedLayer::onReturnToMenuSceneBtnPressed(Ref* pSender) {Director::getInstance()->replaceScene(GameMenuScene::createScene()); }//返回選關 void GameFailedLayer::onReturnToSelectSceneBtnPressed(Ref* pSender) {Director::getInstance()->replaceScene(GameLevelScene::createScene()); }//分享 void GameFailedLayer::onShareBtnPressed(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #endif }//重新開始 void GameFailedLayer::onRestartBtnPressed(Ref* pSender) {Director::getInstance()->replaceScene(GameScene::createScene()); }勝利失敗界面已經(jīng)創(chuàng)建好了,那么我我們在GameScene中進行觸發(fā)吧,觸發(fā)方式如下,在GameScene中update下如下實現(xiàn)
//刷新游戲 void GameScene::update(float dt) {//刷新玩家小球位置auto max = userBallList.size() >= 4 ? 4 : userBallList.size();for (unsigned int i = 0; i < max; i++) {auto ball = userBallList.at(i);if (!ball) {continue;}ball->setPosition(360, 300 - 42 * i);ball->setVisible(true);}//檢測是否碰撞,如果碰撞,游戲結(jié)束if (isBallCollision) {//播放音效GameMusic::playEffect("music/fail.wav");circle->stopAction(rotate);this->runAction(Sequence::create(DelayTime::create(0.8f),CallFunc::create(CC_CALLBACK_0(GameScene::createFailedLayer, this)),NULL));unscheduleUpdate();}if (!isBallCollision) {if (userBallNum == 0) {//播放音效GameMusic::playEffect("music/win.wav");this->runAction(Sequence::create(DelayTime::create(0.5f),CallFunc::create(CC_CALLBACK_0(GameScene::createSuccessLayer, this)),NULL));unscheduleUpdate();}} }有人會問Update是干甚的?下一節(jié)將會帶領大家了解cocos2dx刷新和定時器
二、創(chuàng)建選關界面
上述勝利失敗界面已經(jīng)顯示出來了,那么我們?nèi)绾芜M入下一關呢?
首先我們需要一個關卡選擇的界面,還記得前面第二個場景中關卡選擇按鈕么,就是跳轉(zhuǎn)到這個界面哦
在這一段代碼中涉及到觸摸方法,后續(xù)會對相關內(nèi)容進行單獨的介紹
那么我們直接看一下實現(xiàn)
頭文件GameLevelScene.h
#pragma once #include "cocos2d.h"USING_NS_CC;class GameLevelScene : public cocos2d::Layer { public:GameLevelScene();~GameLevelScene();static cocos2d::Scene* createScene();virtual bool init(); CREATE_FUNC(GameLevelScene);//觸摸開始方法bool onTouchBegan(Touch* touch, Event* event);//觸摸移動方法 void onTouchMoved(Touch* touch, Event* event);//觸摸結(jié)束方法void onTouchEnded(Touch* touch, Event* event); public:void onKeyReleased(EventKeyboard::KeyCode keycode, Event* event); public://點擊關卡按鈕void onLevelBtnPressed(Ref* pSender, int level);//返回按鈕回調(diào)void onBackBtnPressed(cocos2d::Ref *pSender); private:Layer *levelLayer; private:Point pos1;Point pos2;//當前頁編號int pageIndex; };類文件GameLevelScene.cpp
#include "GameLevelScene.h" #include "GameScene.h" #include "GameMenuScene.h" #include "GameDataManage.h" #include "GlobalManage.h" #include "Defines.h"#define PAGE_CONTIANER_MAX 40 #define LEVEL_PAGES (int)(ceil((float)(GameDataManage::getInstance()->totalRow) / (float)(PAGE_CONTIANER_MAX)))GameLevelScene::GameLevelScene() :pageIndex(1){ }GameLevelScene::~GameLevelScene() { }Scene* GameLevelScene::createScene() {auto scene = Scene::create();auto layer = GameLevelScene::create();scene->addChild(layer);return scene; }bool GameLevelScene::init() {if(!Layer::init()) {return false;}//繪制游戲背景auto bg = Sprite::create("level/bg_level.jpg");bg->setPosition(WINSIZE / 2);this->addChild(bg);//返回按鈕auto back = MenuItemImage::create("common/back.png","common/back.png",CC_CALLBACK_1(GameLevelScene::onBackBtnPressed, this));back->setPosition(60, WINSIZE.height - 60);auto menu = Menu::create(back, NULL);menu->setPosition(Point::ZERO);this->addChild(menu, 1);levelLayer = Layer::create();this->addChild(levelLayer);//繪制關卡int index = 0;int maxLevel = GameDataManage::getInstance()->totalRow;for(int i = 1; i <= maxLevel; i++) {MenuItemImage *item = NULL;if(i <= GameDataManage::getInstance()->getCurrentMaxLevel()) {item = MenuItemImage::create("level/has_pass.png","level/has_pass.png",CC_CALLBACK_1(GameLevelScene::onLevelBtnPressed, this, i));} else {item = MenuItemImage::create("level/has_pass.png","level/has_pass.png",CC_CALLBACK_1(GameLevelScene::onLevelBtnPressed, this, i));//添加所鎖auto lock = Sprite::create("level/lock.png");lock->setPosition(Vec2(item->getContentSize() / 2));item->addChild(lock, 10);}item->setPosition(WINSIZE.width * (int)(index / PAGE_CONTIANER_MAX) + 130 + index % 5 * (item->getContentSize().width + 5),1080-(index % PAGE_CONTIANER_MAX) / 5 * (item->getContentSize().width + 5));auto menu = Menu::create(item, NULL);menu->setPosition(Point::ZERO);levelLayer->addChild(menu);index++;//顯示關卡數(shù)auto levelTTF = Label::createWithCharMap("fonts/label/label_level_2.png", 32, 44, '0');levelTTF->setPosition(item->getContentSize() / 2);levelTTF->setString(to_string(i));item->addChild(levelTTF);}//創(chuàng)建一個觸摸監(jiān)聽 auto touchListener = EventListenerTouchOneByOne::create(); //向下傳遞觸摸事件touchListener->setSwallowTouches(false);touchListener->onTouchBegan = CC_CALLBACK_2(GameLevelScene::onTouchBegan, this);touchListener->onTouchMoved = CC_CALLBACK_2(GameLevelScene::onTouchMoved, this);touchListener->onTouchEnded = CC_CALLBACK_2(GameLevelScene::onTouchEnded, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);//注冊捕捉監(jiān)聽auto listenerkeyPad = EventListenerKeyboard::create();listenerkeyPad->onKeyReleased = CC_CALLBACK_2(GameLevelScene::onKeyReleased, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(listenerkeyPad, this);return true; }//觸摸開始方法 bool GameLevelScene::onTouchBegan(Touch* touch, Event* event) {pos1 = touch->getLocation();return true; } //觸摸移動方法 void GameLevelScene::onTouchMoved(Touch* touch, Event* event) {pos2 = touch->getLocation(); } //觸摸結(jié)束方法 void GameLevelScene::onTouchEnded(Touch* touch, Event* event) {if(pos1.x - pos2.x > 100) {//向后翻頁if(pageIndex < LEVEL_PAGES) {if(levelLayer->getNumberOfRunningActions() == 0) {levelLayer->runAction(MoveTo::create(0.5f, Point(-WINSIZE.width * pageIndex, 0)));pageIndex++; }} else {pageIndex = LEVEL_PAGES;} }if(pos1.x - pos2.x < -100) {//向前翻頁if(pageIndex > 1) {if(levelLayer->getNumberOfRunningActions() == 0) {levelLayer->runAction(MoveTo::create(0.5f, Point(-WINSIZE.width * (pageIndex - 2), 0))); pageIndex--;}} else {pageIndex = 1;}} }void GameLevelScene::onKeyReleased(EventKeyboard::KeyCode keycode, Event* event) {if (keycode == EventKeyboard::KeyCode::KEY_ESCAPE) {Director::getInstance()->replaceScene(GameMenuScene::createScene());} else if (keycode == EventKeyboard::KeyCode::KEY_MENU) {} }//點擊關卡按鈕 void GameLevelScene::onLevelBtnPressed(Ref* pSender, int level) {GlobalManage::getInstance()->currentLevel = level;if(GlobalManage::getInstance()->currentLevel > GameDataManage::getInstance()->getCurrentMaxLevel()) {} else {//友盟統(tǒng)計關卡GameDataManage::getInstance()->loadGameData(GlobalManage::getInstance()->currentLevel);Director::getInstance()->replaceScene(GameScene::createScene());} }//返回按鈕回調(diào) void GameLevelScene::onBackBtnPressed(cocos2d::Ref *pSender) {Director::getInstance()->replaceScene(GameMenuScene::createScene()); }三、游戲音效SimpleAudioEngine
SimpleAudioEngine是一個單例,使用方式為
CocosDenshion::SimpleAudioEngine::getInstance()開啟音效別忘了在AppDelegete中將如下打開哦,這個是設置游戲前臺后臺運行時需要做的操作哦
// 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 pauseCocosDenshion::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 hereCocosDenshion::SimpleAudioEngine::getInstance()->resumeBackgroundMusic(); }我們來看下對GameMusic的封裝
頭文件GameMusic.h
#pragma once #include "cocos2d.h" #include "GlobalManage.h" #include "SimpleAudioEngine.h"class GameMusic { public://播放音樂static void playMusic(const char *music, bool loop = false);//播放音效static void playEffect(const char *effect, bool loop = false);//停止音樂static void stopMusic();//停止音效static void stopAllEffect();//暫停音樂static void pauseMusic();//恢復音樂static void resumeMusic(); };類文件GameMusic.cpp
#include "GameMusic.h" #include "GlobalManage.h"USING_NS_CC;//播放音樂 void GameMusic::playMusic(const char *music, bool loop) {if(GlobalManage::getInstance()->isPlayMusic) {CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic(music, loop);} }//播放音效 void GameMusic::playEffect(const char *effect, bool loop) {if(GlobalManage::getInstance()->isPlayEffect) {CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(effect, loop);} }//停止音樂 void GameMusic::stopMusic() {CocosDenshion::SimpleAudioEngine::getInstance()->stopBackgroundMusic(); }//停止音效 void GameMusic::stopAllEffect() {CocosDenshion::SimpleAudioEngine::getInstance()->stopAllEffects(); }//暫停音樂 void GameMusic::pauseMusic() {CocosDenshion::SimpleAudioEngine::getInstance()->pauseBackgroundMusic(); }//恢復音樂 void GameMusic::resumeMusic() {CocosDenshion::SimpleAudioEngine::getInstance()->resumeBackgroundMusic(); }實現(xiàn)到這里其實整個游戲大部分已經(jīng)完成啦,有興趣的小伙伴們可以發(fā)散下自己的思維啊,設計一些更好玩的玩法哈
總結(jié)
以上是生活随笔為你收集整理的Cocos2dx游戏教程(十二):“见缝插针”,游戏结算界面和音效的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔试面试题目
- 下一篇: OS实验-模拟实现首次/最佳/最坏适应算