先来说一下托付模式是什么。以下的内容摘要自维基百科:

托付模式是软件设计模式中的一项基本技巧。在托付模式中,有两个对象參与处理同一个请求。接受请求的对象将请求托付给还有一个对象来处理。托付模式是一项基本技巧。更多的模式,如状态模式、策略模式、訪问者模式本质上是在更特殊的场合採用了托付模式。托付模式使得我们能够用聚合来替代继承。

简单的Java样例

在此例中。类模拟打印机Printer拥有针式打印机RealPrinter的实例,Printer拥有的方法print()将处理转交给RealPrinter的print()方法。

 class RealPrinter { // the "delegate"
void print() {
System.out.print("something");
}
} class Printer { // the "delegator"
RealPrinter p = new RealPrinter(); // create the delegate
void print() {
p.print(); // delegation
}
} public class Main {
// to the outside world it looks like Printer actually prints.
public static void main(String[] args) {
Printer printer = new Printer();
printer.print();
}
}

复杂的Java样例

通过使用接口,托付能够做到类型安全而且更加灵活。在这个样例中。类C能够托付类A或者类B。类C拥有方法使自己能够在类A或者类B间选择。由于类A或者类B必须实现接口I规定的方法。所以在这里托付是类型安全的。这个样例显示出托付的缺点就是须要很多其它的代码。

interface I {
void f();
void g();
} class A implements I {
public void f() { System.out.println("A: doing f()"); }
public void g() { System.out.println("A: doing g()"); }
} class B implements I {
public void f() { System.out.println("B: doing f()"); }
public void g() { System.out.println("B: doing g()"); }
} class C implements I {
// delegation
I i = new A(); public void f() { i.f(); }
public void g() { i.g(); } // normal attributes
public void toA() { i = new A(); }
public void toB() { i = new B(); }
} public class Main {
public static void main(String[] args) {
C c = new C();
c.f(); // output: A: doing f()
c.g(); // output: A: doing g()
c.toB();
c.f(); // output: B: doing f()
c.g(); // output: B: doing g()
}
}

介绍了托付模式。根本上讲就是我是一个对象,我须要做的事我托付还有一个对象来做,这样就降低了我这个对象所要做的事情,我仅仅需把须要的东西都托付给还有一个对象,它能自行处理我的需求。这样一来我这个对象所须要实现的代码就降低了。并且托付的对象能够反复利用,不光我这个对象。凡是有这个需求的都能够托付这个对象来处理相同的事,降低了开发中的反复代码。

对于cocos2d-x中的托付设计模式,在这里我不讲GUI方面的托付模式。比如Menu的响应事件。Button的响应事件,我主要将一下在游戏控制中。推断游戏開始、执行、结束时用到的托付模式。这样把这三个逻辑都交给一个托付类来实现。思路较清晰,并且能够反复利用,降低开发周期。

游戏中的主要逻辑都集中在GameLayer层中,在GameScene场景中加入所须要的Layer层,然后在各个Layer层中实现对应的逻辑。

对于大多数的开发中,我都是在一个GameLayer层中完毕游戏中的全部逻辑推断。后来感觉这样的方法使GameLayer层的代码太臃肿,太不清晰,自己看着都想重构一下代码。

接下来以一个小demo来介绍下cocos2d-x中的托付模式的巧妙运用,使游戏开发更清晰,更快捷。

先来看一下托付类。游戏中的開始、执行、结束的逻辑推断都在这个托付类中实现。

以下是托付类的实现代码,StatusLayer.h的详细代码

#include "cocos2d.h"
#include "GameLayer.h" USING_NS_CC; const int SPRITE_TITLE_TAG = 1000;
/**
* StatusDelegate 是托付类的父类。在GameLayer中实现三个虚函数
* 具体代码例如以下
* class StatusDelegate {
* public:
* virtual void onGameStart() = 0;
* virtual void onGamePlaying() = 0;
* virtual void onGameEnd() = 0;
* };
*/
class StatusLayer : public Layer ,public StatusDelegate{
public:
StatusLayer(void);
~StatusLayer(void); virtual bool init();
CREATE_FUNC(StatusLayer); //实现父类StatusDelegate的三个虚函数
void onGameStart();//游戏開始逻辑推断函数
void onGamePlaying();//游戏执行逻辑推断函数
void onGameEnd();//游戏结束逻辑推断函数 private: void moveFinished(Ref* pSender);//title精灵移动结束后回调此函数
void showRestartMenu(Ref* pSender);//显示又一次開始button
void showOverSprite();//显示GameOver精灵函数
void menuRestartCallback(cocos2d::Ref* pSender);//点击開始button后回调此函数
void menuShareCallback(cocos2d::Ref* pSender);//分享button回调button private:
Size visibleSize;
Point origin;
Sprite* gameOverSprite;
};

代码中不做太多解释。在该凝视的地方都有具体凝视。

以下来看托付类StatusLayer的详细实现。

Statuslayer.cpp

/*
* StatusLayer.cpp
*
* Created on: 2014年7月29日
* Author: tubuntu
*/
#include "StatusLayer.h"
#include "GameScene.h" USING_NS_CC; StatusLayer::StatusLayer() {
} StatusLayer::~StatusLayer() {
} bool StatusLayer::init() {
if(!Layer::init()) {
return false;
}
//获取屏幕大小和原点坐标
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
//加入游戏中的背景
Sprite* background = Sprite::createWithSpriteFrameName("flappyrec_welcome_bg.png");
background->setPosition(Point::ZERO);
background->setAnchorPoint(Point::ZERO);
this->addChild(background); //加入游戏中的标题
Sprite* title = Sprite::createWithSpriteFrameName("flappyrec_welcome_title.png");
title->setPosition(Vec2(0-title->getContentSize().width,visibleSize.height*4/5));
title->setTag(SPRITE_TITLE_TAG);//设置tag值
this->addChild(title); auto move = MoveTo::create(1.0f,Vec2(visibleSize.width/2-50,title->getPositionY()));
//移动结束后回调此函数
auto moveDone = CallFuncN::create(CC_CALLBACK_1(StatusLayer::moveFinished,this));
//先加速后减速的动画特效
EaseExponentialOut* sineIn = EaseExponentialOut::create(move);
//序列动画
auto sequence = Sequence::createWithTwoActions(sineIn,moveDone);
title->runAction(sequence); return true;
} /**
* title移动结束后调用此函数
*/
void StatusLayer::moveFinished(Ref* pSender) {
//TODO
} /**
* 托付类的方法。此方法会在GameLayer中被调用,用于游戏的開始
*/
void StatusLayer::onGameStart(){
this->getChildByTag(SPRITE_TITLE_TAG)->runAction(FadeOut::create(0.4f));
} /**
* 托付类的方法,此方法会在GameLayer中被调用,用于游戏的执行中的逻辑实现
*/
void StatusLayer::onGamePlaying(){
//TODO
} /**
* 托付类的方法,此方法会在GameLayer中被调用,用于游戏的结束逻辑的实现
*/
void StatusLayer::onGameEnd(){
this->showOverSprite(); }
/**
* gameOverSprite精灵的加入,并加入从下到上出现的动作。
* 动作结束后调用显示button的函数
*/
void StatusLayer::showOverSprite() { gameOverSprite = Sprite::createWithSpriteFrameName("flappyrec_welcome_rec.png");
gameOverSprite->setPosition(Vec2(visibleSize.width / 2,0-gameOverSprite->getContentSize().height));
gameOverSprite->setScale(0.5f);
this->addChild(gameOverSprite); auto move = MoveTo::create(0.8f ,Vec2(visibleSize.width/2,visibleSize.height/2 + 60));
auto moveDone = CallFuncN::create(CC_CALLBACK_1(StatusLayer::showRestartMenu,this));
EaseExponentialOut* sineIn = EaseExponentialOut::create(move);
Sequence* sequence = Sequence::createWithTwoActions(sineIn,moveDone); gameOverSprite->runAction(sequence);
}
/**
* button显示的回调函数。显示開始和分享button
* 并为button设置回调函数
*/
void StatusLayer::showRestartMenu(Ref* pSender) { Node* tmpNode = Node::create();//两个button的父节点 Sprite* restartBtn = Sprite::createWithSpriteFrameName("play.png");
Sprite* restartBtnActive = Sprite::createWithSpriteFrameName("play.png");
restartBtn->setScale(0.6f);//缩放
restartBtnActive->setScale(0.6f);//缩放
restartBtnActive->setPositionY(-4);//先下移动四个单位 auto menuRestartItem = MenuItemSprite::create(restartBtn,restartBtnActive,NULL,
CC_CALLBACK_1(StatusLayer::menuRestartCallback,this));//设置button回调函数
auto menuRestart = Menu::create(menuRestartItem,NULL);
menuRestart->setPosition(Vec2(this->visibleSize.width/2 - 35,
this->visibleSize.height/2 - gameOverSprite->getContentSize().height/3 + 60.0f));
tmpNode->addChild(menuRestart);//将button加入到父节点中 Sprite* shareBtn = Sprite::createWithSpriteFrameName("share.png");
Sprite* shareBtnActive = Sprite::createWithSpriteFrameName("share.png");
shareBtn->setScale(0.6f);
shareBtnActive->setScale(0.6f);
shareBtnActive->setPositionY(-4); auto menuShareItem = MenuItemSprite::create(shareBtn,shareBtnActive,NULL,
CC_CALLBACK_1(StatusLayer::menuShareCallback,this));//分享button的会点函数
auto menuShare = Menu::create(menuShareItem,NULL);
menuShare->setPosition(Point(this->visibleSize.width/2 + 65,
this->visibleSize.height/2 - gameOverSprite->getContentSize().height/3 + 60.0f));
tmpNode->addChild(menuShare); this->addChild(tmpNode);//加入父节点
auto fadeIn = FadeIn::create(0.1f);//0.1s后显示出现
tmpNode->runAction(fadeIn);//父节点执行动作
} /**
* 又一次開始button的回调函数,再次開始游戏
*/
void StatusLayer::menuRestartCallback(cocos2d::Ref* pSender){
auto scene = GameScene::create();
TransitionScene *transition = TransitionFade::create(1, scene);
Director::getInstance()->replaceScene(transition);
}
/**
* 分享button的回调函数
*/
void StatusLayer::menuShareCallback(cocos2d::Ref* pSender){
//TODO
}

上面的函数都做了具体的凝视,后面会给出具体的源代码。

托付类中的实现主要是实现了父类StatusDelegate类中的三个虚函数onGameStart(),onGamePlaying(),onGameEnd()。这三个函数不必在GameLayer中实现,能够在GameLayer中调用托付类中的这三个函数。来实现对应的逻辑推断,也起到了GameLayer层和StatusLayer层通信的目的。

好了,这篇介绍了详细的托付类的实现,下一篇介绍这个托付类的详细使用。







cocos2d-x 托付模式的巧妙运用——附源代码(一)的更多相关文章

  1. cocos2d-x 托付模式的巧妙运用——附源代码(二)

    转载请注明出处:http://blog.csdn.net/hust_superman/article/details/38292265,谢谢. 继上一篇将了托付类的详细实现后.这篇来将一下怎样在游戏中 ...

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

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  3. android classloader双亲托付模式

    概述 ClassLoader的双亲托付模式:classloader 按级别分为三个级别:最上级 : bootstrap classLoader(根类载入器) : 中间级:extension class ...

  4. android深入之设计模式(一)托付模式

    (一)托付模式简单介绍 托付模式是主要的设计模式之中的一个.托付.即是让还有一个对象帮你做事情. 更多的模式,如状态模式.策略模式.訪问者模式本质上是在更特殊的场合採用了托付模式. 托付模式使得我们能 ...

  5. 效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】) 转

    效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中[附源代码下载])    本文目录: (一)背景 (二)数据库数据导入到Excel的方法比较   ...

  6. Spring Web Flow 入门demo(三)嵌套流程与业务结合 附源代码

    上篇博客我们说Spring web Flow与业务结合的方式主要有三种,以下我们主要介绍一下第三种的应用方式 3,运行到<action-state> 元素 SpringWeb Flow 中 ...

  7. 基于事件驱动的DDD领域驱动设计框架分享(附源代码)

    原文:基于事件驱动的DDD领域驱动设计框架分享(附源代码) 补充:现在再回过头来看这篇文章,感觉当初自己偏激了,呵呵.不过没有以前的我,怎么会有现在的我和现在的enode框架呢?发现自己进步了真好! ...

  8. 手把手实现微信网页授权和微信支付,附源代码(VUE and thinkPHP)

    wechat github 手把手实现微信网页授权和微信支付,附源代码(VUE and thinkPHP) 概述 公众号开发是痛苦的,痛苦在好多问题开发者文档是没有提到的,是需要你猜的. 在开发过程中 ...

  9. 【转】P2P之UDP穿透NAT的原理与实现(附源代码)

    作者:shootingstars (有容乃大,无欲则刚)  日期:2004-5-25 出处:P2P中国(PPcn.net) P2P 之 UDP穿透NAT的原理与实现(附源代码)原创:shootings ...

随机推荐

  1. 深入分析Android动画(一)

    动画的分类: ①View动画 View动画顾名思义其作用对象为View,包含平移.缩放.旋转.透明,这四类变化分别对应着Animation的子类TranlateAnimation.ScaleAnima ...

  2. 「JavaScript」同步、异步、回调执行顺序之经典闭包setTimeout分析

    聊聊同步.异步和回调 同步,异步,回调,我们傻傻分不清楚, 有一天,你找到公司刚来的程序员小T,跟他说:“我们要加个需求,你放下手里的事情优先支持,我会一直等你做完再离开”.小T微笑着答应了,眼角却滑 ...

  3. mybatis从数据库中取到的date格式不是yyyy-MM-dd HH:mm:ss

    问题:sqlserver中的存储时间格式为date,pojo的时间属性也是date,直接mybatis取出的时间格式是带英语的那种,不满足客户要求. 解决:将pojo的时间属性改为string类型,在 ...

  4. HtmlImageGenerator乱码问题解决、html2image放linux上乱码问题解决

    使用html2image-0.9.jar生成图片. 在本地window系统正常,放到服务器linux系统时候中文乱码问题.英文可以,中文乱码应该就是字体问题了. 一.首先需要在linux安装字体,si ...

  5. 设计模式的征途—7.适配器(Adapter)模式

    在现实生活中,我们的笔记本电脑的工作电压大多数都是20V,而我国的家庭用电是220V,如何让20V的笔记本电脑能够工作在220V的电压下工作?答案:引入一个电源适配器,俗称变压器,有了这个电源适配器, ...

  6. 使用Microsoft.AspNetCore.TestHost进行完整的功能测试

    简介 Microsoft.AspNetCore.TestHost是可以用于Asp.net Core 的功能测试工具.很多时候我们一个接口写好了,单元测试什么的也都ok了,需要完整调试一下,检查下单元测 ...

  7. 《Metasploit魔鬼训练营》第一章习题

    书本p391.The time line is as follows: * May 7, 2007: Initial defect disclosure to the security@samba.o ...

  8. 《用Java写一个通用的服务器程序》02 监听器

    在一个服务器程序中,监听器的作用类似于公司前台,起引导作用,因此监听器花在每个新连接上的时间应该尽可能短,这样才能保证最快响应. 回到编程本身来说: 1. 监听器最好由单独的线程运行 2. 监听器在接 ...

  9. Mybatis(三)返回值

    Mybatis返回值 MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则 ...

  10. bootstarp-fileinput上传 火狐防止拖入文件直接打开新页面

    今日接触了一个bootstarp的上传插件,发现其功能很强大,具体名为bootstarp-fileinput,需要的可以自行度一下. 然后当使用其拖拽功能时,其他浏览器没出毛病,独火狐浏览器拖入时直接 ...