游戏设计模式与实现之:责任链模式 与 关卡设计

15 篇文章 0 订阅
13 篇文章 5 订阅

GoF解释:

让一群对象都有机会处理一个请求,并减少请求发送者与接受者之间的耦合程度。将所有的接受者对象串联起来,让请求沿着串传递,知道有一个对象可以解决请求的问题为止。

模式说明:

对于一个问题或者一项需求,我们可以制造一条流水线,流水线上每个节点都可能是解决问题的方式,或者是满足需求的一部分。GoF四人组的解释只解释了对问题的处理,而责任链模式在当前的应用很多都是处理需求的组装,熟悉Java后台开发,尤其是Netty框架,大量的应用了责任链模式对对象进行组装。我们先来了解一下这个模式,再来仔细说一下这个模式的好处

案例说明:限时的组合关卡活动

1.需求说明:策划需要出限时闯关活动,配置一组关卡的ID,然后玩家从第一关开始,一直突破到最后一关
2.代码分析
实现IStageHandler

public abstract class IStageHandler{

	protected int mStageId ;
	protected IStageHandler mNextHandler;
	public IStageHandler(int stageId){
		this.mStageId = stageId;
	}
	//初始化Stage
	public virtual void InitStage(){ 
		//TODO
		
	}
	
	//设置本关卡的下个关卡
	public virtual IStageHandler SetNextHandler(IStageHandler nextHandler){
		this.mNextHandler = nextHandler
		return this.mNextHandler;
	}
	
	//更新关卡行为
	public virtual void UpdateStage(){
		if(CheckStageOver()){
			if(this.mNextHandler != null){
				this.mNextHandler.UpdateStage();
				return ;
			}
		}
		//TODO
	}
	//检查关卡是否结束
	public virtual bool CheckStageOver(){
		//TODO
		
	}	
}

实现关卡控制系统

public class StageSystem{
	
	private IStageHandler mRootStage = null;
	
	//设置一组关卡ID,在实际中可能是运营在服务器上指定,也可能是策划在配置表中指定
	private List<int> stageIds  = new List<int> { 1001,2001,3001,4001,5001};
	
	public void InitStage(){
		IStageHandler stage = null;
		//因为博主想让设计更贴合项目实际应用一点,所以并没有用完全显示的链式设计。这里的链式设计希望大家能理解。
		for(int i=0; i<stageIds.Count-1; i++){
			if( stage == null ) {
				stage = new IStageHandler(stageIds[i]);	
				this.mRootStage = stage;
			}
			else {
				stage = stage.SetNextHandler(new IStageHandler(stageIds[i]));
			}
		}
	}
	
	public void Update(){
		if(this.mRootStage != null){
			//从第一关开始更新,链式设计会让关卡链自动找到当前还没有完成的关卡
			this.mRootStage.UpdateStage();
		}
	}
}

从代码中就可以看出,关卡系统不需要再维护已经到了哪一关,只需要直接更新一条关卡链的头部节点,而具体已经到了哪一关,关卡链内部会自动更新。这样我们就把发送者和请求分离开来,但是每一个节点都能接收到问题并且执行。

当然责任链不接用于问题的解决,也用于一些对象的完整设置。我们也来举一个例子,比如我们要装配一个服务器处理对象
需求:设置最大链接个数,设置链接是否一直保持活动,设置接收文本的解析类,设置回传消息文本的封装类。
ServerBootstrap: 实际处理链接和消息的封装类

public class ServerBootstrap{
	private int mMaxSize = 1 ;
	private bool mAlive = false ;
	private IDecoder mDecoder ;
	private IEncoder mEncoder;
	//设置链接的最大个数
	public ServerBootstrap SetMaxSize(int size){
		this.mMaxSize = size ;
		return this;
	}
	//设置链接是否保持活跃
	public ServerBootstrap SetKeepAlive(bool alive){
		this.mAlive = alive ;
		return this;
	}
	//设置消息进来的解码
	public ServerBootstrap SetDecoder(IDecoder decoder){
		this.mDecoder = decoder ;
		return this;
	}
	//设置消息回传的编码
	public ServerBootstrap SetEncoder(IEncoder encoder){
		this.mEncoder = encoder ;
		return this;
	}
}

使用链式方法操作ServerBootstrap对象

public  class Server{
	public static void main(string args){
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.SetMaxSize(128)
				 .SetKeepAlive(false)
				 .SetDecoder(new IDecoder())
				 .SetEncoder(new IEncoder());
	}
}

这种做法在Java中相当常见,而目前游戏的短连服务器基本都使用Java完成,Netty中的对象大量的使用了链式编程的方式,使结构更加直观。当然Java服务器是有弊端的,最大的弊端就是不能热修复,另外对长链接的支持性并不好。所以在一些同步要求比较高的游戏中很少使用,长连服务器一般使用C+Lua去实现热修复,以及长连同步的需求。这个都是题外话了,有兴趣的同学可以自己去搜索一些资料看看,后面如果有时间,博主也会出一个专题带大家了解一下游戏服务器的知识。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值