flatbuffers 在cocos2dx中的应用

flatbuffers 在cocos2dx中的应用,第1张

概述这篇文章 接着 前面的http://my.oschina.net/chenleijava/blog/423503,继续说说flatbuffers的应用 这里主要说的是flatbuffer 作为以cocos2dx引擎为基础 ,网络部分的序列化方案采用flatbuffers。 之所以考虑flatbuffers,依赖性低 ,性能较好。 这里只谈论设计方案,该设计方案对代码设计和结构上有一定的约定(相对订

这篇文章 接着 前面的http://my.oschina.net/chenleijava/blog/423503,继续说说flatbuffers的应用

这里主要说的是flatbuffer 作为以cocos2dx引擎为基础 ,网络部分的序列化方案采用flatbuffers。

之所以考虑flatbuffers,依赖性低 ,性能较好。

这里只谈论设计方案,该设计方案对代码设计和结构上有一定的约定(相对订制):

客户端 会接受来自服务器的响应,解码到消息,进行数据处理。针对flatbuffers生成的类和对应处理该消息事的方案映射

在以前protbuffer中有提过(http://my.oschina.net/chenleijava/blog/376560)。这里依旧采用此方案:

注意以下所提及的类或者接口都是代码生成器生成(主要适用于这类方案 定制的,采用java编写),会解析fbs文件,生成对应的controller 文件。编写逻辑 只在

virtualvoIDdispatcherMessage(char*data);

中完成;

fbs测试:

//1.使用genTools生成对应客户端代码你需要严格约定//2.table命名约定上下行消息xxRequestxxResponse//3.前后端交互消息存在一个消息ID;命名约定:msgiD//4.命名空间使用gen---主要限制前端namespacegen;tableLoginFlatRequest{msgiD:int=1;username:string;}tableLoginFlatResponse{msgiD:int=2;time:long;}tableBattleRequest{msgiD:int=3;}tableBattleResponse{msgiD:int=4;}


接口类设计:IController.h

//warnthisisgenfile,don'tmodifyit#ifndef_ICONTRolLER_H#define_ICONTRolLER_H#include<map>#include"cocos2d.h"#include"flatgen/Game_generated.h"usingnamespacecocos2d;usingnamespacegen;usingnamespacestd;#ifndefdelete_array#definedelete_array(p)do{if(p){delete[](p);(p)=nullptr;}}while(0)#endif//delete_arrayclassIController{public:IController(){}/**注册消息ID和对应处理controller的关系以便于快速索引处理*/staticstd::map<int,IController*>controller_map;/**负责处理数据分发*/virtualvoIDdispatcherMessage(char*data);/***获取对应的消息ID*/virtualintmsgiD()=0;/**转化对应消息为flatbuffers实体data+4:消息ID占用4字节*/template<typenameT>constT*getRoot(char*data);/***@Author石头哥哥,15-06-0123:06:26**@brIEf注册controolerandmapper*/staticvoIDregisterMapperController();};template<typenameT>inlineconstT*IController::getRoot(char*data){returnflatbuffers::GetRoot<T>(data+4);}#endif//_ICONTRolLER_H

.cpp

//thisisgenfile,don'tmodifyit#include"IController.h"#include"LoginFlatController.h"#include"BattleController.h"map<int,IController*>IController::controller_map;voIDIController::dispatcherMessage(char*data){}/***注册controllermapper*/voIDIController::registerMapperController(){log("%s","registerMapperController开始注册controller......");controller_map[LoginFlatController::controller->msgiD()]=LoginFlatController::controller;controller_map[BattleController::controller->msgiD()]=BattleController::controller;}


生成对应的子类:LoginFlatController.h

//thisisgenfile,don'tmodifyit#ifndefLoginFlatController_h#defineLoginFlatController_h#include"IController.h"classLoginFlatController:publicIController{public:staticLoginFlatController*controller;public:/**负责处理数据分发处理来自服务器数据*/virtualvoIDdispatcherMessage(char*data);/***获取对应的消息ID*/virtualintmsgiD()overrIDe;};#endif//LoginFlatController_h

.cpp

//thisisgenfile,logiccontroler#include"LoginFlatController.h"LoginFlatController*LoginFlatController::controller=newLoginFlatController;intLoginFlatController::msgiD(){flatbuffers::FlatBufferBuilderbuilder;builder.Finish(CreateLoginFlatResponse(builder));automsgiD=flatbuffers::GetRoot<LoginFlatResponse>(builder.GetBufferPointer())->msgiD();builder.ReleaseBufferPointer();returnmsgiD;}/**负责处理数据分发处理来自服务器数据*/voIDLoginFlatController::dispatcherMessage(char*data){autologinflatresponse=getRoot<LoginFlatResponse>(data);//Todo::处理来自服务器数据LoginFlatResponse}

因为生成代码的工具还在开发中。目前只完成了cpp生成 ,后期支持java(服务器端)---暂时只定制flatbuffer代码生成。

后期开源分享,这里提供java代码生成类:

packagecom.genflat.mapper;/**copyright(c)2015.*游戏服务器核心代码编写人石头哥哥拥有使用权*最终使用解释权归创心科技所有*联系方式:E-mail:[email protected];*个人博客主页:http://my.oschina.net/chenleijava*poweredby石头哥哥*/importorg.apache.commons.io.fileUtils;importjava.io.file;importjava.io.filenameFilter;importjava.io.IOException;importjava.io.RandomAccessfile;importjava.util.ArrayList;/***@author石头哥哥*</P>*Date:2015/6/2*</P>*Time:9:35*</P>*Package:dcServer-parent*</P>*<p/>*注解:*/publicclassGenFlatCpp{/***客户端处理消息类型注意消息命名XXXResponse---服务器响应消息类型*/privatestaticfinalStringclIEnt="Response";/***用于生成处理消息类型引用的变量名注意是静态类型*/privatestaticfinalStringcontrollorname="controller";/***对应客户端处理来自服务器端消息命名*xxxResponse*<p/>*tableLoginResponse{*objectID:int=2;*username:string;*}*<p/>*生成处理来自服务器端的Response类型消息<p/>*自动生成映射的mapper如:controller_map[msgiD<LoginResponse>()]=LoginResponseController::controller;<p/>*同时生成对应的controller处理部分<p/>*逻辑编写部位:virtualvoIDdispatcherMessage(char*data);<p/>**@paramfbspathflatbufferfbs所在文件路径<p/>*@paramcontrollerpath对应controller生成路径<p/>*@throwsIOException*/@SuppressWarnings("ResultOfMethodCallignored")publicstaticvoIDgenCppMapper(Stringfbspath,Stringcontrollerpath)throwsException{filefile;//getfbstableListfile=newfile(fbspath);String[]fbsnames=file.List(newfilenameFilter(){@OverrIDepublicbooleanaccept(filedir,Stringname){returnname.endsWith(".fbs");}});if(fbsnames==null){thrownewException("fbsnotfoundinres!!!");}ArrayList<String>fbsPaths=newArrayList<String>();for(Stringfbsname:fbsnames){fbsPaths.add(fbspath+"/"+fbsname);}//读取所有fbs文件获取文件中的tablenameArrayList<String>mappertable=newArrayList<String>();//loadingfbsandfiltertablenamefor(Stringfbs:fbsPaths){file=newfile(fbs);RandomAccessfilerandomAccessfile;try{randomAccessfile=newRandomAccessfile(file,"r");//O_RDONLYStringtxt="";while(txt!=null){txt=randomAccessfile.readline();if(txt!=null&&txt.startsWith("table")){Stringtemp=txt.substring(0,txt.lastIndexOf("{")).replace("table","");if(temp.endsWith(clIEnt))mappertable.add(temp.trim());}}randomAccessfile.close();//closerandomAccessfile}catch(IOExceptione){e.printstacktrace();}}fbsPaths.clear();ArrayList<String>controllerList=newArrayList<String>();//foricontrollerStringBuildermapperBuilder=newStringBuilder();//controller_map[LoginFlatController::controller->msgiD()]=LoginFlatController::controller;for(Stringtable:mappertable){Stringcontrollername=table+"Controller";controllername=controllername.replace(clIEnt,"");mapperBuilder.append("controller_map[").append(controllername).append("::").append(controllorname+"->msgiD()").append("]").append("=").append(controllername).append("::").append(controllorname).append(";\n");controllerList.add(controllername);//addcontroller}mappertable.clear();ArrayList<String>genIcontrollerheader=newArrayList<String>();genIcontrollerheader.addAll(controllerList);/***don'toverrIDehadgenxxxcontroller*becausemaybehadlogicinit!!!!*/String[]exsiteController=newfile(controllerpath).List(newfilenameFilter(){@OverrIDepublicbooleanaccept(filedir,Stringname){returnname.endsWith(".cpp")&&!name.endsWith("IController.cpp");}});for(Stringname:exsiteController){Stringtemp=name.substring(0,name.indexOf("."));if(controllerList.contains(temp)){controllerList.remove(temp);}}StringBuilderbuilderCpp=newStringBuilder();//gen.hfilefor(Stringcontroller:controllerList){Stringdefine=controller+"_h";builderCpp.append("//thisisgenfile,don'tmodifyit\n").append("#ifndef").append("").append(define).append("\n").append("#define").append("").append(define).append("\n").append("#include\"IController.h\"").append("\n").append("class").append(controller).append(":").append("publicIController{").append("\n").append("public:").append("\n").append("static").append(controller).append("*").append(controllorname).append(";\n").append("public:\n").append("/**\n"+"负责处理数据分发处理来自服务器数据\n"+"*/\n").append("virtualvoIDdispatcherMessage(char*data);\n").append("/**\n"+"*获取对应的消息ID\n"+"*/\n").append("virtualintmsgiD()overrIDe;\n").append("};\n").append("#endif").append("//").append(define);byte[]cpp_h=builderCpp.toString().getBytes();builderCpp.delete(0,cpp_h.length);//writeheaderfilecontrollerfile=newfile(controllerpath);if(!controllerfile.exists()){controllerfile.mkdirs();}fileUtils.writeByteArrayTofile(newfile(controllerpath+"/"+controller+".h"),cpp_h);//gencontrollercppfileStringtablename=controller.substring(0,controller.indexOf("Controller"))+clIEnt;Stringlowtablename=tablename.tolowerCase();builderCpp.append("//thisisgenfile,logiccontroler\n").append("\n").append("#include").append("").append("\"").append(controller).append(".h").append("\"").append("\n").append(controller).append("").append("*").append(controller).append("::").append(controllorname).append("=").append("new").append(controller).append(";\n").append("\n").append("int").append(controller+"::msgiD(){\n").append("flatbuffers::FlatBufferBuilderbuilder;\n"+"builder.Finish(Create"+tablename+"(builder));\n"+"automsgiD=flatbuffers::GetRoot<"+tablename+">(builder.GetBufferPointer())->msgiD();\n"+"builder.ReleaseBufferPointer();\n"+"returnmsgiD;\n").append("}\n\n").append("/**\n"+"负责处理数据分发处理来自服务器数据\n"+"*/\n").append("voID").append(controller).append("::").append("dispatcherMessage(char*data){\n\n").append("auto").append(lowtablename).append("=getRoot<").append(tablename).append(">(data);\n").append("//Todo::处理来自服务器数据").append(tablename).append("\n\n").append("}");byte[]cpp=builderCpp.toString().getBytes();builderCpp.delete(0,cpp.length);fileUtils.writeByteArrayTofile(newfile(controllerpath+"/"+controller+".cpp"),cpp);}//IControlleralwaysoverrIDe//genIControllergeneratedheadernameArrayList<String>generatedheaders=newArrayList<String>();Stringtempname;Stringtempnameup;charfirst;for(Stringname:fbsnames){tempname=name.substring(1,name.lastIndexOf("."));tempnameup=name.substring(0,name.lastIndexOf(".")).toupperCase();first=tempnameup.charat(0);generatedheaders.add(first+tempname);}builderCpp.append("//warnthisisgenfile,don'tmodifyit\n").append("#ifndef").append("_ICONTRolLER_H\n").append("#define").append("_ICONTRolLER_H\n").append("#include<map>\n").append("#include\"cocos2d.h\"\n");//appendgeneratedheaderincludefor(Stringname:generatedheaders){builderCpp.append("#include\"flatgen/").append(name).append("_generated.h\"").append("\n");}generatedheaders.clear();builderCpp.append("usingnamespacecocos2d;\n").append("usingnamespacegen;\n").append("usingnamespacestd;\n").append("#ifndefdelete_array\n").append("#definedelete_array(p)do{if(p){delete[](p);(p)=nullptr;}}while(0)\n").append("#endif//delete_array\n").append("classIController{\n").append("\n").append("public:\n").append("IController(){}\n").append("/**\n"+"注册消息ID和对应处理controller的关系\n"+"以便于快速索引处理\n"+"*/\n").append("staticstd::map<int,IController*>controller_map;\n").append("/**\n"+"负责处理数据分发\n"+"*/\n").append("virtualvoIDdispatcherMessage(char*data);\n").append("/**\n"+"*获取对应的消息ID\n"+"*/\n").append("virtualintmsgiD()=0;\n")//.append("/**\n"+//"*@Author石头哥哥,15-06-0123:06:00\n"+//"*\n"+//"*@brIEf获取生成消息对应的msgiD\n"+//"*\n"+//"*@return<#returnvaluedescription#>\n"+//"*/\n")//.append("template<typenameT>staticintmsgiD();\n").append("/**\n"+"转化对应消息为flatbuffers实体\n"+"data+4:消息ID占用4字节\n"+"*/\n").append("template<typenameT>constT*getRoot(char*data);\n").append("/**\n"+"*@Author石头哥哥,15-06-0123:06:26\n"+"*\n"+"*@brIEf注册controolerandmapper\n"+"*/\n").append("staticvoIDregisterMapperController();\n").append("};\n")//.append("template<typenameT>\n")//.append("inlineintIController::msgiD(){\n"+//"flatbuffers::FlatBufferBuilderbuilder;\n"+//"builder.Finish(CreateLoginRequest(builder));\n"+//"automsgiD=flatbuffers::GetRoot<T>(builder.GetBufferPointer())->msgiD();\n"+//"builder.ReleaseBufferPointer();\n"+//"returnmsgiD;\n"+//"}\n").append("template<typenameT>\n"+"inlineconstT*IController::getRoot(char*data){\n"+"returnflatbuffers::GetRoot<T>(data+4);\n"+"}").append("\n").append("#endif//_ICONTRolLER_H");byte[]data=builderCpp.toString().getBytes();builderCpp.delete(0,data.length);fileUtils.writeByteArrayTofile(newfile(controllerpath+"/IController.h"),data);//genicontrollercppbuilderCpp.append("//thisisgenfile,don'tmodifyit\n").append("#include\"IController.h\"\n");for(Stringcontroller:genIcontrollerheader){builderCpp.append("#include").append("\"").append(controller).append(".h").append("\"\n");}genIcontrollerheader.clear();controllerList.clear();builderCpp.append("\n").append("map<int,IController*>IController::controller_map;\n").append("voIDIController::dispatcherMessage(char*data){}\n").append("/**\n"+"*注册controllermapper\n"+"*/\n"+"voIDIController::registerMapperController(){\n"+"log(\"%s\",\"registerMapperController开始注册controller......\");\n").append(mapperBuilder.toString()).append("}\n");data=builderCpp.toString().getBytes();builderCpp.delete(0,data.length);fileUtils.writeByteArrayTofile(newfile(controllerpath+"/IController.cpp"),data);System.out.println("-------gensuccess!!!---------------------");}}
packagecom.genflat.mapper;/**copyright(c)2015.*游戏服务器核心代码编写人石头哥哥拥有使用权*最终使用解释权归创心科技所有*联系方式:E-mail:[email protected];*个人博客主页:http://my.oschina.net/chenleijava*poweredby石头哥哥*/importjava.io.file;importjava.io.IOException;/***@author石头哥哥*</P>*Date:2015/6/2*</P>*Time:9:34*</P>*Package:dcServer-parent*</P>*<p/>*注解:*/publicclassGenFlatMapper{/***defaultgenc++*args[0]-l*args[1](java,cpp)*args[2]-p*args[3](controllerfilepath)*args[4]-o*args[5]fbsfilepath**@paramargs*/publicstaticvoIDmain(String[]args)throwsIOException{Stringshow=">>>>flatbuffergen"+"\n该工具可以生成基于flatbuffers的代码,接口说明如下\n"+"使用命令:java-jargenflatMapper.jar-lcpp-ccontrollerpath-ffbspath\n"+"-l:编程语言类型这里暂时支持c++;\n"+"-p:游戏中处理对应消息的controller文件路径;\n"+"-o:编写的fbs文件路径;\n"+"游戏中fbs针对上行下行table命名规则有严格约定,如不使用该约定\n"+"使用该工具无效,详见readme!";System.out.println(show);if(args.length!=0){System.out.println("--------begingenclIEntcode----------------");if(args.length<6){System.err.println(show);System.exit(0);}Stringl=args[1];Stringcontrollerpath=args[3];Stringfbspath=args[5];if(l.equals("java")){System.err.println("onlysupportclIEnt,c++\n");System.err.println("useeg:\n"+"java-jargenflatMapper.jar-lcpp"+"-ccontrollerpath-ffbspath");System.exit(0);}elseif(l.equals("cpp")){try{GenFlatCpp.genCppMapper(fbspath,controllerpath);}catch(Exceptione){e.printstacktrace();}}}else{try{//gencurrentfileSystem.out.println("toolswillgentocurrentfiles,ifyourfbsinresfile!!!");filefile=newfile("./controller");if(!file.exists())file.mkdirs();//findfbsGenFlatCpp.genCppMapper("res","./controller");}catch(Exceptione){e.printstacktrace();}}}}


该生代码成器约定如下--如果你使用该方案,那么请严格遵循改约束,或许你有更好的IDea:

###基于flatbuffers,使用fbs文件生成对应前端代码。###完成对应的controller和消息ID映射,目前暂时支持c++。>1.使用genTools生成对应客户端代码你需要严格约定2.table命名约定上下行消息xxRequestxxResponse3.前后端交互消息存在一个消息ID;命名约定:msgiD>4.命名空间使用gen---主要限制前端namespacegen;//下行消息xxRequesttableLoginRequest{msgiD:int=1;//消息IDmsgiDusername:string;}//下行消息xxResponsetableLoginResponse{msgiD:int=1;//消息IDmsgiDusername:string;}####如何使用:该工具可以生成基于flatbuffers的代码,接口说明如下使用命令:java-jargenflatMapper.jar-lcpp-pcontrollerpath-ofbspath>-l:编程语言类型这里暂时支持c++;>-c:游戏中处理对应消息的controller文件路径;>-f:编写的fbs文件路径;

生成对应的文件如下:

上面代码都是生成的。

因为无法上传jar,如果你需要 留言你的邮箱 !

总结

以上是内存溢出为你收集整理的flatbuffers 在cocos2dx中的应用全部内容,希望文章能够帮你解决flatbuffers 在cocos2dx中的应用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1059602.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存