首页 > 代码库 > 【Cocos游戏实战】功夫小子第七课之游戏主功能场景逻辑功能和暂停功能场景的分析和实现

【Cocos游戏实战】功夫小子第七课之游戏主功能场景逻辑功能和暂停功能场景的分析和实现

CSDN的markdown编辑器是吃屎了么!

!。什么玩意。!写了一半写不了东西还全没了,搞个毛线!


本节课的视频教程地址是:第七课在此 
假设本教程有帮助到您,希望您能点击进去观看一下,并且如今注冊成为极客学院的会员,能够免费领取30天学习时间,免费拿极客学院VIP,1000+高清视频。学习Android、HTML5、iOS各种开发技术,限时领取。手快的戳:http://e.jikexueyuan.com/invite/index.html?ZnJvbV9jb2RlPVkxblJUZSZ1bmFtZT1TdW9vTCZjaGFubmVsPWludml0ZV8xMDB3X3NoYXJlYnV0dG9uX2RpcmVjdDE=。验证手机号码和邮箱号码会赠送三天的会员时间。手机端首次也能够领取五天的会员时间哦(即使是购买年会员眼下也不过年费260)。成为极客学院学习会员能够无限制的下载和观看全部的学院站点的视频。谢谢您的支持!

转载请注明出处:http://blog.csdn.net/suool/article/details/47128637


不想再重写一遍了。简短点。这节课要实现和学习的内容有:(假设想看具体内容的请戳上面的连接,看下视频的教程更好)

技术分享

1.人物的运动状态控制——跳起。受伤,死亡推断。和怪物的打斗逻辑

2.碰撞检測(我们这个游戏因为是横版且人物仅仅可以在左右走。因此变化的坐标仅仅有X,所以检測起来也是非常easy的。

很多其它关于碰撞检測的东西见:http://shahdza.blog.51cto.com/2410787/1548097

3.关卡的失败和胜利推断以及相关的场景的分析和实现

4.暂停功能场景的分析和实现

关于跳起的动作这里简单的解释一下。

由于要模拟人物跳起后的一个近抛物线的运动轨迹,因此我们这里让Y轴的速度不断变化,而X轴不变,这个原理学过高中物理应该都明确。

这个函数就是:

	float velocity = 0.0f;  // 跳起速度
	float getVelocity();    // 获取跳跃的速度

逻辑的东西解释起来比較复杂,先把代码贴出来吧。

/*!
* \file GameLayer.h
* \date 2015/06/13 16:55
*
* \author SuooL
* Contact: hu1020935219@gmail.com
*
* \brief 游戏场景
*
* TODO: long description
*
* \note
*/

#ifndef __GameLayer__H__
#define __GameLayer__H__

#include <iostream>
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "ActionTool.h"
#include "GlobalData.h"
#include "GlobalDefine.h"
#include "extensions/cocos-ext.h"
#include "Monster.h"

USING_NS_CC;
using namespace extension;

class Hero;
class ProgressBar;
class GameMap;

class GameLayer : public Layer
{
public:

	static Scene* createScene();
	virtual bool init();

	// 暂停
	void gamePause(Ref* pSender);

	void gameOver(float delta);
	void gameVictory(float delta);
	// 技能--拳击--脚踢--超级技能--蹦
	void fistAttack(Ref* pSender, Control::EventType type);
	void footAttack(Ref* psender, Control::EventType type);
	void comboAttack(Ref* pSender, Control::EventType type);
	void jump(Ref* pSender, Control::EventType type);

	// 前进,后退
	void forward(Ref* pSender, Control::EventType type);
	void backward(Ref* pSender, Control::EventType type);

	bool isAttackMonster(Hero * hero, Monster* monster);

	virtual void update(float delta);

	CREATE_FUNC(GameLayer);

private:

	// 英雄&怪物
	Hero* m_pHero;
	Monster* m_pMonster1;

	GameMap* myMap;

	// 背景条
	Sprite* m_pBG;
	// 血条。能量前景条
	ProgressTimer* m_pHPBar;
	ProgressTimer* m_pMPBar;

	ControlButton * m_pComboBtn;
	Sprite* m_pComboPic;

	RenderTexture* render;
	RenderTexture* renderResult;

	float velocity = 0.0f;  // 跳起速度
	float getVelocity();    // 获取跳跃的速度

	bool m_bDirection;  // 行走的方向
	bool m_bRun;        // 是否在跑
	bool m_bJump;       // 是否在跳

};

#endif

实现文件为:

/*!
* \class GameLayer
*
* \ingroup GroupName
*
* \brief
*
* TODO: long description
*
* \note
*
* \author SuooL
*
* \version 1.0
*
* \date 六月 2015
*
* Contact: hu1020935219@gmail.com
*
*/
#include "GameLayer.h"
#include "GameMap.h"
#include "Hero.h"
#include "Monster.h"
#include "PauseLayer.h"
#include "GateMapLayer.h"
#include "MonsterOne.h"
#include "extensions/cocos-ext.h"   
#include "cocostudio/CocoStudio.h"

USING_NS_CC;
using namespace CocosDenshion;
using namespace cocos2d::extension; //引用cocos2d::extension命名空间

Scene* GameLayer::createScene()
{
	Scene* scene = Scene::create();
	GameLayer* layer = GameLayer::create();
	scene->addChild(layer);

	return scene;
}

bool GameLayer::init()
{
	if (!Layer::init())
	{
		return false;
	}

	if (getBoolFromXML(MUSIC_KEY))
	{
		float music = getFloatFromXML(MUSICVOL)*100.0f;
		aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));
		if (SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
		{
			aduioEngine->pauseBackgroundMusic();
			aduioEngine->playBackgroundMusic("Sound/gameBGM.wav", true);
		}
		else
			aduioEngine->playBackgroundMusic("Sound/gameBGM.wav", true);
	}
	else
		aduioEngine->pauseBackgroundMusic();

	velocity = 10.0f;
	m_bDirection = false;
	m_bRun = false;
	m_bJump = false;

	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("pnglist/mapBefore.plist");
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("pnglist/mapRoad.plist");

	String *bgName = String::createWithFormat("bgmap%d.png", m_iSelectGate);
	String *midName = String::createWithFormat("MapMiddle%d.png", m_iSelectGate);
	String *groundName = String::createWithFormat("MapGround%d.png", m_iSelectGate);
	String *beforeName = String::createWithFormat("MapBefore%d.png", m_iSelectGate);
	String *comoboName = String::createWithFormat("comboBtn%d.png", m_iSelectGate);

	auto bgPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(bgName->getCString()));
	bgPic->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);
	this->addChild(bgPic, 0);
	myMap = GameMap::create();
	myMap->InitMap(midName->getCString(), groundName->getCString(), beforeName->getCString());
	this->addChild(myMap, 1);

	// 界面控制键初始化
	// 技能键
	auto m_pFistBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("fist.png"));
	auto m_pFistBtn = ControlButton::create(m_pFistBG);
	m_pFistBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("fist.png"))->getContentSize());

	auto m_pFootBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("foot.png"));
	auto m_pFootBtn = ControlButton::create(m_pFootBG);
	m_pFootBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("foot.png"))->getContentSize());

	auto m_pJumpBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jump.png"));
	auto m_pJumpBtn = ControlButton::create(m_pJumpBG);
	m_pJumpBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jump.png"))->getContentSize());

	auto m_pComboBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(comoboName->getCString()));
	m_pComboBtn = ControlButton::create(m_pComboBG);
	m_pComboBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(comoboName->getCString()))->getContentSize());

	// 按键背景
	auto m_pFistPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("quan.png"));
	auto m_pFootPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jiao.png"));
	auto m_pJumpPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tiao.png"));
	m_pComboPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tiao.png"));

	auto m_pFistPicSize = m_pFistPic->getContentSize();
	m_pFistBtn->setPosition(ccp(m_pFistPicSize.width / 2, m_pFistPicSize.height / 2));
	m_pFistBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::fistAttack), Control::EventType::TOUCH_UP_INSIDE);

	auto m_pFootPicSize = m_pFootPic->getContentSize();
	m_pFootBtn->setPosition(ccp(m_pFootPicSize.width / 2, m_pFootPicSize.height / 2));
	m_pFootBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::footAttack), Control::EventType::TOUCH_UP_INSIDE);

	auto m_pJumpPicSize = m_pJumpPic->getContentSize();
	m_pJumpBtn->setPosition(ccp(m_pJumpPicSize.width / 2.0 - 1.5, m_pJumpPicSize.height / 2));
	m_pJumpBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::jump), Control::EventType::TOUCH_UP_INSIDE);

	auto m_pComboPicSize = m_pComboPic->getContentSize();
	m_pComboBtn->setPosition(ccp(m_pComboPicSize.width / 2 - 1.5, m_pComboPicSize.height / 2));
	m_pComboBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::comboAttack), Control::EventType::TOUCH_UP_INSIDE);

	m_pFistPic->addChild(m_pFistBtn, 1);
	m_pFootPic->addChild(m_pFootBtn, 1);
	m_pJumpPic->addChild(m_pJumpBtn, 1);
	m_pComboPic->addChild(m_pComboBtn, 1);

	m_pFistPic->setPosition(WINSIZE.width - 230, 76);
	m_pFootPic->setPosition(WINSIZE.width - 73, 76);
	m_pJumpPic->setPosition(WINSIZE.width - 60, 220);
	m_pComboPic->setPosition(WINSIZE.width - 387, 76);

	m_pComboPic->setVisible(false);


	this->addChild(m_pFistPic, 1);
	this->addChild(m_pFootPic, 1);
	this->addChild(m_pJumpPic, 1);
	this->addChild(m_pComboPic, 1);

	// 行走控制键。暂停键
	auto puaseGameItem = MenuItemSprite::create(
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("pauseNormal.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("pauseSelected.png")),
		CC_CALLBACK_1(GameLayer::gamePause, this)); // Pause

	auto backwardBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directionNormal.png"));
	auto backwardSelBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directionSelected.png"));
	auto backwardBtn = ControlButton::create(backwardBG);
	backwardBtn->setBackgroundSpriteForState(backwardSelBG, Control::State::HIGH_LIGHTED);
	backwardBtn->setZoomOnTouchDown(false);
	backwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::backward), Control::EventType::TOUCH_DOWN);
	backwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::backward), Control::EventType::TOUCH_UP_INSIDE);
	backwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::backward), Control::EventType::DRAG_OUTSIDE);
	backwardBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directionNormal.png"))->getContentSize());

	auto forwardBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directForNor.png"));
	auto forwardSelBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directForSel.png"));
	auto forwardBtn = ControlButton::create(forwardBG);
	forwardBtn->setBackgroundSpriteForState(forwardSelBG, Control::State::HIGH_LIGHTED);
	forwardBtn->setZoomOnTouchDown(false);
	forwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::forward), Control::EventType::TOUCH_DOWN);
	forwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::forward), Control::EventType::TOUCH_UP_INSIDE);
	forwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::forward), Control::EventType::DRAG_OUTSIDE);
	forwardBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directForNor.png"))->getContentSize());

	puaseGameItem->setPosition(WINSIZE.width - 50, WINSIZE.height - 48);
	backwardBtn->setPosition(117, 70);
	forwardBtn->setPosition(304, 70);

	auto menuWalk = Menu::create(puaseGameItem, NULL);
	menuWalk->setPosition(Point::ZERO);
	this->addChild(backwardBtn, 1);
	this->addChild(forwardBtn, 1);
	this->addChild(menuWalk, 1);

	// 状态条
	m_pBG = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("barGround.png"));

	m_pHPBar = ProgressTimer::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("HPBar.png")));
	m_pHPBar->setType(ProgressTimer::Type::BAR);
	m_pHPBar->setMidpoint(ccp(0, 0.5));
	m_pHPBar->setBarChangeRate(ccp(1, 0));
	m_pHPBar->setPercentage(100);

	m_pMPBar = ProgressTimer::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("MPBar.png")));
	m_pMPBar->setType(ProgressTimer::Type::BAR);
	m_pMPBar->setMidpoint(ccp(0, 0.5));
	m_pMPBar->setBarChangeRate(ccp(1, 0));
	m_pMPBar->setPercentage(0);

	m_pHPBar->setPosition(240, 45);
	m_pMPBar->setPosition(226, 30);

	m_pBG->addChild(m_pHPBar);
	m_pBG->addChild(m_pMPBar);

	m_pBG->setPosition(260, WINSIZE.height - 60);

	this->addChild(m_pBG, 1);

	// 英雄
	m_pHero = Hero::create();
	m_pHero->InitHeroSprite("idle.png", 1);
	m_pHero->setPosition(100, 360);
	this->addChild(m_pHero, 3);


	MonsterOne *monster = MonsterOne::createWithMapAndHero(myMap, m_pHero);

	this->scheduleUpdate();
	return true;
}

// 拳击
void GameLayer::fistAttack(Ref* pSender, Control::EventType type)
{
	if (m_pHero->IsRunning || m_pHero->IsAttack || m_pHero->IsHurt || m_pHero->m_bIsJumping)
	{
		return;
	}
	PLAYEFFECT;
	m_pHero->AttackAnimation("fist", 0.1f, m_bDirection);
}

// 腿击
void GameLayer::footAttack(Ref* psender, Control::EventType type)
{
	if (m_pHero->IsRunning || m_pHero->IsAttack || m_pHero->IsHurt || m_pHero->m_bIsJumping)
	{
		return;
	}
	PLAYEFFECT;
	m_pHero->AttackAnimation("leg", 0.1f, m_bDirection);
}

// 
void GameLayer::jump(Ref* pSender, Control::EventType type)
{

	if (m_pHero->IsRunning || m_pHero->IsAttack || m_pHero->IsHurt || m_bJump)
	{
		return;
	}

	if (getBoolFromXML(SOUND_KEY))
	{
		aduioEngine->setEffectsVolume(getFloatFromXML(SOUNDVOL));
		aduioEngine->playEffect("Sound/Jump.wav");
	}

	m_bJump = true;
}

void GameLayer::comboAttack(Ref* pSender, Control::EventType type)
{
	if (m_pHero->IsAttack || m_pHero->m_bIsJumping == true || m_pHero->m_bCanCrazy)
	{
		return;
	}
	if (getBoolFromXML(SOUND_KEY))
	{
		aduioEngine->setEffectsVolume(getFloatFromXML(SOUNDVOL));
		aduioEngine->playEffect("Sound/combo.wav");
	}
	m_pHero->m_bCanCrazy = true;
	switch (m_iSelectGate)
	{
	case 1:
		m_pHero->AttackAnimation("combo", 0.1, m_bDirection);
		break;
	case 2:
		m_pHero->AttackAnimation("bakandao", 0.1, m_bDirection);
		break;
	case 3:
		m_pHero->AttackAnimation("gun", 0.1, m_bDirection);
		break;
	default:
		break;
	}
}



void GameLayer::gamePause(Ref* pSender)
{
	//能够直接使用pause方法暂停当前的场景,可是这样做有一个bug,就是不能够屏蔽触摸事件,所以採用截图的方法
	//Director::getInstance()->pause();

	/*截取当前场景的图片而且保存*/

	auto size = Director::getInstance()->getWinSize();
	//RenderTexture是一个纹理渲染类,我们须要把要渲染的当前场景放进去,这是初始化它的大小
	render = RenderTexture::create(size.width, size.height);
	//開始获取内容
	render->begin();
	//是用节点的visit方法增加到渲染中
	Director::getInstance()->getRunningScene()->visit();
	//结束
	render->end();
	render->retain();

	//3.0 截屏须要在截完屏的下一帧才干处理RenderTexture,这点要注意
	auto _schedule = this->getScheduler();
	auto replaceScene = [&](float tm)
	{
		//最后切换场景
		Director::getInstance()->pushScene(PauseLayer::createScene(render));
	};
	_schedule->schedule(replaceScene, this, 0.0f, 0, 0.0f, false, "screenshot");
}


void GameLayer::backward(Ref* pSender, Control::EventType type)
{
	if (m_pHero->IsAttack && m_pHero->m_bIsJumping == true)
	{
		return;
	}
	switch (type)
	{
	case cocos2d::extension::Control::EventType::TOUCH_DOWN:
		m_bRun = true;
		m_bDirection = true;
		break;
	case cocos2d::extension::Control::EventType::DRAG_INSIDE:
		break;
	case cocos2d::extension::Control::EventType::DRAG_OUTSIDE:
		m_bRun = false;
		m_pHero->StopAnimation();
		break;
	case cocos2d::extension::Control::EventType::DRAG_ENTER:
		break;
	case cocos2d::extension::Control::EventType::DRAG_EXIT:
		break;
	case cocos2d::extension::Control::EventType::TOUCH_UP_INSIDE:
		m_bRun = false;
		m_pHero->StopAnimation();
		break;
	case cocos2d::extension::Control::EventType::TOUCH_UP_OUTSIDE:
		break;
	case cocos2d::extension::Control::EventType::TOUCH_CANCEL:
		break;
	case cocos2d::extension::Control::EventType::VALUE_CHANGED:
		break;
	default:
		break;
	}
}

void GameLayer::forward(Ref* pSender, Control::EventType type)
{
	if (m_pHero->IsAttack && m_pHero->m_bIsJumping == true)
	{
		return;
	}
	switch (type)
	{
	case cocos2d::extension::Control::EventType::TOUCH_DOWN:
		m_bRun = true;
		m_bDirection = false;
		break;
	case cocos2d::extension::Control::EventType::DRAG_INSIDE:
		break;
	case cocos2d::extension::Control::EventType::DRAG_OUTSIDE:
		m_bRun = false;
		m_pHero->StopAnimation();
		break;
	case cocos2d::extension::Control::EventType::DRAG_ENTER:
		break;
	case cocos2d::extension::Control::EventType::DRAG_EXIT:
		break;
	case cocos2d::extension::Control::EventType::TOUCH_UP_INSIDE:
		m_bRun = false;
		m_pHero->StopAnimation();
		break;
	case cocos2d::extension::Control::EventType::TOUCH_UP_OUTSIDE:
		break;
	case cocos2d::extension::Control::EventType::TOUCH_CANCEL:
		break;
	case cocos2d::extension::Control::EventType::VALUE_CHANGED:
		break;
	default:
		break;
	}
}

void GameLayer::gameOver(float delta)
{
	// 对声音的处理
	if (getBoolFromXML(MUSIC_KEY))
	{
		float music = getFloatFromXML(MUSICVOL)*100.0f;
		aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));
		if (SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
		{
			aduioEngine->pauseBackgroundMusic();
			aduioEngine->playBackgroundMusic("Sound/failure.wav", true);
		}
		else
			aduioEngine->playBackgroundMusic("Sound/failure.wav", true);
	}
	else
		aduioEngine->pauseBackgroundMusic();
	// 弹出游戏失败的界面
	auto bgSprite = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("heiping.png"));
	bgSprite->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);
	this->addChild(bgSprite, 5);
	auto bgTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("bgTitle.png"));
	bgTitle->setPosition(WINSIZE.width / 2 + 23, WINSIZE.height / 2 + 17);
	auto faliureTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("faliure.png"));
	faliureTitle->setPosition(WINSIZE.width / 2, WINSIZE.height / 2 + 227);
	auto energyTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tili.png"));
	energyTitle->setPosition(WINSIZE.width / 2, WINSIZE.height / 2 - 23);
	auto tips = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tipsNext.png"));
	tips->setPosition(WINSIZE.width / 2, WINSIZE.height / 2 - 227);

	auto m_pEnergyLabel = LabelTTF::create("-  1", "", 45);
	m_pEnergyLabel->setColor(ccc3(0, 255, 255));
	m_pEnergyLabel->setPosition(300, 60);

	bgSprite->addChild(bgTitle);
	bgSprite->addChild(faliureTitle);
	bgSprite->addChild(energyTitle);
	bgSprite->addChild(tips);

	// 获取事件分发器
	auto dispatcher = Director::getInstance()->getEventDispatcher();
	// 触摸监听器
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [](Touch* touch, Event* event){return true; };
	listener->onTouchMoved = [](Touch* touch, Event* event){};
	listener->onTouchEnded = [](Touch* touch, Event* event){
		Director::getInstance()->replaceScene(GateMapLayer::createScene());
	};
	listener->setSwallowTouches(true);
	dispatcher->addEventListenerWithSceneGraphPriority(listener, bgSprite);
}

void GameLayer::gameVictory(float delta)
{
	// 对声音的处理
	if (getBoolFromXML(MUSIC_KEY))
	{
		float music = getFloatFromXML(MUSICVOL)*100.0f;
		aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));
		if (SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
		{
			aduioEngine->pauseBackgroundMusic();
			aduioEngine->playBackgroundMusic("Sound/victory.wav", true);
		}
		else
			aduioEngine->playBackgroundMusic("Sound/victory.wav", true);
	}
	else
		aduioEngine->pauseBackgroundMusic();

	if (m_iSelectGate == 1)
	{
		setBoolToXML(GATEONE, true);
	}
	else if (m_iSelectGate == 2)
	{
		setBoolToXML(GATETWO, true);
	}
	else
		setBoolToXML(GATETHREE, true);

	// 弹出游戏胜利的界面
	auto bgSprite = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("heiping.png"));
	bgSprite->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);
	this->addChild(bgSprite, 5);
	auto bgTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("bgTitle.png"));
	bgTitle->setPosition(WINSIZE.width / 2 + 23, WINSIZE.height / 2 + 17);
	auto victoryTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("victory.png"));
	victoryTitle->setPosition(WINSIZE.width / 2, WINSIZE.height / 2 + 227);
	auto energyTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tili.png"));
	energyTitle->setPosition(WINSIZE.width / 2 + 116, WINSIZE.height / 2 - 23);
	auto moneyTitle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jinbi.png"));
	moneyTitle->setPosition(WINSIZE.width / 2 - 275, WINSIZE.height / 2 - 27);
	auto tips = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tipsNext.png"));
	tips->setPosition(WINSIZE.width / 2, WINSIZE.height / 2 - 227);
	bgSprite->addChild(bgTitle);
	bgSprite->addChild(victoryTitle);
	bgSprite->addChild(energyTitle);
	bgSprite->addChild(moneyTitle);
	bgSprite->addChild(tips);

	// 获取事件分发器
	auto dispatcher = Director::getInstance()->getEventDispatcher();
	// 触摸监听器
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [](Touch* touch, Event* event){return true; };
	listener->onTouchMoved = [](Touch* touch, Event* event){};
	listener->onTouchEnded = [](Touch* touch, Event* event){
		Director::getInstance()->replaceScene(GateMapLayer::createScene());
	};
	listener->setSwallowTouches(true);
	dispatcher->addEventListenerWithSceneGraphPriority(listener, bgSprite);
}

bool GameLayer::isAttackMonster(Hero * hero, Monster* monster)
{
	bool hero_dire = hero->HeroDirecton;
	bool monster_dire = monster->MonsterDirecton;
	float hero_x = hero->getPositionX();
	float monster_x = monster->getPositionX() + myMap->getPositionX();
	if (hero_dire)
	{
		if (monster_x <= hero_x)
		{
			return true;
		}
	}
	else
	{
		if (monster_x >= hero_x)
		{
			return true;
		}
	}

	return false;
}

float GameLayer::getVelocity()
{
	velocity = velocity - 0.3f;
	return velocity;
}

void GameLayer::update(float delta)
{
	// 人物跳起
	if (m_bJump)
	{
		getVelocity();

		if (velocity >= 0.1)  // 速度不为0
		{
			m_pHero->JumpUpAnimation("jumpup", 0.1f, m_bDirection);
			if (m_bDirection == false)
			{
				if (m_pHero->getPositionX() <= WINSIZE.width - 8)//不让精灵超出右边,8能够改成你喜欢的
				{
					if (!m_pHero->JudgePosition(WINSIZE) || myMap->JudgeMap(m_pHero)) //精灵没到达窗体中间位置或者地图已经移动到边缘了,精灵才干够移动。否则仅仅播放动画
						m_pHero->setPosition(ccp(m_pHero->getPosition().x + m_pHero->m_iSpeed, m_pHero->getPosition().y + velocity)); //向右走
					else
					{
						m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
					}
					//以下是移动地图
					myMap->MoveMap(m_pHero);
				}
				else
					m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
			}
			else
			{
				if (m_pHero->getPositionX() >= 8)//不让精灵超出左边,8能够改成你喜欢的
				{
					if (!m_pHero->JudgePosition(WINSIZE) || myMap->JudgeMap(m_pHero))//精灵没到达窗体中间位置或者地图已经移动到边缘了,精灵才干够移动,否则仅仅播放动画
						m_pHero->setPosition(ccp(m_pHero->getPosition().x - m_pHero->m_iSpeed, m_pHero->getPosition().y + velocity)); //向左走
					else
					{
						m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
					}
					//以下是移动地图
					myMap->MoveMap(m_pHero);
				}
				else
					m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
			}

		}
		else
		{
			m_pHero->JumpDownAnimation("jumpdown", 0.1f, m_bDirection);
			if (m_bDirection == false)
			{
				if (m_pHero->getPositionX() <= WINSIZE.width - 8)//不让精灵超出右边,8能够改成你喜欢的
				{
					if (!m_pHero->JudgePosition(WINSIZE) || myMap->JudgeMap(m_pHero))//精灵没到达窗体中间位置或者地图已经移动到边缘了,精灵才干够移动。否则仅仅播放动画
						m_pHero->setPosition(ccp(m_pHero->getPosition().x + m_pHero->m_iSpeed, m_pHero->getPosition().y + velocity)); //向右走
					else
					{
						m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
					}
					//以下是移动地图
					myMap->MoveMap(m_pHero);
				}
				else
					m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
			}
			else
			{
				if (m_pHero->getPositionX() >= 8)//不让精灵超出左边,8能够改成你喜欢的
				{
					if (!m_pHero->JudgePosition(WINSIZE) || myMap->JudgeMap(m_pHero))//精灵没到达窗体中间位置或者地图已经移动到边缘了。精灵才干够移动。否则仅仅播放动画
						m_pHero->setPosition(ccp(m_pHero->getPosition().x - m_pHero->m_iSpeed, m_pHero->getPosition().y + velocity)); //向左走
					else
					{
						m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
					}
					//以下是移动地图
					myMap->MoveMap(m_pHero);
				}
				else
					m_pHero->setPosition(ccp(m_pHero->getPosition().x, m_pHero->getPosition().y + velocity)); //向左走
			}
		}

		if (m_pHero->getPositionY() <= 359)
		{
			m_pHero->JumpEnd();
			m_pHero->setPosition(ccp(m_pHero->getPosition().x + 3, 360));
			velocity = 10.0f;
			m_bJump = false;
		}
	}

	// 人物移动
	if (m_bRun && m_bDirection == false && m_pHero->IsHurt == false && m_pHero->IsAttack == false && m_pHero->m_bIsJumping == false)
	{
		m_pHero->SetAnimation("run", 0.07f, m_bDirection);
		if (m_pHero->getPositionX() <= WINSIZE.width - 8)//不让精灵超出右边,8能够改成你喜欢的
		{
			if (!m_pHero->JudgePosition(WINSIZE) || myMap->JudgeMap(m_pHero))//精灵没到达窗体中间位置或者地图已经移动到边缘了。精灵才干够移动,否则仅仅播放动画
				m_pHero->setPosition(ccp(m_pHero->getPosition().x + m_pHero->m_iSpeed, m_pHero->getPosition().y)); //向右走
			//以下是移动地图
			myMap->MoveMap(m_pHero);
		}
	}
	else if (m_bRun && m_bDirection == true && m_pHero->IsHurt == false && m_pHero->m_bIsJumping == false)
	{
		m_pHero->SetAnimation("run", 0.07f, m_bDirection);
		if (m_pHero->getPositionX() >= 8)//不让精灵超出左边,8能够改成你喜欢的
		{
			if (!m_pHero->JudgePosition(WINSIZE) || myMap->JudgeMap(m_pHero))//精灵没到达窗体中间位置或者地图已经移动到边缘了,精灵才干够移动,否则仅仅播放动画
				m_pHero->setPosition(ccp(m_pHero->getPosition().x - m_pHero->m_iSpeed, m_pHero->getPosition().y)); //向右走
			//以下是移动地图
			myMap->MoveMap(m_pHero);
		}
	}

	// 主角和怪物攻击碰撞检測
	if (m_pHero->IsAttack)
	{
		for (auto monster : monsterShowList)
		{
			// 怪物没死
			if (monster->Isdead == false && isAttackMonster(m_pHero, monster) && m_pHero->m_bIsJumping == false)
			{
				// 得到两点x的距离, 记得怪物的坐标要加上地图的
				float x = m_pHero->getPositionX() - (monster->getPositionX() + myMap->getPositionX());

				//先计算怪物和英雄的距离
				auto dis = fabs(x);
				if (dis <= 150)
				{
					if (monster->m_iType == 1)
					{
						monster->HurtAnimation("monsterHurt", monster->MonsterDirecton, 0.2f, 1);
					}
					else if (monster->m_iType == 2)
					{
						monster->HurtAnimation("lionHurt", monster->MonsterDirecton, 0.2f, 1);
					}
					else
					{
						monster->HurtAnimation("stoneHurt", monster->MonsterDirecton, 0.2f, 1);
					}
				}
				// 				if (this->isRectCollision(CCRectMake(m_pHero->getPositionX(), m_pHero->getPositionY(), m_pHero->GetSprite()->getContentSize().width-30, m_pHero->GetSprite()->getContentSize().height-20), 
				// 					CCRectMake(monster->getPositionX(), monster->getPositionY(), monster->GetSprite()->getContentSize().width - 30, monster->GetSprite()->getContentSize().height - 20)))
				// 				{
				// 					monster->HurtAnimation("monsterHurt", monster->MonsterDirecton, 0.2f, 1);
				// 				}
			}
		}
	}

	for (auto monster : monsterShowList)
	{
		if (!monster->Isdead)
		{
			if (monster->IsAttack && m_pHero->IsDead == false && m_pHero->m_bIsJumping == false)
			{
				// 得到两点x的距离, 记得怪物的坐标要加上地图的
				float x = m_pHero->getPositionX() - (monster->getPositionX() + myMap->getPositionX());

				//先计算怪物和英雄的距离
				auto dis = fabs(x);
				if (dis <= 130)
				{
					m_pHero->HurtByMonsterAnimation("hurt", 0.2f, m_bDirection);
					m_pHPBar->setPercentage(m_pHero->percentage);
				}
			}
		}
	}

	m_pMPBar->setPercentage(m_pHero->m_iCurrentMp);
	if (m_pMPBar->getPercentage() >= 100)
	{
		m_pComboPic->setVisible(true);
	}
	else
	{
		m_pComboPic->setVisible(false);
	}

	// 主角和怪物攻击碰撞检測
	if (m_pHero->IsAttack && m_pHero->m_bCanCrazy)
	{
		for (auto monster : monsterShowList)
		{
			// 怪物没死
			if (monster->Isdead == false && isAttackMonster(m_pHero, monster) && m_pHero->m_bIsJumping == false)
			{
				// 得到两点x的距离, 记得怪物的坐标要加上地图的
				float x = m_pHero->getPositionX() - (monster->getPositionX() + myMap->getPositionX());

				//先计算怪物和英雄的距离
				auto dis = fabs(x);
				if (dis <= 350)
				{
					monster->HurtAnimation("monsterHurt", monster->MonsterDirecton, 0.2f, 1);
				}
				// 				if (this->isRectCollision(CCRectMake(m_pHero->getPositionX(), m_pHero->getPositionY(), m_pHero->GetSprite()->getContentSize().width-30, m_pHero->GetSprite()->getContentSize().height-20), 
				// 					CCRectMake(monster->getPositionX(), monster->getPositionY(), monster->GetSprite()->getContentSize().width - 30, monster->GetSprite()->getContentSize().height - 20)))
				// 				{
				// 					monster->HurtAnimation("monsterHurt", monster->MonsterDirecton, 0.2f, 1);
				// 				}
			}
		}
	}

	// 游戏结束判定
	if (m_pHero->IsDead)
	{
		// 游戏结束
		this->scheduleOnce(schedule_selector(GameLayer::gameOver), 1.0f);
		this->unscheduleUpdate();
	}
	// 怪物全死
	if (m_bFlag3 == false)
	{
		bool noMonster = true;
		for (auto monster : monsterShowList)
		{
			if (!monster->Isdead)
			{
				noMonster = false;
			}
		}
		if (noMonster)
		{
			this->scheduleOnce(schedule_selector(GameLayer::gameVictory), 2.0f);
			this->unscheduleUpdate();
		}
	}
}

关于暂停场景的实现例如以下,由于暂停要实现一个动态的开关效果,并且背景是游戏暂停的场景。所以做了一个截图,传递给这个场景,代码实现例如以下:

/*!
 * \file PauseLayer.h
 *
 * \author SuooL
 * \date 六月 2015
 *
 * 暂停界面
 */

#ifndef __PauseLayer__H__
#define __PauseLayer__H__
#include "cocos2d.h"
#include "extensions/cocos-ext.h"

USING_NS_CC;
using namespace cocos2d::extension;

class PauseLayer : public Layer {
public:
	static Scene* createScene(RenderTexture* rt);
	virtual bool init();
	CREATE_FUNC(PauseLayer);

	Sprite* spriteOn;
	Sprite* spriteDown;

	void musicSet(Ref* pSender);

private:

};

#endif

实现文件为:

/*!
* \file PauseLayer.cpp
* \date 2015/04/08 15:30
*
* \author SuooL
* Contact: 1020935219@qq.com
*
* \brief 暂停界面
*
* \version 1.0
*
* TODO: long description
*
* \note
*/
#include "PauseLayer.h"
#include "GlobalDefine.h"
#include "GlobalData.h"
#include "GameLayer.h"
#include "StartLayer.h"
#include "cocos2d.h"
#include "extensions/cocos-ext.h"

USING_NS_CC;
using namespace cocos2d::extension;

Scene* PauseLayer::createScene(RenderTexture* rt)
{
	Scene* scene = Scene::create();
	PauseLayer* layer = PauseLayer::create();

	auto sprite = Sprite::createWithTexture(rt->getSprite()->getTexture());
	sprite->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);
	sprite->setFlippedY(true);
//	sprite->setColor(cocos2d::ccGRAY);
	scene->addChild(sprite, 0);

	scene->addChild(layer);

	return scene;
}

bool PauseLayer::init()
{
	if (!Layer::init())
	{
		return false;
	}

	auto size = Director::getInstance()->getWinSize();

	// 背景黑色的图片
	spriteOn = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("pauseBG1.png"));
	spriteDown = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("pauseBG2.png"));
	spriteOn->setPosition(size.width / 2, size.height + spriteOn->getContentSize().height / 2);
	spriteDown->setPosition(size.width / 2, - (spriteDown->getContentSize().height / 2));
	this->addChild(spriteOn); 
	this->addChild(spriteDown);

	/*
	继续游戏button:  X:630.5 Y349.0
	声音按键:X:190.0  Y294.0
	重置键button:X346.0 Y:294.0
	返回关卡界面键button:X890.0 Y:294.0
	下一关键button:X1053.0 Y:294.0
	*/
	// 继续游戏button
	auto resumeItem = MenuItemSprite::create(
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("playNormal.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("playSelected.png")),
		[&](Ref * ref){
		PLAYEFFECT;
		//弹出保存的场景
		auto moveOn = MoveBy::create(0.5f, Point(0, (spriteOn->getContentSize().height)));
		auto moveDown = MoveBy::create(0.5f, Point(0, -spriteDown->getContentSize().height));
		CallFunc* replace = CallFunc::create([](){Director::getInstance()->popScene();});
		Action* resume = Sequence::create(moveOn, replace, NULL);
		spriteDown->runAction(moveDown);
		spriteOn->runAction(resume);
		});
	resumeItem->setPosition(spriteOn->getContentSize().width / 2-5, 110.0f);

	// 返回游戏主界面
	auto startItem = MenuItemSprite::create(
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("backNormal.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("backSelected.png")),
		[](Ref * ref){
		PLAYEFFECT;
		//弹出保存的场景
		Director::getInstance()->replaceScene(StartLayer::createScene());});
	startItem->setPosition(890.0f, 180.0f);

	// 又一次開始游戏
	auto againItem = MenuItemSprite::create(
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("againNormal.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("againSelected.png")),
		[](Ref * ref){
		PLAYEFFECT;
		//弹出保存的场景
		Director::getInstance()->replaceScene(GameLayer::createScene());});
	againItem->setPosition(346.0f, 180.0f);
	// 下一关
	auto nextItem = MenuItemSprite::create(
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("nextNormal.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("nextSelected.png")),
		[](Ref * ref){
		PLAYEFFECT;
		//弹出保存的场景
		if (m_iSelectGate++ < 3)
		{
			Director::getInstance()->replaceScene(GameLayer::createScene());
		}
		});
	nextItem->setPosition(1053.0f, 180.0f);

	// 声音设置button
	auto musicOn = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("musicOn.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("musicOff.png")));
	auto musicOff = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("musicOff.png")),
		Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("musicSelected.png")));
	auto musciToggle = MenuItemToggle::createWithTarget(this, menu_selector(PauseLayer::musicSet), musicOn, musicOff, NULL);
	musciToggle->setPosition(190.0f, 180.0f);

	auto menu = Menu::create(resumeItem, startItem, againItem, nextItem,musciToggle, NULL);
	menu->setPosition(Point::ZERO);
	spriteOn->addChild(menu);

	auto moveDown = MoveBy::create(0.6f, Point(0, - (spriteOn->getContentSize().height)));
	auto moveUp = MoveBy::create(0.6f, Point(0, spriteDown->getContentSize().height));
	spriteOn->runAction(moveDown);
	spriteDown->runAction(moveUp);

}

void PauseLayer::musicSet(Ref* pSender)
{
	PLAYEFFECT;
	auto musicTemp = (MenuItemToggle*)pSender;
	if (getBoolFromXML(SOUND_KEY))
	{
		aduioEngine->setEffectsVolume(getFloatFromXML(SOUNDVOL));
		aduioEngine->playEffect("");
	}
	if (musicTemp->getSelectedIndex() == 1)
	{
		SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
	}
	else
	{
		aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));
		SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
	}
}

代码的凝视已经很具体了。

假设您有不明确的地方能够留言或者邮箱我:1020935219@qq.com

整个project的源代码已经开源,地址是:https://github.com/SuooL/KungfuBoy

下一课将会说明下打包APK和项目打包过程及打包后会出现的一些问题及其解决办法。









【Cocos游戏实战】功夫小子第七课之游戏主功能场景逻辑功能和暂停功能场景的分析和实现