cocos2d-x 委托模式的巧妙运用——附源码(二)

转载请注明出处:http://blog.csdn.net/hust_superman/article/details/38292265,谢谢。

继上一篇将了委托类的具体实现后,这篇来将一下如何在游戏中使用实现的委托类。也就是如何在游戏中来调用委托类来完成一些功能。具体的应用场景和应用层会在下面介绍。

先来看一看游戏demo实现的具体图片,demo比较简单,但是资源齐全,拿到源码后可以在源码的基础上继续完善demo做出一款真正的游戏。好了,老规矩,先上图再说:

游戏中点击播放按钮后会进入游戏主界面,看到一个红色的小方块慢慢的移动到下面,最后游戏结束,结束后会有结束界面。

这个demo主要是来阐释如何运用委托类来在游戏中使主游戏逻辑更清晰。

好了,下面来看一下具体的场景和游戏的主要层。

游戏中一个GameScene 场景,在场景中添加了委托类StatusLayer层和游戏主逻辑GameLayer层,GameLayer层中调用委托类来完成游戏开始与游戏结束的逻辑。

下面来看一下GameScene.cpp的实现,在其中会将委托类注册到GameLayer层中。

#include "GameScene.h"
#include "GameLayer.h"
#include "StatusLayer.h"

USING_NS_CC;

GameScene::GameScene(){
}

GameScene::~GameScene(){
}

bool GameScene::init() {
	if(Scene::init()) {
<span style="white-space:pre">	</span>//加载图片资源到缓存,方便后面使用图片资源
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("flappyrec.plist","flappyrec.png");
	auto statusLayer = StatusLayer::create();
	this->addChild(statusLayer);
	//Add the main game layer
	auto gameLayer = GameLayer::create();
	//注册委托类到GameLayer层中
	gameLayer->setDelegator(statusLayer);
	this->addChild(gameLayer);
	return true;
	} else {
	return false;
	}
}

GameScene中比较简单,就是添加了StatusLayer层和GameLayer层,并把StatusLayer作为委托类注册到GameLayer中。

游戏中的主要的东西都在GameLayer中,下面来看下GameLayer.h的内容

#include "cocos2d.h"

USING_NS_CC;
//游戏进行的状态枚举类
typedef enum _game_status {
	GAME_STATUS_READY = 1,
	GAME_STATUS_START,
	GAME_STATUS_OVER
} GameStatus;

/**
 * 抽象的委托类,有三个虚函数,继承这个委托类的子类需要实现
 * 这三个虚函数,以便控制游戏开始,运行,结束的判断
 */
class StatusDelegate {
public:
	/**
	* When the game start, this method will be called
	*/
	virtual void onGameStart() = 0;
	/**
	* During paying, after the score changed, this method will be called
	*/
	virtual void onGamePlaying() = 0;
	/**
	* When game is over, this method will be called
	*/
	virtual void onGameEnd() = 0;
};

const int MENU_START = 10001;

class GameLayer : public Layer {
public:
	GameLayer();
	~GameLayer();
	virtual bool init();
	CREATE_FUNC(GameLayer);	//实现注册委托类的宏,delegator作为成员变量,可以调用委托类中的各个函数

	//覆写父类的onEnter函数,记得带override
	virtual void onEnter() 	//实现注册委托类的宏,delegator作为成员变量,可以调用委托类中的各个函数override;
	//实现注册委托类的宏,delegator作为成员变量,可以调用委托类中的各个函数
	CC_SYNTHESIZE(StatusDelegate*,delegator,Delegator);
private:
	void showStartButton();//显示开始按钮
	void menuStartCallback(Ref* pSender);//开始按钮回调函数
	void createSquares();//创建红色方块
	void moveFinished(Ref* pSender);//方块移动结束函数
private:
	Sprite* square;
	Size visibleSize;
	Point origin;

	GameStatus gameStatus;
};

上面代码中最重要的就是委托类宏的使用,这个GameScene中的下面的对应

//注册委托类到GameLayer层中
gameLayer->setDelegator(statusLayer);

宏的作用也就是注册到GameLayer中的具体的委托类StatusDelegate的子类StatusLayer。

下面看GameLayer.cpp的具体实现

#include "GameLayer.h"

USING_NS_CC;

GameLayer::GameLayer(){
}
GameLayer::~GameLayer() {
}

bool GameLayer::init() {
	if(!Layer::init()) {
		return false;
	}
	this->gameStatus = GAME_STATUS_READY;
	visibleSize = Director::getInstance()->getVisibleSize();
	origin = Director::getInstance()->getVisibleOrigin();
	//调用显示开始按钮
	this->showStartButton();

	return true;
}

void GameLayer::onEnter() {
	Layer::onEnter();
	//TODO
}
/**
 * 显示开始按钮,并为按钮注册回调函数
 */
void GameLayer::showStartButton() {
	Sprite* startBtn = Sprite::createWithSpriteFrameName("play.png");
	Sprite* startBtnActive = Sprite::createWithSpriteFrameName("play.png");
	startBtn->setScale(0.6f);//缩放
	startBtnActive->setScale(0.6f);//缩放
	startBtnActive->setPositionY(4);//使button向上移动4个单位
	//将上述精灵作为菜单进行添加
	auto menuStartItem = MenuItemSprite::create(startBtn,startBtnActive,NULL,
			CC_CALLBACK_1(GameLayer::menuStartCallback,this));
	auto menuStart = Menu::create(menuStartItem,NULL);
	menuStart->setPosition(Vec2(this->visibleSize.width/2, this->visibleSize.height/2));
	menuStart->setTag(MENU_START);
	this->addChild(menuStart,10);

}
/**
 * 按下开始菜单后的回调函数,主要是调用委托类中的onGameStart函数来实现游戏的开始
 * 同时移除开始按钮并创建游戏主界面中的红色小方块
 */
void GameLayer::menuStartCallback(Ref* pSender) {
	if(this->gameStatus == GAME_STATUS_OVER) {
		return ;
	}
	if(this->gameStatus == GAME_STATUS_READY) {
		log("start");
		//委托StatusLayer中的onGameStart函数来执行游戏开始逻辑
		this->delegator->onGameStart();
		this->getChildByTag(MENU_START)->runAction(FadeOut::create(0.4f));
		this->removeChildByTag(MENU_START,true);
		this->gameStatus = GAME_STATUS_START;
		this->createSquares();//创建红色小方块
	} else if(this->gameStatus  == GAME_STATUS_START) {
		//TODO
	}
}
/**
 * 创建红色小方块,并在移动5s后游戏结束
 */
void GameLayer::createSquares(){
	//添加方块精灵
	square = Sprite::createWithSpriteFrameName("whitebird.png");
	square->setPosition(Vec2(visibleSize.width/2,visibleSize.height/2));
	square->setColor(Color3B::RED);
	this->addChild(square);
	//游戏开始,5秒后游戏结束
	auto move = MoveTo::create(5.0f,Vec2(square->getPositionX(),origin.y));
	//移动结束后回调函数
	auto moveDone = CallFuncN::create(CC_CALLBACK_1(GameLayer::moveFinished,this));
	auto sequence = Sequence::createWithTwoActions(move,moveDone);
	square->runAction(sequence);
}
/**
 * 移动结束后的回调函数,也就是游戏结束,
 * 其中可以开到delegator->onGameEnd的运用
 * 这个是直接使用委托类的onGameEnd来控制游戏结束
 * 是不是瞬间感觉这个类清晰了许多,
 */
void GameLayer::moveFinished(Ref* pSender) {
	//委托StatusLayer中的onGameEnd函数执行游戏结束的逻辑
	this->delegator->onGameEnd();
	this->removeChild(square,true);
}

上面代码中需要特别注意的就是委托类调用onGameStart()函数和onGameEnd()函数,都是使用的前面介绍的那个委托类的宏

CC_SYNTHESIZE(StatusDelegate*,delegator,Delegator);

直接使用delegator来调用委托类中的函数,相当于实现了层与层之间的通信。

//委托StatusLayer中的onGameEnd函数执行游戏结束的逻辑
this->delegator->onGameEnd();

上面这段代码是这篇博客最主要想表达的,当你把具体的委托类都实现好了,那么在游戏主逻辑中你会发现原来可以这么轻松清晰高效的来调用这些东西,代码看着就清晰,而且看到的代码逻辑都是如此的简单,因为你都在委托类中具体的实现了。

好了,这篇文章和上一篇文章表达的就是委托类的具体实现,拥有好委托类,可以是游戏主逻辑更清晰,而且也可以在游戏的层与层之间进行传递参数,避免了静态变量的运用,也简化了主游戏层的代码量,不显得那么臃肿。

下面附上demo的源码,源码中有具体的资源文件,下载好源码后可以自己建立个新工程来把游戏完善,实现这个小游戏。

下载地址:点击下载

好了,这篇主要讲了委托类的具体应用,下一篇写一下游戏中的物理碰撞规则的应用。

cocos2d-x 委托模式的巧妙运用——附源码(二)

时间: 2024-10-23 16:38:47

cocos2d-x 委托模式的巧妙运用——附源码(二)的相关文章

cocos2d-x 委托模式的巧妙运用——附源码(一)

先来说一下委托模式是什么,下面的内容摘要自维基百科: 委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理.委托模式是一项基本技巧,许多其他的模式,如状态模式.策略模式.访问者模式本质上是在更特殊的场合采用了委托模式.委托模式使得我们可以用聚合来替代继承. 简单的Java例子 在此例中,类模拟打印机Printer拥有针式打印机RealPrinter的实例,Printer拥有的方法print()将处理转交给RealPrint

Java设计模式-代理模式之动态代理(附源码分析)

Java设计模式-代理模式之动态代理(附源码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象.上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个.还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实习该方法,不符合设计模式原则. 动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类.每个代理类的对象都会关联一个表示内部处理

C#版无人驾驶汽车(附源码)

一,简单问题复杂化: 100公里/1小时的速度,在日常生活中是比较常见的速度,把它转换为其它单位: 100公里/1小时 ≈ 28米/1秒 100公里/1小时 ≈ 2800厘米/秒 如果想要无人驾驶汽车达到厘米级的位移监测.探测器扫描路况时,每秒上传2800次数据给PC机.若一辆汽车有10个探测器,就意味着每秒的并发量为2.8W次/秒. 2.8W次/秒的并发量,在网站上肯定会采用分布式,缓存,读写分离,集群技术,关键还有这个数据的存储,到底用二维数据库,还是用NOSQL.这些问题是不是让你很头痛?

Android学习笔记(十四)——在运行时添加碎片(附源码)

在运行时添加碎片 点击获取源码 将UI分割为多个可配置的部分是碎片的优势之一,但其真正强大之处在于可在运行时动态地把它们添加到活动中. 1.使用上一篇创建的Fragments项目,在main.xml文件中注释掉两个<fragment>元素: 2.在FragmentActivity.java中添加下面的代码: FragmentManager fragmentManager = getSupportFragmentManager();//向活动添加碎片 FragmentTransaction fr

Android学习笔记(十五)——碎片的生命周期(附源码)

碎片的生命周期 点击下载源码 与活动类似,碎片具有自己的生命周期.理解了碎片的生命周期后,我们可以在碎片被销毁时正确地保存其实例,在碎片被重建时将其还原到前一个状态. 1.使用上一篇的项目Fragments,在Fragment1.java文件中添加如下代码: package net.zenail.Fragments; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragm

ANDROID自定义视图——仿瀑布布局(附源码)

简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3.绘制--onDraw():如何绘制这个View. 第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 第一步的测量,可以参考:(ANDROID自定义视图--onMeasure,MeasureSpec源码 流程 思路详解) 第二步的布局,可以参考:(AN

Android应用经典主界面框架之一:仿QQ (使用Fragment, 附源码)

最近反复研究日常经典必用的几个android app,从主界面带来的交互方式入手进行分析,我将其大致分为三类.今天记录第一种方式,即主界面下面有几个tab页,最上端是标题栏,tab页和tab页之间不是通过滑动切换的,而是通过点击切换tab页.早期这种架构一直是使用tabhost+activitygroup来使用,随着fragment的出现及google官方也大力推荐使用fragment,后者大有代替前者之势.本文也使用fragment进行搭建,标题中的"经典"指这种交互经典,非本文的代

C#版的无人驾驶汽车(附源码)

一,简单问题复杂化: 100公里/1小时的速度,在日常生活中是比较常见的速度,把它转换为其它单位: 100公里/1小时 ≈ 28米/1秒 100公里/1小时 ≈ 2800厘米/秒 如果想要无人驾驶汽车达到厘米级的位移监测.探测器扫描路况时,每秒上传2800次数据给PC机.若一辆汽车有10个探测器,就意味着每秒的并发量为2.8W次/秒. 2.8W次/秒的并发量,在网站上肯定会采用分布式,缓存,读写分离,集群技术,关键还有这个数据的存储,到底用二维数据库,还是用NOSQL.这些问题是不是让你很头痛?

java多线程核心技术梳理(附源码)

java多线程核心技术梳理(附源码) java多线程核心技术梳理附源码 写在前面 java多线程 对象及变量的并发访问 线程间通信 Lock的使用 定时器 单例模式与多线程 拾遗补增 参考资料 本文对多线程基础知识进行梳理,主要包括多线程的基本使用,对象及变量的并发访问,线程间通信,lock的使用,定时器,单例模式,以及线程状态与线程组. 写在前面 花了一周时间阅读<java多线程编程核心技术>(高洪岩 著),本文算是此书的整理归纳,书中几乎所有示例,我都亲手敲了一遍,并上传到了我的githu