cocos2d-x开发: 如何从项目中分离出接口范例

cocos2d-x开发,包括核心模块接口开发和脚本部分的业务逻辑实现.从上层应用需求开始说,脚本在做业务逻辑实现的时候, 很多时候都需要依赖底层的接口功能,但是不是所有的人都可以游刃有余的去明白该怎么使用下层的接口,这不仅仅是语言的区别,其中还包括接口开发者在设计之初就期望的使用方式问题,所以一般都应该提供接口使用demo,由于我都是使用lua,所以我习惯的称之为unittest,接口功能测试则是以testcase的方式呈现.其实也就只是一种叫法.

先来说一下为什么我会做这样子的区分,我见过一些项目,要不然就是不提供使用范例,就是将各种测试都写在项目的入口文件那里.假如我们的引擎进入luaEngine之后进入的是src/main.lua文件中.那么按照很多没有分离好的项目的做法就会出现在main.lua文件中做一个变量.然后判断是进入游戏,还是进入测试,还是进入工具模式等等.程序员嘛,我们可以不纠结于这个实现的过程,结果也算是实现了各个方面的功能.不过,我还是要来分析一下: 项目开发毕竟是多个部分合作开发的,我们并不希望策划在使用我们提供的工具的时候还要自己手动去改配置文件.另外,由于初期就是为了方便将各种测试都堆叠在项目的某个文件里面,当然好的习惯不一定会被大家学习,这种坏习惯就很容易传染.后面每一个人就都会习惯这种简单的测试方法,认为这种测试堆叠的方法是理所当然的.最后的结果就是,堆测试的文件基本就是没法看了.

最后也是最主要的一点,我认真思考了一下,做下层接口,写范例代码是为了什么?其实就是作为对api不足的补充,更好的是某种情况下,达成某正规范,是可以让大家很快的熟悉接口的使用方法.我始终坚信,接口的设计者在实现的时候就应该会想到该如何更好的去使用自己写的接口.上面说了很多,希望能够准确的表达我的意思, 如果看不懂, 可以看下面我的思路以及实现,相信还是很容易看得懂的.

我先想到的是将除了项目业务逻辑实现部分的其他相关,像是工具呀,接口范例呀这些都分离出来,要做到这样子并不难,无非是在项目脚本目录的同级目录穿件一个新的文件夹,另外提供一个新的入口文件.就像下面这样子:

1 frameworks
2 runtime
3 res
4 src
5      --main.lua  --我们通常看到的游戏入口文件
6      --Tests
7              --TestsController.lua -- 测试入口
8      --Tools   -- 如果需要,工具部分入口.

结合我前面的出发点,我不希望更改脚本或者是配置文件做到这样子.不过也好解决,我们都知道,无论是在win下还是在linux下面,应用程序在运行的时候是可以解析命令行参数的.当然在Linux下面就是解析main函数的argc和argv,而在win下面也是同样,我们可以解析lpCmdLine,或者是__argc,__targv(tchar.h).关于win下面的这部分因为涉及到unicode的问题,所以我才会写成这个样子的,不过大家应该都会明白的.说到这里,应该很好明白如何去实现这部分的功能了.我以win32为例,代码如下:

 1 AppDelegate.h
 2 public:
 3     void setCmdLine(const std::string& cmdline)
 4     {
 5         this->M_cmdline_ = cmdline;
 6     }
 7     std::string getCmdLine() const
 8     {
 9         return this->M_cmdline_;
10     }
11 private:
12     std::string getCmdByFlag(const std::string& flag, const std::string& defaultValue);
13     std::string M_cmdline_;

这是引擎封装好的入口代理,这里我添加了一个私有属性,用来装从命令行读取的参数.不管读到了什么,都一并装过来.不过,既然是我写,我当然知道我希望的格式是什么样子的了. “xiaoyan.exe -esrc/Tests/TestsController.lua”

就像是这个样子的,解析的时候我只要去解析-e后面的flag属性字段,我就知道要运行什么模块的代码了.好了,我做了一下Unicode字符串到ansi的转换,如下:

 1 win32 main.cpp
 2  // create the application instance
 3     AppDelegate app;
 4     if(__argc > 1)
 5     {
 6 #if(UNICODE)
 7         std::wstring wcmdLine(lpCmdLine);
 8         const wchar_t* wparams = wcmdLine.c_str();
 9         size_t size = wcmdLine.size() * 2 + 1;
10         char* tmp = new char[size];
11         memset(tmp, 0, size);
12         wcstombs(tmp, wparams, size);
13         std::string cmdline(tmp);
14         app.setCmdLine(cmdline);
15         delete[] tmp;
16 #else
17         std::string cmdLine(lpCmdLine);
18         app.setCmdLine(cmdline);
19 #endif
20     }
21     int ret = Application::getInstance()->run();

虽然我不懂win32 sdk,但是简单看看unicode处理,还是很容易写出上面的这些代码.现在,我拿到了我想要的命令行参数,也做了相应的跨平台转化处理,放在std::string,解析部分就简单了,直接给实现:

 1 std::string AppDelegate::getCmdByFlag(const std::string& flag, const std::string& defaultValue)
 2 {
 3 4     if(this->M_cmdline_.empty()) { return defaultValue; }
 5     std::size_t index = this->M_cmdline_.find(flag);
 6     if(index == std::string::npos) { return defaultValue; }
 7     std::size_t nextIndex = this->M_cmdline_.find("-", index+flag.size());
 8     if(nextIndex == std::string::npos) { return this->M_cmdline_.substr(index+flag.size(), std::string::npos); }
 9     else { return this->M_cmdline_.substr(index+flag.size(), nextIndex-index-flag.size()); }
10     return defaultValue;
11 }

经过上面的变动,我就可以去修改我的引擎入口实现了,不废话,直接看吧.

 1 bool AppDelegate::applicationDidFinishLaunching()
 2 {
 3     auto engine = LuaEngine::getInstance();
 4     ScriptEngineManager::getInstance()->setScriptEngine(engine);
 5     std::string entranceFile = getCmdByFlag("-e", "main.lua");
 6     if (engine->executeScriptFile(entranceFile.c_str())) {
 7         return false;
 8     }
 9
10     return true;
11 }

我这边只是添加了一个接口测试模块,所以并没有什么逻辑判断之类的,不过我相信,即使是再多添加一些功能,也是很容易做的,但是不是修改上面这里的入口,而是简单的在运行时候提供我们想要运行的模块入口文件就行了.因为涉及到工作目录的问题,我在测试的时候是使用vs做的,不过,我也写好了sublime text配置部分的,一并给出来.我先是修改了build system,添加了一个Test的子模块:(可以对照上一篇文章看一下,如果不嫌麻烦)

 1 {
 2     "cmd": ["C:\\Users\\Administrator\\Desktop\\xiaoyan\\scripts\\compile-win32.cmd"],
 3     "working_dir": "C:\\Users\\Administrator\\Desktop\\xiaoyan\\xiaoyan",
 4     "shell": true,
 5     "encoding":"utf-8",
 6     "variants":
 7     [
 8         {
 9             "cmd" : ["start","C:\\Users\\Administrator\\Desktop\\xiaoyan\\xiaoyan\\runtime\\win32\\xiaoyan.exe"],
10             "name": "Run",
11         },
12         {   --添加一个Test,带有参数
13             "cmd" : ["start","C:\\Users\\Administrator\\Desktop\\xiaoyan\\xiaoyan\\runtime\\win32\\xiaoyan.exe","-esrc/Tests/TestsController.lua"],
14             "name": "Test",
15         }
16     ]
17 }

如上面我在注释中给出的说明一样, 后面加入了Test附加的参数,也就是测试模块的入口.好吧,做到这里就只剩下最后的琐碎了.先去添加一个快捷键:

1 [
2     { "keys": ["alt+f1"], "command": "toggle_side_bar" },
3
4     { "keys": ["f5"], "command": "build" },
5     { "keys": ["f10"], "command": "build", "args": {"variant": "Run"} },
6     { "keys": ["f8"], "command": "build", "args": {"variant": "Test"} },
7 ]

好吧,做到这个份上了, src/Tests/TestController.lua的测试源码就不用给了吧? 我相信还是很容易想到如何做的.该说说我为什么要这样做,而这么做和分离又有什么关系?在说这之前,我先说一下如何用,一样的,知道如何用就知道优点在哪里,自然也就明白了好处.可以参照Lua-tests的例子,是一种很好实现Tests的方法,不过,当然我们不会写的这么复杂.做到这样,可能还不完善,但是分离的工作相信很容易就看到成效了,在开发中有什么不明白的,先去翻阅Tests下面的TestCase,如果需要添加接口,将写好的接口测试加入TestCase提交就好了.

到这里,分离部分我就做完了,对于分离后下面的测试实现,相信不同的有见解的程序员会有不同的做法,那些就自由发挥了.其实我这样做的目的,是为了测试下层模块接口使用的.在没有确定游戏类型和需求之前,盲目的去做下层架构设计相关的工作,会造成后期开发很多问题.

时间: 2024-11-12 21:54:37

cocos2d-x开发: 如何从项目中分离出接口范例的相关文章

单页开发web app项目中使用的技术点总结

首先项目中需要的技术依赖于业务,所以先说下业务概述 1.业务概述 个人用户在线申请房源 2.技术分解 2.1 项目布局结构 2.2 开发环境 2.2.1安装NodeJS环境 @echo offrem ======= 如何安装handlebars编译器 =======rem 1.到https://nodejs.org/下载并安装nodejsrem 2.打开cmd并定位到项目目录rem 3.执行npm install handlebars -g命令rem 4.执行npm install grunt-

切身体会,从项目中小结出 前端程序员容易忽视的一些基础知识

基础数据结构与算法 现在有两个不同的JSON,比较复杂,可以参考这里的DEMO中返回的JSON.要比较它们的差异,除了用现成的工具如beyond compare以外,如果我们的机器上没有安装这个工具,能如何较快解决?作为一个程序员,一个个对比是不可行的,对比完也不会有什么收获.我会把之放进Excel中(如果你机器连这个都没有,那忽视我),先排序,再用二分法去快速定位找到有差异的JSON属性,即使是1024个字段的大数据,也最多10次的定位即可找到.其实算法这东西,并不是给你一道题目然后把死记下来

项目中调用天气预报接口

项目中使用的是心知天气的API,下面我就简单总结一下使用的过程: 1. 在心知天气官网注册一个个人账号,这样就会产生一个API秘钥和一个用户ID,用户ID用于签名验证方式.签名指的是通过HMAC-SHA1,对请求参数加密后得到的签名字串进行身份验证,避免了将API密钥明文包含在请求中而造成泄露. 2. 关于签名生成方式如下: (1)构造验证参数字符串 将请求参数按照参数名字典升序排列后,把所有参数param=value用&连接起来,类似URI中Query string的构造方式.目前支持的参数有

以“掌上东航”为例,论混合开发在企业级项目中的实践

提起"掌上东航",很多人一下子会想到另一款应用"东方航空",那么,这款企业级应用有什么作用?和"东方航空"之间又有什么关系或者区别?近日,在北京国际会议中心举行的AppCan移动开发者大会上,东方航空移动互联部的项目经理张晨飞,对"掌上东航"进行了详细解读. 东航移动互联部的项目经理张晨飞作演讲 "掌上东航"-不断发展壮大 众所周知,"东方航空"是东航推向各个旅客的一个Web的应用,而&

IDEA开发环境MAVEN项目中使用profile来指定环境所遇到的问题

有时候我们会在web.xml中传递参数时指定环境,但这样可能会遇到一些问题,web.xml配置文件如下图所示 可以看到在这里使用了${profiles.activation},这样做本身是没有问题的,当我们使用maven打包时,会按照我们指定的环境对其进行替换,比如替换为dev. 因此我们可以直接用tomcat7:deploy来远程部署项目,用tomcat7:redeploy来重新部署项目,因为它们本质上都是先将项目打包,然后上传到服务器运行. 可是当我们使用tomcat7:run来启动项目时,

iOS开发 - 公司项目中一个类似淘宝的商品属性选择页的实现

废话不多说,有一点:( 这里公司项目 本来是用button通过计算宽度来实现,但是当标签过多时,大量的button会影响效率,正解还是乖乖使用collectionview实现 )直接上效果图: 代码在我的github:https://github.com/caijunrong/CommodityTagView.git

C#.NET常见问题(FAQ)-使用SharpDevelop开发 如何在项目中添加类文件

点击文件-新建-文件,然后再工程内创建文件 ? 或者工程-添加-新建项 ? ? 更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com/acetaohai123 ? 我的在线论坛: http://csrobot.gz01.bdysite.com/ ? 问题交流: QQ:910358960 邮箱:[email protected] ? ?

linux下如何从FIT镜像(*.itb)中分离出内核、根文件系统和设备树?

答: 使用dumpimage工具可以对itb文件进行分离,示例如下: $ dumpimage -l <your.itb> (列出itb文件中描述内核.根文件系统.设备树等的相关信息) $ dumpimage -T flat_dt -p index -o kernel.gz <your.itb>  (index=0,1...) 原文地址:https://www.cnblogs.com/dakewei/p/12430203.html

如何在python项目中写出像Django中一样功能的settings

一  核心文件目录结构 二  实现代码 resdme: 在实现此功能主要用到的知识点及模块: 1.反射 3.内置方法dir # 全局配置 NAME = 'root' # 用户配置 NAME = 'personal' from lib.conf import global_settings # 全局默认配置 from config import setting # 用户个人配置 class Settings(): ''' 需要注意的是: 1.在初始化的时候要将全局的配资放在个人的前面 2.因为如果