首页 > 代码库 > 量产化游戏
量产化游戏
量产化游戏
----- 程序员的殿堂之路
----- 作者: 欧阳江平
QQ:75260062
前言:
程序猿 关于两个1的问题?
两个1放在一起,大家都会说这是"两个"1,但如果把一个1放到眼睛前方,一个1放到脑袋后面,
大家会说前面一个1,后面一个1。我们发现,说法不一样了,应为理解的角度不一样了。
概念最终的定义也不一样了。
ok,一切都从这么细节的地方出发了。
第一部分: 问题的提出
1. 像工厂一样的做游戏?(都喜欢做的事,扒皮,效果却不尽如人意)?
2. 能量产化到什么程度?
3. 以下游戏的共同点在哪里?
RPG=Role-playing Game:角色扮演游戏
ACT=Action Game:动作游戏
AVG=Adventure Game:冒险游戏
SLG=Simulation Game:策略游戏
RTS=Real-Time Strategy Game:即时战略游戏
FTG=Fighting Game:格斗游戏
STG= Shooting Game:射击类游戏
FPS=First Personal Shooting Game:第一人称视角射击游戏
RCG=Racing Game:竞速游戏[也有称作为RAC的]
共同点,也是我们的目标
1.都需要协议通信(二进制,字符串xml/http)
2.都需要数据库来持久化数据
3.都可以有appframe框架
4.是否都会有任务,技能(所见即所得),背包,移动(视野对称)等基础的操作单元呢?
5.是否还有其他的共同点呢?
6.一些系统是否能够独立出来能?比如邮件?比如类似大富翁里面的那个跳跳棋?
思维发散开了后,发现我们到了另外的世界,有很多的东西可以做。这个世界需要我们去搭建,
需要有步骤的,持续的,耐心的,细致的来搭建,一步一个脚印。
ko,已经有了足够可以做的东西了,做完这些,如果我有个gameframe.sh这样的一个脚本,能够执行一下。
基本的游戏框架就有了,并且可以接任务,移动,打怪了。接下来你知道自己要做啥了。
下面要讲的是我们如何达到这样的一个frame.
第二部分各阶段思想层面的人会如何去实现
游戏的实现和理念和程序员的认识有很大的关系,各层次的思想决定了这个框架的搭建和实现细节,现在就以下三种阶段来做说明:
1. 暴走阶段evs
Evs 是我早期总结和写的一套框架,这个框架如下:
这个东西做起来就很传统,所有的进程都围绕共享内存来做逻辑。一个逻辑模块可以开很多进程。我们一般都开128个进程,性能没有问题。企鹅同屏可见,单服2-3W在线。在魔方工作室这套东西用的比较多:QQPet,TNT,洛克王国,Q宠大乐斗
2. 像神一样tfs4g
腾讯框架系统(用c实现的)
一、TSF4G的层次划分
说明:
OS:操作系统
PAL:平台无关层,支持夸平台
COMM: 通用数据结构和算法、模块约定(例如ERR 宏的分配)等
TDR:数据表示层
TLOG lib:日志lib
TMNG lib:管理lib
TSEClib:安全lib
TBUSlib:进程间通信lib(例如1.1.1.1是一个服务器的id表示)
TSF4Gbase lib:tsf4g的底层库的集合,包含其下层所有的库以及tapp进程框架库等
TLOGService:日志服务
TMNGService:管理服务
TSECService:安全服务
TMSGService:消息服务
Apps:领域应用
实用范例:
一个进程架构的xml式配置:
进程和进程间的描述关系tcmcenter.xml(展示),这个关系另外一个名字就叫”架构”
一个数据协议的xml配置:proto_cs.xml(展示)
Tencent Service Framework/For Game
说明: tfs4g是设计和想法都很到位的一个应用体系,这里的思想层次,已经跨越了单个应用架构的想法,而是从里到外都用了自己的一套想法。和操作系统的想法很接近。其中每个服务器都用点分十进制表示,通信都依赖这个唯一的id.比如6.10.8.8
AddrTemple="region:6.world:10.function:8.instance:8"可以解析成:大区6上面的世界10上面的zone服务的第八个zonesvr
这个框架拉过来后可以直接写逻辑,其中协议,数据库操作和各个模块都用tcm管理中心生成。相关通信等都不用管了。内存实用的共享内存。主要是用单进程的概念做无阻塞的操作。当然torm数据库操作是多进程的模式.
协议在这个框架里面做的非常到位,只一个xml的描述就做到了protobuf的功能,并且比protobuf的效率高了一个数量级。自然支持协议的增量更新。客户端和服务器的协议不需要保持高度的统一。这样的对于开发的灵活性提高到一定的层次。
TFS4G哪些游戏公司在用?
1. QQ寻仙
2. QQ飞车
3. 轩辕剑
4. 斗战神
5. 御龙在天
6. 零纪元
7. 梦三国(类dota游戏)
以及其他一些我还不知道的
3. 超神的erlang
Erlang的起点就改变了我们的编程语言。这个起点就到了神的级别
我们需要多进程,erlang天生支持多并发
我们需要共享内存,erlang有ets并且进程dump时能够被扑捉并把数据回写
我们需要持久化,erlang给了我们dets(虽然不主流,但是也是套解决方案)
我们需要链表等操作,erlang给了我们lists等各种类似std的东西,而这种是这门语言的基础,让我们不会像c++下的std的东西一样喜欢,敬畏,但最终还是用自己写的觉得安心.
我们需要进程间通信,这个erlang太能给了,call ,cast,timer等我们已经熟悉的不行了。
第三部分 正在做的erlang框架
1 我们还需要啥,是的我们还要
1. 类似protobuf,tfs4g一样的协议组件,这样不用每次都写一个协议的时候都
要等客户端和服务器都去写协议解析编码和调试是否对齐等重复的工作.并
且能做到增量更新
2.需要通用的mysql数据库来持久化数据,并且自动化操作相关的数据,这里我
有个很好的原型gen_cache.
3.我们需要一个appframe框架,输入一个名字,应该就能生成启动的应用
4.我们可以有任务,技能(所见即所得),背包,移动(视野对称)等基础的操作单元(需要在项目中去积累,并沉淀下来)
2.我们已经做了的
Edr: erlang and as的协议xml解析工具.
Ecache: cache层和数据库链接的一个组件,我们用工具生成map_data所需要的
record和record_type,这样ecache 的协议xml也自动能形成自动化流程了
新系统的好处点:
1. 协议的xml描述,
协议描述简洁,注释和协议一体化。不需要再写协议文档了(解决了协议和协议文档描述分开的麻烦)
2. 协议的唯一性
写一个协议,客户端和服务器都能公用,服务器和客户端不在需要写解析协议的过程,并且完美支持复杂协议
,现有的复杂协议,可能要写100多行的解析函数,还的分读写两份,调试的代价也省下来了
3. 协议修改的方便性
协议指定完后,如果客户端和服务器需要调整字段的大小,只需要改下xml描述的协议类型,编译就可以,都不需要
去查协议并还的要客户端配合一起修改。
4. 数据库操作的简单化
当一个结构体需要保存在数据库中的时候,以前都需要写类型和对应的mysql语句。
现在这些你都不要做了,你只需要操作内存就自动会完成插入,修改,查询等操作。
程序中,代码已经不会涉及mysql任何操作语句。不再担心,我结构改后,自己的逻辑和
对应的表字段还的一一去对一遍,还的担心顺序,字段类型,字段大小等各种纠结的事了.
5. 策划配置数据的完美兼容
现有的配置数据,需要配合erlang的语法,来填写配置数据,导致策划时常忘记各种符号,而导致匹配错误。
比如:技能数据{1,2,3,4,0,0,0} 这个数据如果少填了一个0,就会导致程序的崩溃。
新的方案已经完全避免了这种情况
并且支持策划表直接导成data_xx.erl的结构性数据文件。
这样策划在改数据完数据后,策划自己reload,就可以把数据加载到内存里面。无缝支持策划调试数据
这个过程不需要程序参与。不用程序去关闭程序,然后把玩家踢下线,然后在重启充许,然后策划在进入测试。
6. 以上是起步式的完美呈现,接下来是一些模块化的经典处理方法
我们正在做的
写一个客户端和服务器可以运行的demo,demo已经写完
我们将要做的
技能: 区别于现有的技能实现,技能实现之后可以支持,回合制,arpg,类dota,LOL等技能.(可以说说实现)
状态: 支持状态互斥表,同等级顶替,时间延续,互斥,0.5ms跳变等几乎所有的状态关系和极高的灵敏度.
物品: 良好的物品效果支持,比如,使用物品,加血,加魔,加状态,变身等逻辑的支持.
任务: 任务的三大单元 正在运行中,放弃的,已经完成的。前置任务等
视野对称:地图移动,最精华的东西,能做到1W人在同一个9宫格里面,而程序完全没有压力(属于原创)
以上的预研做完后,我们需要去做一款足够NB,复杂的rpg游戏,然后把
这个框架稳定下来。
旧新系统的对比:
功能 现在的方式 新架构的方式
协议设计 服务器用erlang写一份 自动生成
协议设计 客户端用as写一份 自动生成
协议调试 目测字段类型匹配 无需调试
协议调试 目测字段长度匹配 无需调试
协议调试 手动写调试代码 提供函数打印协议包数据内容
协议修改 客户端服务器要人工修改 一键搞定
协议复杂度支持 能把程序员给写死哈 无需写编解码,天生支持无限复杂协议
协议规范 靠人力去规范 自动格式化,绝对美观
逻辑支持 各种奇葩 统一的风格,清晰的逻辑
数据库支持 需要写各种sql语句 操作内存就是操作数据库,看不到sql语句,被ecache封装了.
数据库加字段 各种地方修改 无需改动.编译即可用
策划表支持 每个表都要写各种导表逻辑(hph) 工具自动导出,无需写任何东西
策划表支持 各种erlang语法的规范 无规范,一个字段一个值。清晰简单
策划支持 修改数据后,需要程序帮忙导入 策划gm指令热加载(修改表字段需要冷启动)
以上是已经做到的功能,并且有demo测试过。就是说可以用到项目级了.
以下是将要做的逻辑大块:(一下逻辑以前都在c下实现过。所以都是可行的。)
技能: 技能的基本分类常用的分 普攻,吟唱,引导,定时。技能效果,比如加血,加魔,加buff,debuff,变身等。这些可以做成很通用的配置。和状态系统配合能完成所有回合制,arpg等技能的实现。LOL的技能,是在这个基础上做一个分支逻辑。实现特殊技能功能,做到特殊技能,有共用的配置,也有自己独立的配置。完成一个游戏产业的技能布局。
状态: 状态主要分两块,1个是状态的功能,比如1秒减血,每秒递减移动速度。这个效果逻辑。2个是状态的互斥表,就是说状态和状态直接的叠加,顶替,替换,互斥等逻辑。能实现现在能看到的所有的状态表现。
地图: 地图不管是9宫格还是4宫格实现,我的唯一目标就是实现,1w人站在同一个9宫格内,还能移动自如。是的,就是这么严格的要求这个处理方式是要用对称视野的方式来做。
怪物: NPC是怪物的一种,应为NPC可以杀红名的,npc的刷出,是服务器通知客户端的。而不是客户端主动去读配置,这样做的好处是。服务器可以做很多灵活的事,并且控制npc的动态显示。
物品: 物品同样需要一个效果字段case。
任务系统: 任务系统一定不要和地图绑定,任务的接取都是有任务自己配置的,比如接取的限制条件,前置任务,后续任务。都由任务自己决定。然后npc表决定任务显示在哪个地图上。任务身上的任务数据,就是三大块,当前,完成,放弃。
以上,系统出来后,都很独立,并且可重用性非常高。
做到以上效果,不再会有扒皮之后的痛苦了。
阶段性总结:我们将引领公司erlang领域的二次技术革命.直接把公司的技术带到顶级俱乐部中
轻松一刻: 两个大师的趣味点(进距离接触c++之父Lippman和侯捷)
侯捷: 深入浅出MFC作者,人生轨迹是,从写代码到写书
c++之父stan Lippman: 写代码,顺带写书,再继续写代码,现在还在写代码.
Lippman预言的下一代大规模编程的方向,是细胞式编程。
这个有点抽象,但肯定会是个翻天覆地的变化。
两个大师的出路:一个最后去做管理了,一个还在写技术哈.
自己的路,大家自己看着办哈
第四部分点点的总结
erlang的多进程原子数据访问方法;
1.ecache可以是多进程,多个ets
2.每个ets可以对应1个进程和多个进程.
3.当一个ets对应多个进程的时候,一定是一个数据节点对应且只有一个写进程
4.例如:ets_player,每个玩家上来后建立一个进程,单个用户进程维护一个ets_player上的节点的修改,另外一个ets_player_tick进程,来轮寻超时的时间节点,并处理相关的到期时间节点.
我们来看这个可操作的流程推演:
原子性操作的一个应用,比如 牛头人A放了一个大招打B用户
接下来我们看看这个流程是否能支撑住,
A进程调用B进程的过程
1. A进程发送atk包,服务器通知周边玩家开始表现放招了
2. A进程发送hit包,打到了B用户,A进程中校验技能序号,施法距离,持续时间,检验过了,说明这是个合法的目标.
3. A进程开始走攻防流程获取A/B(从ets里面读出来)的实时的攻防数据结构,并代入公式,算出伤害。将伤害传入B的进程进去扣伤害,如果扣成功,就减血,和处理死亡的流程,并通知周围玩家,扣失败,就返回攻防流程结束。
4. 总结: 流程能通,但写代码时需要非常注意,B进程不能调用A进程, 这个无法保证,应为你的推演中A已经call了B,没有理由能保证B函数里面不call进程A
改进下:
加入一个攻防进程C来调用A,B. 并且A,B不会调用C,这个是可控的。
我们发现问题清晰出来了。就多加个或加一组C进程都是OK的。
再看一个复杂一点的,二阶原子操作。比如
打死之后,扣钱,扣物品,扣不到就不能打死。(这个需求有点怪,不管他,我们要的是这个流程)在扣hp的时候,C进程是call到了B进程里面的,B进程自己能扣钱,并且call到物品进程里面扣物品,
如果扣不成功,就返回false,B进程把钱加回去,把hp也加回去,最后返回失败.
这是一个流操作过程,如果这时停电了,最多就是B进程的钱没加回去。这个是可以接受的,并且通过日志可以做一些运维上的补偿。
实际中不要去弄三阶原子操作
多进程几个典型的架构(QQGame,洛克王国)
1.QQGame 无公享数据多进程,每个房间一个进程,100个桌子,每个桌子4个人,一个进程400人.
2.QQPet/洛克王国,有共享数据多进程,多进程文件锁,同屏2-3W人.
单进程几个典型的架构(御龙在天, 零纪元)
1. 御龙在天: 核心进程无锁,无异步访问,一个区9个国家,每个国家3千+在线(测试能上6千人),一个区就是3W人在线.
2. 零纪元:简单的单进程,支持无限的复杂的逻辑,压力测试单服能上7千
我们系统的瓶颈在哪里?
系统的4大瓶颈:1.cpu 2.内存 3.io(这里指网络io,不指磁盘io) 4.应用同步和异步.
erlang给我们解决了cpu多核利用的问题,64位机器的普及,给我们解决了内存的问题。同步和异步以及加锁的问题,也给erlang给解决了。剩下网络io瓶颈了。一个服监听一个端口,一个端口最大能处理4w/s包左右的处理量。这个数据的解释是100个人在9宫格里面每秒走动一下,或每秒说一句话,这样的广播消息就是1w条。所以这个瓶颈很容易就达到了。
ok,一切都围绕这个点来优化.
修改点1: 移动不要走一段发个数据包,而应该把一条足够长的路径发给服务器,而且客户端走动时,服务器也要走动。
这样可以节省到原来至少1/10左右的移动包量.
修改点2: 同屏可见的处理按目标的优先级来划分,最多能看到200个对象的情况下,能让服务器在玩家任何行为下,保证客户端不卡.能节省的包量在几千人在线的情况下得到几个数量级以上效果。
修改点3: 下行包的合包逻辑一定要做,保证每秒10/人个包左右的下行量,尽量用足一个MTU的大小
架构的思想是为需求服务的,也是为容易写代码而服务的,更是为可重用性服务的.
开源的几个协议组件为啥不用?
1. json轻量级的字符串协议.
致命伤: json的协议解析是递归的方式,并且是字符串解析。每秒好像就2-3千的效率。后来我们把这个解析规则改过。效率提升了几倍,但还是达不到
要求.
2. protobuff 很好的c++和各种语言的解析
致命伤: 会把简单的事,复杂化。本来一个结构体搞定的事,它加了很多
get/set等附带的方法,把逻辑弄复杂了。另外我们大部分人,都不会标准
编程
3. xml 协议,游戏里面做xml协议,能做成很复杂的协议。
如果flash也直接用xml协议规则解析二进制,你会发现,效率也提升不上
来。
游戏协议有他自身的特点,很重要的一点就是海量的数据包,复杂的数据包协议。
一个比较好的东西,大乐斗正在用的一个东西
轻量级的db key-value键值队的一个数据库。数据库读写非常快
TC(Tokyo Cabinet) 和 TT(Tokyo Tyrant)
世界唯一id的组成规则:
服务器id(short)+时间(int)+增量(short).
可以保证所有的服务器的id都是唯一的。
数据备份的重要性,
数据备份一定要本机和异机一起备份,防止磁盘损坏的情况下,数据无法恢复的问题。腾讯在汶川大地震的时候反思了自己的备份措施。把核心数据都做跨省份备份。甚至QQ用户数据进行了银行级别的保护性备份(能抗10级地震)
正在发生的危险:
我算是第二代程序人,我所迷失的东西,是对操作系统的详细认识。
虽然也看过一些非主流的系统代码。
第三代程序人还在迷失更多的东西。
现有的东西,使我们越来越迷失对底层东西的求知欲。
结束语:
结合erlang可以出一个到至今为止我能看到的最好的架构和框架体系
本文出自 “量产化游戏” 博客,转载请与作者联系!