战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

#

近期在写基于go的游戏服务器框架, 在全面脱离C/C++前, 需要对老架构进行一个总结

基于C/C++游戏服务器框架总体设计的还是不错的, 兄弟们总体使用效果都是好评. 因为在技术上喜欢"偷懒", 所以在很多设计上, 都是力求简单, 高效(开发效率).

基于任务的异步DB查询系统, 带多重异步的同步

代码示例:

   1:   
   2:  void BatchQueryPlayerInfo( uint32 ClientID, const std::string& AccountName, int64 CharID )
   3:  {
   4:      GDBExecutor->Commit
   5:          (    
   6:          dynamic_cast<DBDataTask*>( (new DBQueryCharInfo(  ClientID, CharID ) ) 
   7:          ->LinkAtomTask( new DBQueryQuest( ClientID, CharID ) )
   8:          ->LinkAtomTask( new DBQuerySkill( ClientID, CharID ) )
   9:          ->LinkAtomTask( new DBQueryHero( ClientID, CharID ) )
  10:          ->LinkAtomTask( new DBQueryAccountInfo( ClientID, AccountName ) )
  11:          ->LinkAtomTask( new DBQueryEquip( ClientID, CharID ) )
  12:          ->LinkAtomTask( new DBQueryObject( ClientID ,CharID ) )
  13:          ->LinkAtomTask( new DBQueryLevel(ClientID, CharID))
  14:          ->LinkAtomTask( new DBQueryChapter(ClientID, CharID))
  15:          ->LinkAtomTask( new DBQueryActivity( ClientID, CharID ))
  16:          )
  17:          );
  18:   
  19:  }

这段主要处理玩家在登陆时, 需要从DB查询大量的不同分类的数据. 为了保证效率, 我让每个Task并行执行, 然后通过一个机制, 让所有任务完成后, 回调第一个任务的一个函数. 这样就无需手动实现很多粘合代码, 避免了反复调试和错误

基于protobuf反射机制的语句自动合成

   1:  DBUpdateCharInfo::DBUpdateCharInfo( int64 CharID, const std::string& Buffer )
   2:  {
   3:      char buffer[256];
   4:   
   5:      sprintf( buffer, "update tb_char set $FIELD$ where charid = %lld;", CharID );
   6:          
   7:      ExecuteCommand( buffer, Buffer, dbopr::FET_Equation );
   8:  }

这段就是一个典型的DB任务, 构造函数提供了CharID和一个由结构体序列化好的buffer, $FIELD$字段, 是通过反射根据Buffer内容, 自动填充字段

这段例子中, $FIELD$可以填充为 hp=100, mp=100之类的. 自动填充避免了因为添加字段的到处添加代码, 还需要调试, 容易搞错

 

配置系统概念

基于同一个配置系统, 分层实现不同的需求. 更简单的说, 解决的1个实际问题是:

自己改了配置文件中的ip, 上传svn后, 覆盖了别人的配置, 很多人的解决方法都是, 本地配置不提交. 但同时问题又来了:

当配置中有别人新加的系统配置, 怎么保证每个人都能更新到?

上线后, 服务器交付运维, 他们会对配置有一定程度的修改, 这个时候怎么合并程序配置和运维配置?

其实对于冲突的需求, 只要对系统进行分层就可以解决问题,我的处理方式:

配置分为:

全局配置: 所有服务的总体配置

单服务配置: 本服务的配置, 涉及网络及逻辑

本地配置: 这个配置每个人一份, 不上传SVN

命令行配置: 格式和前面的一致, 这块就可以通过运维进行配置

总体结构其实就是OO的派生概念, 下层可以覆盖, 修改上层的配置

 

服务器互联及识别框架

基本功能: 基于一些简单的配置就可以将多台服务器, 同种类的不同服务器互相连接起来, 断线自动重连.

服务器连接后, 所有服务器可知晓并可自动按需连接

逻辑端也很方便的进行广播或者单独发送等

也就是说, 每个服务器的连接和接受端都是带识别名称或id的.

后面觉得这套东西实在是做的复杂, 多整出一台中心服务器来做. 但好歹框架稳定下来了, 也就好了.

 

基于lua的服务器web后台框架

思想是很不错的,  C++ 配合lua本身绝对是个失败

问题出在web处理,本身都是一个同步阻塞过程, 而这个后台框架是异步方式来做, 所以特别别扭

不过比起以前的本地GM系统, 这块的设计是伟大的进步

 

现在正在设计基于golang的服务器框架, 基本框架已经完工, 等待编写逻辑后的实战测试

以上的很多思想在golang的服务器框架都有改进, 特别是golang本身做web也是优秀的, 外加martini这种牛X框架, 更是水到渠成

如果你对服务器框架设计有特别的认识, 或者想碰撞思想, 可以加博客群 309800774或者我的qq: 20998333讨论

posted @ 2014-12-18 16:39 战魂小筑 阅读(8552) | 评论 (1)编辑 收藏

推荐一个适用于Visual Studio2013/11的Google protobuf的proto文件高亮插件, 上图

image

虽然没有Eclipse插件的自动生成序号功能, 但已经很漂亮了, 还自带有protobuf关键字提醒, 很不错
地址: https://visualstudiogallery.msdn.microsoft.com/4bc0f38c-b058-4e05-ae38-155e053c19c5

posted @ 2014-12-16 14:06 战魂小筑 阅读(2999) | 评论 (0)编辑 收藏

LiteIDE中有一个get按钮可以模拟go get –v 的操作

image

但默认因为找不到git而报错。 解决方法如下:

http://git-scm.com/downloads下载对应平台git

在LiteIDE的查看->编辑环境变量中, 修改PATH, 加入git路径。例如

PATH=c:\mingw64\bin;%GOROOT%\bin;c:\Program Files (x86)\Git\bin;%PATH%

再按下Get键, 第三方包就会自动更新了

posted @ 2014-11-27 17:19 战魂小筑 阅读(5076) | 评论 (2)编辑 收藏

Unity3D引擎开发2D游戏的介绍很少, 本文以笔记方式进行介绍

 

工程参数设置

image

在创建时, 记得将最下边的模式设为2D模式

摄像机参数设置

image

这里需要设定的项:

Z设为-10, 如果设为0, 将不可见物体

ClearFlags设为纯色, 因为是2D游戏, 所以无需默认参数的天空盒

Projection设为正交投影(Orthographic), 这是相对于3D的透视投影的

Size根据你的设计期分辨率的半高度来设定.比如设计期, 我们以iPhone4的分辨率(960*640)为设计分辨率, 那么Size就设为640/2=320

 

精灵帧的导出

U3D原生支持对纹理Atlas的切片以制作精灵帧, 是通过SpritePacker来做的, 不过介于TexturePacker的强大合并及纹理分布优化, 这里我们还是以TexturePacker来做例子.

TexturePacker 官方网站: https://www.codeandweb.com/texturepacker

image

将需要合并Atlas的图片拉入TexturePacker, 然后参考上图, 设定描述文件格式为Unity3D. TexturePacker将为我们导出一个png的纹理及一个txt格式的文本. 这个文本内部格式是json, 描述每个精灵帧在原图Atlas的信息

设定纹理对应像素尺寸

image

点击导入到U3D的png纹理, 在Inspector中奖Pixels To Units 设定为1

默认这个值是100, 代表一张100宽100高的纹理在U3D中只有1个单位大小, 设为1后, 就是传统2D引擎的, 纹理与屏幕分辨率对应模式

转载, 请注明http://www.cppblog.com/sunicdavy 战魂小筑

转换TexturePacker导出格式到Unity3D精灵帧格式

https://github.com/autolame/TexturePackerExtended下载一个Unity的扩展, 并甩到工程Assets中导入

image

在刚才使用TexturePacker导出的txt格式文件上点击右键, 选择Process to animated Sprites

这种导出法, 适用于以原始单图片中, 以图片正中心为原点的序列帧

image

之后, 将Atlas小箭头展开的序列帧拉到场景中, 就可以预览动画了

posted @ 2014-10-10 22:30 战魂小筑 阅读(4119) | 评论 (0)编辑 收藏

最近看到一个关于vs的lua调试插件, 装了vs2012试了下, 忍不住发此文总结下lua各种调试工具

Decoda

    这是现今地球上调试lua5.1最方便的工具, 没有之一. 强大的注入式调试, 性能极高.支持 挂接进程, 变量展开, 断点等各种日常所需.

早期的Decoda是收费工具, 因此质量非常高.

    Decoda现在已经停止开发并开源了, 调试lua5.2会crash. 源代码可以作为一种技术参考, 很多dll注入修改技术, 灰常牛X

image

LuaStudio

   比较优秀的调试工具(因为收费), 可以调试lua5.1/5.2, 界面属于vs2008类型, 土豪可以考虑买几套试试

 

ZeroBrane Studio

对lua5.1支持较好, 5.2也能调但偶尔还是会crash, 基于远程调试方式, 所以性能略低.

RemDebug

没有IDE, 纯命令行方式调试器, 但因为简单, 所以可以参考后写一个自己的程序内建调试器

Babe Lua

把这货放在最后是有原因的, 还记得那句老话: 老外一开源, 我们就有自主研发了, 对的, 这货一定是参考了Decoda的代码后搞出个vs的插件来, 虽然不收费, 但是不提下参考对象的行为还是值得批斗的. 这货在中文博客上说, 不支持挂接到进程(Decoda支持), 不支持64位调试(LuaStudio支持), 调试30~50次偶尔挂1到2次. 哎, 毕竟只是代码搬运工, 不生产代码.

这货装上, 能用, 调5.2是不行的, 5.1比Decoda方便点, 毕竟vs支持悬浮显示变量.

 

说了那么多, 其实对于lua5.2版本的调试, 还是没有免费的比较合适的方案, 如果实在想调试, 还是可以参考下RemDebug的原理及lua官方调试文档, 自己通过c api调用写一套适合自己的远程调试工具. 其实没有多复杂, 但总比不调试的好微笑

posted @ 2014-09-28 15:19 战魂小筑 阅读(15303) | 评论 (7)编辑 收藏

感谢这位的博客提供的解决方法

http://www.lszhang.com/topics/git-push-%E6%97%B6%E5%87%BA%E7%8E%B0-remote-fatal-early-eof-%E9%94%99%E8%AF%AF

 

修改 GIT 的本地 config 文件,在 core 中加入:

compression = -1

这里是在clone方处理

windows git目录在c:\Program Files (x86)\Git\etc\gitconfig中

 

其他辅助方法参考http://git.661346.n2.nabble.com/Large-pack-causes-git-clone-failures-what-to-do-td5481488.html

git repack --max-pack-size=100m -a -d

posted @ 2014-05-29 14:30 战魂小筑 阅读(34190) | 评论 (0)编辑 收藏

Cocos2dx的作者王哲来到公司给大家做了一场技术答疑会

以下是我及我们项目组的一些Q&A

1. Cocos2dx 3.0版本在引擎退出时, 会有内存泄露

我:本来以为这个在rc1版本中发现的问题会在final版本中解决, 但实际上还是没有解决. 本人使用的是Windows下的VLD的内存泄露检测, 多年来这东西一直没有误报过, 虽然这个泄露不是很大, 但会干扰在这引擎上开发的逻辑的内存泄露查找

王哲:Cocos2dx的内存泄露测试是在XCode下进行的, 借助mac平台的工具来做的, 他说, 虽然操作系统会在进程结束时会自动回收, 但还是会在patch版本解决这个问题.

2. Cocos2dx 3.0 中的getInstance设计问题

我:3.0中的singleton是使用自动new的方式来实现的, 对象都是分配在堆上, 而不是栈上. 这种方式的特点就是在singleton为空时, 自动new出来, 从而让上层保证使用简单. 但是弊端就是前一个问题说过的, 如果处理不当的话, 会导致内存泄露.

3.0中的Director在析构时, 会先删除Configurator的一个配置类, 但是, Renderer在析构时, 又会使用到这个配置类, 调用配置类的单件, 从而导致配置类重新实例化. 之后, 就没有管理配置类的析构, 所以发生内存泄露. 我尝试修复这个问题. 但是因为getInstance本身的设计弊端,导致拆东墙补西墙, 东墙又倒掉的问题.

王哲: 已经发现这个问题, 会在未来版本加以修正

3. 为什么不自带更新系统

王哲: Cocos2dx引擎一开始设计是偏重于渲染器, 所以包括网络及其他部分都是属于附属. 现在开发团队只有10个人, 所以精力也是有限的

另外, 每个公司和个人对更新系统的需求都不是一样的. 不过引擎会在以后版本中的ResourceManager提供一些类似的功能

4. 帧率控制器

我: 游戏一般分为固定帧率和可变帧率两种更新方式. 前者在早期的日本游戏中常见, 后者是3D游戏及后期的游戏中用的比较多. 在U3D中分别使用FixedUpdate和Update两种方法来实现类似的功能. 但是在Cocos2dx中没有实现类似的功能.

王哲: Cocos2dx里因为要处理一些复杂的情况, 比如接听电话之类的, 所以这里仍然使用可变帧率来做.

我: 虚幻里有一套更新算法, 在帧率足时, 击中处理一些垃圾回收, 内存释放等耗时操作. 但是超过预设的阀值后, 停止占用帧更新时间, 留给逻辑足够的更新时间. 但是没看到Cocos2dx内使用这种算法

(其实王哲应该没听懂我说的意思)

王哲: 我尝试在3.0的渲染器中支持多线程, 但是在某些情况会出现crash, 而且这种技术的加入会提高引擎的门槛, 所以未来会根据实际需要加入.

5. 为什么不统一setResourceRootPath/setResourceDirectory 的接口?

这是我们项目的一个兄弟做下载更新时, 碰到的2.0中的一个问题. 王哲表示3.0已经做了1年半, 2.0的东西都忘记了, 但是在3.0中是统一的接口.

6. 如何看待云风喷cocos2dx?

这是我们项目的一知乎粉提的问题. 王哲说, 云风对C++很反感, 所以自己的代码及项目大部分都是C. 因此对cocos2dx这种C++引擎肯定会有些反感. 但是cocos2dx的使用率很高, 不能因为一两个大佬的意见而改变cocos2dx本身的一些优势

7. SpriteFrame和纹理的释放问题, 为什么不使用智能指针?

王哲: 我做过一个测试, 智能指针在移动设备上跑的速度肯定是要慢于retain/release这种手动方式, 所以依然在3.0中采用retain/release方式.

我: 我们有某些资源需要常驻内存, 但是全局方式的SpriteFrameCache和TextureCache会导致这个问题很难解决. 能否提供分组资源管理概念

王哲: 这个修改其实没什么难度, 论坛里也有很多建议, 我们会考虑在新版本支持这些功能

8. Scene的接口不统一, 用错还会crash

王哲: 这个问题确实存在, 我们会加以修正

9. 为什么要对STL进行一些包装, 而不是直接使用?

王哲: 因为要适用于retain/release模式( 此时, 我终于发现我们为什么会出现第七个问题了)

10. string为什么需要一种垃圾回收机制来进行回收, 而不是直接用string?

王哲: 这是一个历史遗留问题, 为了兼容objc版本的移植及风格

 

其他的一些信息

CocoStudio是使用WPF写的, 底层使用P/Invoke与C++引擎层进行交互. 有人提出这个编辑器要开源么, 作者表示后期会考虑的, 但是因为代码很乱, 所以一开始没有考虑开源

本人感受, 微软的一切开发工具及代码的东西都是按商业模式做的, 根本不考虑开发者的利益. DX7到DX11, 说好的COM兼容, 最后改的一塌糊涂. MFC那么老掉牙的东西, 到VS2013都还在更新, 这不是祸害群主么. XNA退不起来, Silverlight干不过Flash. 更别说乱的一塌糊涂的WP, WindowsRT, WinPhone. 对于VisualStudio来说, 这是地球上做的最好的编辑器, 保留这个足矣, 但是也别太依赖即可. 拥抱开源, 珍惜生命, 远离微软

WP版的Cocos2dx支持是微软设在西雅图的一个叫OpenTech的公司来做的, 并非王哲团队做的. 而且DirectX现在变成小众API, 因此这公司采用AngleProject来用OpenGL模拟DirectX的接口, 当然性能上肯定有很大的损失

最后附上王哲团队的照片以鉴真伪

image

posted @ 2014-04-25 18:35 战魂小筑 阅读(6713) | 评论 (5)编辑 收藏

lua5.2后, 官方建议大家放弃module/package机制, 这套机制对于使用者来说是方便的, 对于module的编写者简直要抓狂, 所有module后的函数对_G均不可见, 还要一个个手动在module前转成local调用. 相当反人类. 官方建议大家手动实现package机制. 本博客之前有实现过, 参考http://www.cppblog.com/sunicdavy/archive/2013/12/10/204696.html

由于要使用protoc-gen-lua, 这东西生成出来的lua依然使用官方的module/package机制. 对于游戏项目来说, 想进行一些自定义读取, 加密等, 就变得不可能. 幸好官方在扩展上支持的还是不错的.

参考lua5.2的官方文档http://www.lua.org/manual/5.2/manual.html#pdf-require

require时, lua会自动根据一定的搜索规律找到加载代码的方法. 这个方法定义在package.searchers这个数组中. 一共有4个加载搜索顺序

1. preload, 对已加载的module进行直接返回, 对应package.preload[modname]

2. lualoader, 对lua文件进行加载, 搜索路径为package.path

3. cloader, 对lua标准dll进行加载, 搜索路径为package.cpath

4. croot, 官方文档说的是all-in-one加载器, 感觉很神奇, 感兴趣可以自行参考源码

那么, 如果只需要自己的加载器, 只需要这样做:

  package.searchers[2] = function( name )
        print("try to load", name )
    end
    package.searchers[3] = nil
    package.searchers[4] = nil
    
    require "libtest"
    只保留preload功能, 然后将第二个加载器换成自己的加载函数, 第三,第四直接屏蔽

posted @ 2014-04-16 20:29 战魂小筑 阅读(7416) | 评论 (0)编辑 收藏

用惯了hg的便捷, 换做git感觉确实有些不人性化. 但是比起hg分支的反人类,git的强大还是值得我们迁移的

这里使用TortoiseGit Windows客户端+Git-1.9.0-preview20140217.   不是使用msysgit, 理论上差异不大

网上大多数文章都介绍如何和github进行远程拉取. 我想说, 我们开发客户端, 用github资源就是个大问题, 还更别说直接开源…

 

和TortoiseHG一样, TortoiseGit也有一样的远程P2P方式拉取的方法

只需要在一个代码库上右键菜单中选取Daemon即可

image

这里的提示告诉你, 这样的拉取无需任何的权限. 其实本地开发, 这不存在, 要的是方便, 所以果断Proceed

 

image

本图表示, 你已经对外开放了你指定库的权限

 

局域网的其他人选择一个空文件夹, 然后选择Clone

image

注意, 这里有巨大的坑, daemon中只告诉你git://你的IP/  但是实际拉取会出错. 正确的URL格式必须是

git://你的IP/.git

表示访问的git的目录!!

posted @ 2014-04-02 14:17 战魂小筑 阅读(10571) | 评论 (0)编辑 收藏

这里使用的golua版本是https://github.com/aarzilli/golua

按照作者的安装方法在天朝行不通的, 原因你懂的

因此进入这个链接, 点击右边的Download ZIP下载快照包

下载好后放到你的GOPATH指定路径, 整理路径如下

github.com\aarzilli\golua\

其下的目录如下

example\
    lua\
    LICENSE
    README.md
    TODO

然后准备lua5.1的开发包

lua-5.1.4.tar.gz

还有2个第三方依赖包

readline-6.2.tar.gz

ncurses-5.9.tar.gz

直接configure –> make install 装好

 

go env确认你的GOPATH已经指向你的开发目录

golua默认使用cgo进行编译, 可能会报错, 修改lua.go的cgo定义如下

#cgo linux,!llua,!luaa LDFLAGS: -llua -lm –ldl

进入$GOPATH\src\github.com\aarzilli\golua\lua

执行go install

完成

posted @ 2014-03-18 12:51 战魂小筑 阅读(2238) | 评论 (0)编辑 收藏

仅列出标题
共26页: 1 2 3 4 5 6 7 8 9 Last