网络游戏中不管采用什么语言开发 ,序列化和反序列化工具 google的 flatbuff 和protobuf 都是首选!
flatbuf后起之秀和protobuf中有一个共同的特性,那就是在游戏开发中对应的发序列化后的实体和对应的处理函数的对应关系。
可以采用传统的if else or switch case,如果 但是在实际的场景中要求快速响应。上述肯定是不能够满足实际的开发需求。游戏中区分消息以及消息对应的处理函数都是通过ID来查找。通常设计方案有如下2种:
1.用数组来存储,ID作为数组下标,对应处理函数或则对应处理函数的引用作为存储值。
2.通过map来存储。ID做key,对应处理函数或则对应处理函数的引用作为存储值。
两种数据结构,。针对java c++ 高级的编程语言(支持多态)处理都不错。不过有一点要注意,java中不能够存储function。所以在对应的2中方案中对应的值应该是处理函数的引用!这点要注意。c++ 则不同,可以存储引用或则function。
这里游戏数据包结构:packageLength +ID+message,其中packageLength为ID和message数据的总长度。
游戏中在业务层分发数据的时候,先解析出ID,然后通过上面的2中方式获取对应处理函数或则对应处理函数的引用作为存储值。调用处理函数,将对应的消息派发出去。
一般处理函数可以定义为void (session ,message);---这里 自己根据实际的场景来定义吧,seesion通常是一个player ? client 什么的,message 就是对应的那个pb实体消息类型--- 可以在分发的时候将字节数组转化为pb实体,亦可以在业务处理函数层转化。
下面具体解析下处理数据和pb实体的关系处理(主要用数组方式,map是一样的处理):
首先全局初始化一个静态的数组(c++版本):
typedef function<void(int , int )> DispatcherMessage;
static DispatcherMessage *array_message_hand_ref = new DispatcherMessage[1000]; 业务处理函数
void testFunctionMap2(int a, int b){
cout << "std::bind call 2 value of a ,b--->" << a << "," << b << endl;
} 对应的初始化ID和function或则引用。(这里的初始化 要注意选择合适的位置和时间 通常在程序初始化的时候)
array_message_hand_ref[2] = std::bind(&testFunctionMap2, std::placeholders::_1,
std::placeholders::_2);; 当业务层解析到ID 和对应的消息之后如这里是ID==2:
array_message_hand_ref[2](2,3); 这样就完成了数据的派发。
对于java,采用数组的方式应该用两个数组,ID 作为下标。利用java的多态性。
首先获取对应的引用,调用基类的函数,完成数据派发。
以上2中方案只作为参考。欢迎讨论。
后续。。。。
java 实现方案参考:
/**
* Created by 石头哥哥 on 2015/2/7.
* Content: 测试泛型接口
*/
public interface Function<T extends Object, M extends Message> {
/**
* 处理游戏逻辑接口
*
* @param session
* @param message
*/
void DispatcherMessage(T session, M message);
} 所有实例处理均继承该类并实现对应的方法
import com.google.protobuf.Message;
import javolution.util.FastMap;
import javax.annotation.PostConstruct;
/**
* Created by 石头哥哥 on 2015/2/7.
* Content:
*/
public abstract class BaseController implements Function<Player, Message> {
public static FastMap<Integer, Function<Player, Message>> MAP_FUNCTIONS = new FastMap<Integer, Function<Player, Message>>();
/**
* 负责初始化 ID 和 处理实体的关系
*/
@PostConstruct
protected abstract void PreIntiFunction();
}
import com.google.protobuf.Message;
import org.springframework.stereotype.Service;
/**
* Created by 石头哥哥 on 2015/2/7.
* Content:
*/
@Service
public class TestController extends BaseController {
@Override
protected void PreIntiFunction() {
MAP_FUNCTIONS.put(1, this); //初始化ID 和 实体处理函数关系
}
/**
* 处理游戏逻辑接口
*
* @param session
* @param message
*/
@Override
public void DispatcherMessage(Player session, Message message) {
}
}
public class Player {
} 注意java实现的方案 ,初始化 依赖了spring 整个游戏对象存在spring容器管理,这里只实现了基于map的方案,服务器要求快速相应 还是推荐选择数组方案 空间换时间,如果是客户端建议用map,内存不足情况下 尤其是手机平台。 技术选型 自己决定!!!
|