前面游戏主场景已经可以试玩了吧,但是是不是感觉很单调呢,如何进入下一关呢?要不要配置些音乐呢,在我的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 pause
CocosDenshion::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 here
CocosDenshion::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();
}
实现到这里其实整个游戏大部分已经完成啦,有兴趣的小伙伴们可以发散下自己的思维啊,设计一些更好玩的玩法哈