欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

Cocos2dx游戏教程(十二):“见缝插针”,游戏结算界面和音效

发布时间:2023/12/16 编程问答 57 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Cocos2dx游戏教程(十二):“见缝插针”,游戏结算界面和音效 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

前面游戏主场景已经可以试玩了吧,但是是不是感觉很单调呢,如何进入下一关呢?要不要配置些音乐呢,在我的BGM中是不是有些无敌的感觉呢


首先我们来看一下需要添加的文件

我们可以看到,在这一节新增了GameFailedLayer,GameSuccessLayer,GameMusic,GameLevel四个类。
我们都知道如何创建一个层,我们首先来看一下胜利失败的界面吧

下面带领大家看看下如何实现界面

一、创建结算层

1、胜利层
头文件GameSuccessLayer.h

#pragma once #include "cocos2d.h"USING_NS_CC;extern LanguageType type;class GameSuccessLayer :public cocos2d::Layer{ public:CREATE_FUNC(GameSuccessLayer);virtual bool init(); public://胜利对话框void initWinLayer(); public://返回开始菜单void onReturnToMenuSceneBtnPressed(Ref* pSender);//返回选关void onReturnToSelectSceneBtnPressed(Ref* pSender);//分享void onShareBtnPressed(Ref* pSender);//下一关按钮回调void onNextLevelBtnPressed(cocos2d::Ref *pSender); };

类文件 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);//关卡数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) {//跳转到主菜单界面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

#pragma once #include "cocos2d.h"USING_NS_CC;extern LanguageType type;class GameFailedLayer :public cocos2d::Layer{ public:CREATE_FUNC(GameFailedLayer);virtual bool init(); public://胜利对话框void initFailedLayer(); public://返回开始菜单void onReturnToMenuSceneBtnPressed(Ref* pSender);//返回选关void onReturnToSelectSceneBtnPressed(Ref* pSender);//分享void onShareBtnPressed(Ref* pSender);//重新开始void onRestartBtnPressed(Ref* pSender); };

类文件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);//关卡数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()); }

胜利失败界面已经创建好了,那么我我们在GameScene中进行触发吧,触发方式如下,在GameScene中update下如下实现

//刷新游戏 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);}//检测是否碰撞,如果碰撞,游戏结束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是干甚的?下一节将会带领大家了解cocos2dx刷新和定时器

二、创建选关界面

上述胜利失败界面已经显示出来了,那么我们如何进入下一关呢?
首先我们需要一个关卡选择的界面,还记得前面第二个场景中关卡选择按钮么,就是跳转到这个界面哦
在这一段代码中涉及到触摸方法,后续会对相关内容进行单独的介绍
那么我们直接看一下实现

头文件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);//触摸结束方法void onTouchEnded(Touch* touch, Event* event); public:void onKeyReleased(EventKeyboard::KeyCode keycode, Event* event); public://点击关卡按钮void onLevelBtnPressed(Ref* pSender, int level);//返回按钮回调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++;//显示关卡数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);}//创建一个触摸监听 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);//注册捕捉监听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(); } //触摸结束方法 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 {//友盟统计关卡GameDataManage::getInstance()->loadGameData(GlobalManage::getInstance()->currentLevel);Director::getInstance()->replaceScene(GameScene::createScene());} }//返回按钮回调 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(); }

实现到这里其实整个游戏大部分已经完成啦,有兴趣的小伙伴们可以发散下自己的思维啊,设计一些更好玩的玩法哈

总结

以上是生活随笔为你收集整理的Cocos2dx游戏教程(十二):“见缝插针”,游戏结算界面和音效的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。