WebGame游戏开发现状浅析

(一)产品设计

    1)新手设计无脑化、傻瓜化
        1. UI操作简单、直观、便捷;
        2. 短时间使玩家角色获得快速成长;
    2)针对付费的设计
        1. 第一时间让玩家产生付费的冲动;
        2. 付费点遍及游戏各个系统;
    3)内挂设计,减少外挂影响
        1. 自动寻路、自动拾取物品、自动战斗、自动补充HP/MP等;
        2. 自动换装(或者提示玩家换更强的装备);
    4)提供玩家最大的满足感和爽快感
        1. 更好的游戏代入:游戏题材的选择,游戏世界观的设计等
        2. 深挖数值,但又不能使游戏系统过于复杂,即玩家能快速理解游戏玩法内容;

(二)技术研发

    1)提供跨服PK的功能,即不同大区的玩家能够同场竞技;
        技术关注点:不同大区的服务器是否部署在同一IDC?存储服务器数据分区部署 or 全Cluster共享?
    2)支持一机多服部署
        即同一台物理机器部署多个游戏世界
    3)形成一套核心研发机制和稳定的开发框架、基础库,保障核心功能快速复制

(三)运营推广

    1)快速开服,满足玩家“滚服”需求:《龙将》和《神仙道》做到了1天1服或1天2服,所谓“滚服”,即玩家会在不同服务器体验,目的是争取在新的服务器更高的排名和更大的满足感;
    2)开服第一周的收入是该服最主要的收入,也决定了运营商是否加大推广的力度;
    3)流量就是金钱,一般运营商的成本是每个人1-2元每人的流量成本;
    4)运营商可以提供机器,也可能让开发者自己租用机器和带宽,它只提供一个域名;

(四)其它

    1)核心玩家群特征:低粘性、高ARP值,即纯粹互联网用户,游戏只是其网络生活的一种典型应用;
    2)3–6个月完成一款RPG类webgame的全部开发,即正式付款公测;

WebGame游戏服务器技术要点

(一)服务器技术实现方案选择的问题?

(1)选择标准WebServer+CGI开发(偏轻)
【优点】
    1)快速开发:WebServer都是现成的,如:Nginx和Apache;CGI程序能也快速编程;
    2)灵活开发:整个后台服务可由多个CGI程序组成,一个CGI程序可以对应一项或多项业务功能,增加新功能时则增加新的CGI程序即可;
    3)不停机更新:部署新的CGI程序,不影响已运行的CGI程序;
    4)可适合处理SNS类玩家异步(离线)交互数据的情形;
【不足】
    1)CGI程序如果过多,可能会加大维护的难度;
    2)业务需求如果要涉及到多个CGI程序之间的通信,即有状态的关联依赖,可能会有较复杂的逻辑和可能的性能瓶;
(2)选择自定义通信服务器+GameSvr开发(偏重)
【优点】
    1)可应对复杂业务逻辑的处理,如:业务需求之间的关联依赖较深等;
    2)可轻松处理玩家之间同步数据的需求;
【不足】
    1)开发复杂度较大,需要较多的开发资源;

(二)游戏服务器Cache设计方案

【背景】
    1)游戏服务器cache数据可大大缓解数据存取时压力;
    2)多台分布式游戏服务器作Cache,可有效利用硬件资源;
【实现方案】
    1)基于共享内存的对象池设计;
【注意事项】
    1)数据一致性:对于SNS强交互类游戏,需要作多玩家修改同一数据的设计;
    2)数据同步的时机:根据业务数据的重要程度,分级设计同步时间,越重要的数据,同步时间越短;

(三)游戏服务器数据分类设计方案

【基本思想】
    把业务数据按重要程度进行分类,每类数据采用不同的存储和逻辑处理策略;
 
【应用说明】
    SNS类游戏需要重点考虑

(四)游戏服务器全局锁的设计

【背景】
    1)同一玩家数据会被多玩家修改;
    2)某一Cache数据会被多个应用修改;
【方案一】:热点数据分布在各个游戏服务器的Cache中
    1)数据被修改点(热点数据)设置一个全局Seq,如:玩家数据修改,则在玩家身上设置一个Seq;
    2)当Client读热点数据时,则直接返回数据给Client,并将Seq一齐带上;
    3)当Client写热点数据时,会在写数据请求里带上上次请求获得的该热点数据的Seq,热点数据的处理逻辑先比较写数据请求的Seq,是否与当前热点数据的Seq一致,若不一致(该请求来之前已被其它Client修改过),则有如下两种异步处理方案:
        1. 直接报错给请求Client,此时Client可能需要提示玩家重新刷新浏览器;
        2. 返回当前最新热点数据给请求Client,Client需要重新处理一遍之前的业务逻辑,再提交写数据请求;
    4)每次写热点数据成功后,热点数据本身的Seq加1;
    5)数据修改的逻辑统一在热点数据所在的游戏服务器处理;
【方案二】:热点数据集中在一个全局公共服务器的Cache中
    实现方法与【方案一】类似
【两个方案的比较】
    1)【方案一】:Cache分布在每台游戏服务器中,可以有效利用硬件资源,但SS交互逻辑复杂一些;
    2)【方案二】:可以减少一些SS协议的交互,但需要单独的全局Cache服务器;
【注意事项】
    1)需要分别考虑玩家在线和离线数据的修改;

 (五)如何有效利用机器的多核CPU

1)多个通信服务器+1个游戏服务器;

    2)多个通信服务器+多个游戏服务器;
 

(六)如何评估网络I/O的瓶颈

    1)网卡(1000M bit/100M bit)本身的极限处理能力:理论处理包的数量:网卡带宽[1000M bit]/(最小包大小[64Byte] * 8);
    2)游戏业务对包的数量较包的大小更敏感,因为每个网络包在CPU处理时,会产生IO中断,因此,常用的策略是,合并多个请求包为一个包,提高带个包的信息量;
 

(七)深入了解MySQL的存储性能

    1)Mysql5.5+InnoDB1.1;
    2)Mysql的Cache解决方案;
【声明:若有摘录,请注明来自http://gameislife.info/archives/109】

Nginx下用C/C++开发FastCGI程序

(一)关于环境搭建
1)分别安装Nginx1.08+FastCGI2.41,这个过程中可能需要安装pcre库;
2)安装C语言版本的spawn-fcgi-1.6.3;
3)安装C语言版本的fcgiwrap,这是不是必须,但它可以使应用程序像传统CGI的方式工作,即即时执行,即时释放;
(二)Nginx配置成FastCGI
location ~ \.cgi$ {

root cgi-bin;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/nginx/nginx-fcgi.sock;
rewrite (.*).cgi /$1 break;
fastcgi_index index.cgi;
include fastcgi.conf;

}

参数说明如下:
1. 【root】:为cgi程序存放的相对目录,即相对于Nginx的安装路径,我的Nginx存入在/usr/local/nginx/sbin下,则上述配置的cgi程序则存入在/usr/local/nginx/cgi-bin下;
2. 【fastcgi_pass】:cgi程序部署的机器IP和应用监听端口,此处也可以配置成unix本地socket,这里需要特别指出的是,用spawn-fcgi包装器运行的应用程序的监听IP和端口必须与这里配置的保持一致;
3. 【rewrite】:应用程序忽略.cgi后缀名;
(三)应用程序的工作方式
  • 传统CGI方式
利用上面提到的fcgiwrap作为默认应用程序用spawn-fcgi包装器在后台运行,这样它会把请求的cgi程序像传统的cgi那样执行,即当次请求执行完后,就释放掉,就是所谓的fork-exec模式;
  • FastCGI同步方式
自已编写的cgi应用程序直接用spawn-fcgi包装器在后台运行,这样它会像一个常驻内存的cgi程序;
  • FastCGI异步方式
1. 自己实现一个解析http协议的框架,并应用程序以so的形式在框架中运行,公司的qzhttp用这一原理实现的;
2. 修订spawn-fcgi源码,使之能支持异步消息通信;
 
(四)注意事项
      若应用程序使用shmget等函数操作操作系统的共享内存,则在用spawn-fcgi作为包装器启动应用程序时,需注意启动的权限,即-u 选项指定的用户即为共享内存创建时的用户,否则访问共享内存将为失败; 

《Lua游戏开发实践指南》读后感

书籍地址:http://book.douban.com/subject/20392269/

一句话点评该书:想用Lua作游戏脚本开发的同学值得一读!

(一)本书特点

市面专门讲Lua的中文书籍很少,窃以为,一方面可能觉得Lua比较简单,可深入讲的东西并不多;另一方面,说明Lua的开发者数量,(尤其是国内)还是一个比较小众的群体,出版商们也无利可图。回到这本书,它不同于一般纯粹讲Lua语言本身的书籍,如:《Lua程序设计》等,而是专注于讲解Lua在游戏领域的应用,从书中列出的几个例子来看,可以看得出作者在游戏行业是有比较丰富的经验的。下面摘取了书中的一些要点,与诸君分享之:)

(二)要点分享

(1)Lua在游戏开发的应用场景

1)编辑游戏的用户界面

我的理解:GUI图形绘制等基础功能还是要由宿主语言来完成,如:C/C++,Lua可以负责GUI的排版、布局等逻辑处理;

2)定义、存储和管理基础游戏数据

我的理解:游戏对象各配置数据如果比较简单的,均可以用Lua代码直接描述,用以代替文本文件,并省却解析的代价。复杂一点的,可以结合excel(保存为cvs文件),并利用Lua强大的文本解析功能来完成。

3)管理实时游戏事件

我的理解:玩家与游戏的交互都是通过鼠标、键盘等外设来完成,而在游戏设计中,普遍的做法是用事件机制来驱动完成。在Lua中可以通过定义LuaGrue函数与C/C++等宿主语言进行交互调用来形成一整套完整的事件系统。具体实现时,宿主语言实现捕获鼠标、键盘各类事件的底层接口,而事件触发后具体做什么,以及事件之间可能的依赖关系等逻辑,则由Lua来完成;

4)创建和维护开发者友好的游戏存储和载入系统

我的理解:在单机游戏中的游戏存档等数据,也可以很方便的用Lua来直接描述;

5)编写游戏的人工智能系统

我的理解:作者说的在AI中应用Lua,我觉得应用场景应该是在一些比较小的单机游戏中,而在大型多人在线的网络游戏中,恐怕还是需要性能更高的C/C++来实现。当然,作者也讲到,一个灵活的做法是,先用Lua来快速实现原型,遇到性能瓶颈了,再用C/C++来替换。

作者在讲到Lua在游戏开发团队中的应用分工时说,“程序员负责将Lua整合到游戏开发环境中,游戏设计师(策划)是脚本语言的主要使用者,因为他们和上层的游戏设计和数据直接打交道,美术师也会经常使用Lua,进行诸如界面布局、设计和3D场景中各种模型的摆放之类的工作。”看到这里时,不禁感叹,我们与国外游戏开发同行的水平差距:人家认为游戏策划和美术人员写脚本是理所当然的事情,而咱们这里,却认为这些不都是程序员该干的活吗?开发理念的高低直接导致了开发成果的巨大差异!

(三)本书的不足

(1)书中讲的Lua版本是5.0,而现在最新的已是5.2.1了,与C语言通信的API也有了一些变化;

(2)没有讲Lua的一个重要特性:协程,协程在异步编程中应用广泛,不但能简化传统异步编程的代码编写,而且还能有效的提高性能;

《程序员的职业素养》读书笔记

书籍地址:http://book.douban.com/subject/11614538/

一句话点评该书:Bob大叔的职业生涯经验总结,现身说法,可信可敬!

(一)专业主义

(1)“专业主义”就意味着担当责任;

(2)所谓专业人士,就是能对自己犯下的错误负责的人,哪怕那些错误实际上在所难免;

(3)你写的每一行代码都要测试。如果你希望自己的软件灵活可变,那就应该时常修改它!

(4)每个专业人士必须精通的事项;

1)设计模式:必须能描述GOF书中全部24种模式,同时还要有POSA书中多数模式的实战经验;

2)设计原则:必须了解SOLID原则,而且要深刻理解组件设计原则;

3)方法:必须理解XP、Scrum、精益、看板、瀑布、结构化分析及结构化设计等;

4)实践:必须掌握测试驱动开发、面向对象设计、结构化编程、持续集成和结对编程;

5)工件:必须了解如何使用UML图、DFD图、结构图、Petri网格图、状态迁移图、流程图和决策表;

(5)坚持学习。

不写代码的架构师必然遭殃,他们很快会发现自己跟不上时代了;不学习新语言的程序员同样会遭殃,他们只能眼睁睁看着软件业径直向前,把自己抛在后面;学不会新原则和技术的开发人员必将沦落,他们身边的人都是益卓越;

(6)业精于勤。

我常用的一个技巧是重复做一些简单练习:不妨早晚都个10分钟的卡塔吧!学习的第二个最佳方法是与他人合作。

(7)每位专业软件人员都有义务了解自己开发的解决方案所对应的业务领域;

(8)雇主的问题就是你的问题,每次开发系统,都应该站在雇主的角度来思考,确保开发的功能真正能满足雇主需要;

(二)说“不”

(1)专业人士敢于说明真相而不屈从于权势。专业人士有勇气对他们的经理说“不”!

(2)最要说“不”的是那些高风险的关键时刻。越是关键时刻,“不”字就越具价值。

(3)许诺“尝试”,就意味着你承认自己之前未尽全力,承认自己还有余力可施。如果承诺尝试,你其实也在承诺将改自己原来的方案。你是在承认原来的方案中存在不足。

(三)说“是”

(1)做出承诺包含三个步骤:

1)口头上说自己将会去做;

2)心里认真对待做出的承诺;

3)真正付诸行动;

(2)识别“缺乏承诺”的征兆,注意搜寻如下词语:“需要/应当”、“希望/但愿”、“让我们”

(3)真正的承诺是,你对自己将来做某件事做清晰的事实陈述,而且还明确说明了完成期限;

(4)如果你无法兑现承诺,那么最重要的就是尽早向你的承诺对象发出预警、越快越好,越早越好;

(5)专业人士不需要对所有请求都回答“是”。不过,他们应该努力寻找创新的方法,尽可能做到有求必应。当专业人士结出肯定回答时,他们会使用承诺用语,以确保各方能明白无误地理解承诺内容;

(四)编码

(1)编码原则

1)首先,代码必须能够正常工作;

2)代码必须能够帮你解决客户提出的问题;

3)代码必须要能和现有系统结合得天衣无缝;

4)其他程序员必须能读懂你的代码;

(2)如果感到疲劳或心烦意乱,千万不要编码。强而为之,最终只能再回头返工。相反,要找到一种方法来消除干扰,让心绪平静下来;

(3)结对是应对中断的一种好方法,另一种有帮助的方法便是采用TDD;

(4)广泛阅读包括软件、政治、生物、航天、物理、化学、数学等,能激发创造力:“创造性输出”依赖于“创造性输入”,创造力会激发创造力;

(5)软件开发是一场马拉松,而不是短跑冲刺。你无法全程一直以最快的速度冲刺来赢得比赛,只有通过保存体力和维持稳定节奏来取胜;

(6)管理延迟的诀窍,便是早期检测和保持透明;

(五)测试驱动开发

(1)TDD的三项原则

1)在编好失败单元测试之前,不要编写任何产品代码;

2)只要有一个单元测试失败了,就不要再写测试代码,包括无法通过编译;

3)产品代码恰好能够让当前失败的单元测试成功通过即可,不要多写;

(2)TDD是专业人士的选择。它是一项能够提升代码确定性、给程序员鼓励、降低代码缺陷率、优化文档和设计的原则。

(六)练习

(1)专业人士都需要借助专门训练来提升自己的技能;

(2)保持不落伍的一种方法是为开源项目贡献代码;

(3)我的理解:练习就像是学生时代的课后作业,日事日毕,练习内容可包括:经典算法、常用数据结构、设计模式等;

(七)验收测试

(1)做业务的人和写程序的人都容易陷入一个陷阱,即过早进行精细化;

(2)验收测试定义为业务方与开发方合作编写的测试,其目的在于确定需求已经完成;

(3)业务分析员测试“正确路径”,以证明功能的业务价值;QA则测试“错误路径”、边界条件、异常、例外情况;

(4)实现某项功能的代码,应该在对应的验收测试完成后开始;

(5)验收测试不是单元测试。单元测试是程序员写给程序员的,它是正式的设计文档,描述了底层结构及代码的行为;验收测试是业务方写给业务方的,它们是正式的需求文档,描述了业务方认为系统应该如何运行;

(6)整套持续集成系统应该由源代码管理系统来触发。只要有人提交了代码,持续集成系统就会开始构建,并运行所有的测试,测试结果会用电子邮件发送给团队所有人;

(八)测试策略

(1)开发小组要把“QA”应该找不到任何错误“作为努力的目标;

(2)QA在团队中扮演的是需求规约定义者和特性描述者;

(3)专业开发人员遵循测试驱动开发的要求来创建单元测试。专业开发团队使用验收测试定义系统需求,使用持续集成保证质量稳步提升;

(4)测试金字塔,由下至上的顺序是:单元测试–>组件测试–>集成测试–>系统测试–>人工探索式测试,其中单元测试是基石。

(九)时间管理

(1)站立会议的核心:

1)我昨天干了什么?

2)我今天打算做什么?

3)我遇到了什么问题?

(2)迭代计划会议用来选择在下一轮迭代中实现的开发任务;

(3)凡是不能在5分钟内解决的争论,都不能靠辩说来解决。这类争论依据的不是事实,而是信念。唯一出路是,用数据说话。

(4)用番茄工作法管理时间。(呵,没想到Bob大叔也用这个)

(5)睡眠的重要性怎么强调都不为过,保证7小时睡眠!

(6)要避免的行为:优先级错乱、死胡同、泥潭;如果你掉进入坑里,别继续再挖!

(十)预估

(1)专业开发人员不随便承诺,除非他们确切知道可以完成;

(2)专业开发人员能够清楚区分预估和承诺。只有在确切知道可以完成的前提下,他们才会给出承诺。此外,他们也会小心避免给出暗示性的承诺。他们尽可能清楚地说明预估的概率分布,这样主管就可以做出合适的计划;

(3)预估实践方法之三元分析法,即划为乐观预估O、标称预估N、悲观预估P,结果u=(O+4N+P)/6;

(4)预估实践方法之德尔菲法:一组人集合起来,讨论某项任务,预估完成时间,然后重复”讨论–预估“的过程,直到意见统一;

(5)预估是非常容易出错的,控制错误的方法之一是大数定律:把大任务分成许多小任务,分开预估再加总。

(十一)压力

(1)即使有压力,专业开发人员也会冷静果断。尽管压力不断增大,他仍然会坚守所受的训练和纪律,他知道这些是他赖以战胜由最后期限和承诺所带来的压力感的最好方法;

(2)在压力下保持冷静的最好方式,便是规避会导致压力的处境;

(3)避免压力的方法

1)不做不切实际的承诺;

2)让系统、代码和设计尽可能整洁;

3)在危机中依然遵守纪律原则;

(4)应对压力

1)避免孤注一掷的想法,鲁莽仓促只会把你带入更深的深渊。相反,要放松下来,对问题深思熟虑。

2)和团队、主管沟通;

3)坚信并依靠你的纪律原则;

4)结对寻求帮助;

(十二)协作

(1)不正常的团队最糟糕的症状是,每个程序员在自己的代码周边筑起一道高墙,拒绝让其他程序员接触到这些代码;

(2)专业开发人员是不会阻止别人修改代码的;期望拥有代码的是整个团队,而非个人;

(3)专业人士结对工作,是解决程序间合作的最有效方法,也是分享知识的最好途径;

(4)最有效率最有效果的代码复查方法,就是以互相协作的方式完成代码编写;

(十三)团队与项目

(1)形成团队是需要时间的。团队成员需要首先建立关系。他们需要学习如何互相协作,需要了解彼此的癖好,强项、弱项,最终,才能凝聚成团队。否则,那就是团伙,而非团队!

(2)最理想的团队是12人,7名程序员,2名测试人员,2名分析师和1名项目经理;

(3)创建有凝聚力的团队,然后不断地把新项目分派给他们,而不是围绕项目来构建团队;

(4)团队对项目更难构建。因此,组建稳健的团队,让团队在一个又一个项目中整体移动共同工作是较好的做法;

(十四)辅导、学徒期与技艺

(1)所谓大师

已经领导过多个重要软件项目的程序员。一般说来,他们已经拥有10年以上的从业经验,曾在多个不同类型的系统、语言和操作系统上工作过。他们懂得如何领导和协调多个团队,他们是熟练的设计师和架构师,能够游刃有余地编程。

(2)专业主义价值观和技术敏锐度需要进行不断地传授、培育、滋养和文火慢炖,直至其深植入文化当中;

【Bob大叔使用的开发工具】

使用Git来管控源代码,使用Tracker来管理Bug,使用Jenkins来进行持续构建,使用IntelliJ作为集成开发环境,使用XUnit来做单元测试,使用FitNesse来做组件测试

【附Bob大叔不完全Resume】

(1)1968年自学计算机编程,时年15岁,学习PDP-8汇编器、FORTRAN、COBOL、PL/1;

(2)1970年,没有上大学,被ASC公司聘为程序员,时年17岁;

(3)1973年,20岁与妻子Ann Marie永结连理,妻子那年刚18岁过去3天。Bob大叔深情地说:“38年来,她一直是我坚定不移的伴侣,是我的舵和我的帆,是我的爱与生命。我期待同她携手再走40年!”看来,一个卓越的程序员,也一定是一个深爱妻子与家庭的人!这点倒是与我不谋而合!大笑

(4)到目前为止,Bob编了42年的程序,与妻子育有二女一子!