AngryPowman

2013 年 9 月 22 日

追求“术”的人一辈子工作很辛苦,只有掌握了本质和精髓才能永远游刃有余。追求“术”的人希望走捷径,但做好一件事没有捷径,需要一万小时的专业训练和努力。——《数学之美》

传送门
泡面的个人Wiki : http://wiki.powman.org/pages/viewpage.action?pageId=4161547
Github : https://github.com/AngryPowman
宙斯的创世日记:http://gamediary.org
jira项目管理:http://jira.angrypowman.org

这是一个C++交流群(基本上是灌水的):这是一个C++交流群

TCP性能分析技术系列
TCP性能分析技术(1):Windows下TCP/IP协议栈的实现
TCP性能分析技术(2):TCP层收发包行为分析
TCP性能分析技术(3):数据接收端行为分析
TCP性能分析技术(4):数据发送端行为分析
TCP性能分析技术(5):数据发送端流程图
TCP性能分析技术(6):应用层通信流程
TCP性能分析技术(7):socket的数据发送与接收

进行中的开源项目
我的三年计划 : http://github.com/AngryPowman/chord [NEW]
Open source C++ libraries and frameworks for building game solution.
基于C++/QT网游 : http://git.oschina.net/AngryPowman/Coeus [HOT]
老肉鸡的代码公共库:https://github.com/zpublic/zpublic

暂时没空填上的项目
基于cocos2d-x引擎的mmorpg游戏 : http://git.oschina.net/AngryPowman/zeus-cocos2dx
基于HGE的MMORPG游戏:https://github.com/ZeusTeam/Zeus
C#/ZeusMud(Windows GUI游戏):https://github.com/AngryPowman/ZeusMud
程序员的在线交流平台:https://github.com/VNOC/vnoc
一款游戏编辑器:https://github.com/GenexTeam/Genex

大视野
知乎 Quora 果壳 创意气球

神奇的0x5f3759df

Quake-III Arena里面有一个闻名游戏界的开平方取倒函数:

/*
** float q_rsqrt( float number )
*/
float Q_rsqrt( float number )
{
	long i;
	float x2, y;
	const float threehalfs = 1.5F;

	x2 = number * 0.5F;
	y  = number;
	i  = * ( long * ) &y;						// evil floating point bit level hacking
	i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
	y  = * ( float * ) &i;
	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//	y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

#ifndef Q3_VM
#ifdef __linux__
	assert( !isnan(y) ); // bk010122 - FPE?
#endif
#endif
	return y;
}

第一次看到时着实被酷炫了一把,感觉很厉害,但却无法弄懂它的原理。这个函数的作用是用于对一个数开平方并取倒数,比用C库的sqrt实现(1.0f/sqrt(x))快了将近4倍。实现原理其实是牛顿迭代,也是平方根的一般算法,反复执行 y = y * ( threehalfs – ( x2 * y * y ) ); 其中y趋向于(1.0f/sqrt(x)),拿到的结果可以无限接近于我们想要的精度。

这个函数实现的算法被称为‘Fast Inverse Square Root’, 而它神奇的地方在于函数里面的实现采用了一个神秘的常数:0x5f3759df. 这个常数的来源目前无法被考究,也不能追溯确定这个常数的方法。

这里还有个典故,在Q3的代码公布,并且数学家Chris Lomont得知0x5f3759df这个常数之后,他通过用暴力搜索得出了与0x5f3759df非常接近、并且代入后得出的结果更加精确的魔数0x5f375a86,当然,实际上和0x5f3759df还是非常接近。

3D游戏引擎设计的作者David Eberly曾经发表论文解释了这个算法:
http://www.geometrictools.com/Documentation/FastInverseSqrt.pdf

不过最早还是Lomont在2003发表的:
http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf

而David Eberly最近的一次补充是在2010年。

See also: http://en.wikipedia.org/wiki/Fast_inverse_square_root

Mathematica求极限

x趋于0时tan2x/x的极限

In[3]= Limit[Tan[2 x]/x, x -> 0]
Out[3]= 2

某群以前设置过的累人的入群问题,但结果很明显不是无穷大:

x趋向0时x^7/(tansinx-sintanx)的极限

In[3]= Limit[x^7/(Tan[Sin[x]] - Sin[Tan[x]]), x -> 0]
Out[3]= 30

不过可惜大作业都是要写过程的。

苹果IAP安全支付与防范技巧

这两天我在筹备我们的游戏APP的内购,仔细考虑了几个付费安全上的问题。凡是涉及到付费的问题都很敏感,任何一方出现损失都是不能接受的,所以在这里整理一些支付安全的要点分享一下。IAP是指In-App Purchase, 是一种付费方式,而并不是苹果专有的付费方式,在其它平台上也会有不同的实现,这里针对Apple IAP。

说到IAP安全问题,在苹果的IAP流程中有一个比较明显的逻辑漏洞,这个逻辑漏洞是建立在我们处理不当的情况下发生的,会导致己方提供的服务和玩家之间出现问题。先看看IAP支付时序图:
sequence_iap

整个支付流程如下:
1.客户端向Appstore请求购买产品(假设产品信息已经取得),Appstore验证产品成功后,从用户的Apple账户余额中扣费。
2.Appstore向客户端返回一段receipt-data,里面记录了本次交易的证书和签名信息。
3.客户端向我们可以信任的游戏服务器提供receipt-data
4.游戏服务器对receipt-data进行一次base64编码
5.把编码后的receipt-data发往itunes.appstore进行验证
6.itunes.appstore返回验证结果给游戏服务器
7.游戏服务器对商品购买状态以及商品类型,向客户端发放相应的道具与推送数据更新通知

这七个步骤实际上是一个很安全的流程了。那问题出在哪里呢?我们谈谈两种苹果IAP的验证模型。

IAP built-in Model,本地验证

有些单机游戏甚至是网游,都直接跳过了3~7步骤,在第2步拿到receipt-data之后,直接由客户端向itunes.appstore发送验证请求,并且拿到结果,根据结果修改游戏数据。

我们在设计游戏的时候都遵循一个真理,“凡是在客户端的数据都是不安全的”,深以为然。如果没有独立服务器辅助验证,这样也就避免不了数据被修改的事实了,是的,你会少赚钱。不过如果网游也不通过独立服务器验证,而是在客户端验证之后再告知服务器状态让其发放游戏道具,那就太可怕了点。这是IAP built-in Model,经常出现安全问题的逻辑如下:

void paymentQueue(...)
{
    if (transaction != nullptr)
    {
        me.money += 1000;
    }
}

上面的代码在接收到付费成功的response就直接给游戏发放商品,不对产品和单据进行验证。如果receipt-data允许放在本地验证,就可能发生我们说的免费内购的BUG. 而实际上也真的有类似IAPCracker/IAPFree等工具专门利用这样的IAP漏洞的。而对于已经越狱了的iOS设备就太简单了,甚至不需要通过伪造或者跳过receipt-data验证就可以修改本地数据达到目的。

那是不是就完全不能让这个过程变得安全了呢?也不是,但这个安全保障只是让修改变得困难而已。苹果官方提供了 Validating Receipts Locally 在客户端对receipt-data进行安全验证,主要是对证书以及签名的合法性验证。如果不想自己写代码验证,也可以借助第三方机构提供的receipt-data验证API,比较著名的有 urbanairship 和 beeblex 。

但如果能伪造一个完全合法的receipt-data,是不是一样可以达到欺骗目的。是的,为了绕过Validating Locally,于是黑客开始用自己伪造的receipt-data进行移花接木,所以出现了可以伪造”合法订单”的 in-appstore 。因此这种本地加强验证的方法也不能完全避免IAP攻击。

IAP Server Model,服务器验证

而如果我们把验证逻辑移到服务器上,这个过程就变得容易多了。因为不再需要担心receipt-data被伪造的问题。不过就算把步骤4~7在服务器上做了,同样也会产生一些幼稚的逻辑漏洞:

对验证receipt-data的reponse content不进行验证和记录,只根据Product直接发放商品。这样只要客户端不断提交receipt-data,按照正常逻辑你就需要不断验证并且重复发放商品。较为安全的做法是:

在每一次收到receipt-data之后,都把提交的玩家账号以及receipt-data中的单号建立映射并记录下来,在每次验证receipt-data时,先判断其是否已经存在。

只要做了这样的验证,整个支付流程都变得明朗起来。

确保receipt-data的成功提交与异常处理

建立在IAP Server Model的基础上,并且我们知道手机网络是不稳定的,在付款成功后不能确保把receipt-data一定提交到服务器。如果出现了这样的情况,那就意味着玩家被appstore扣费了,却没收到服务器发放的道具。

解决这个问题的方法是在提交receipt-data的协议上设一个返回值,让服务端告知它已经成功收到并验证了receipt-data. 在没有收到这样的回复之前,客户端必须要把receipt-data保存好,并且定期向服务端发起请求,直至收到服务端的回复为止。

如果是客户端没成功提交receipt-data,那怎么办?就是玩家被扣费了,也收到appstore的消费收据了,却依然没收到游戏道具,于是投诉到游戏客服处。

这种情况在以往的经验中也会出现,常见的玩家和游戏运营商发生的纠纷。游戏客服向玩家索要游戏账号和appstore的收据单号,通过查询itunes-connect看是否确有这笔订单。如果订单存在,则要联系研发方去查询游戏服务器,看订单号与玩家名是否对应,并且是否已经被使用了,做这一点检查的目的是为了防止恶意玩家利用已经使用过了的订单号进行欺骗,谎称自己没收到商品。这就是上面一节IAP Server Model中红字所提到的安全逻辑的目的。当然了,如果查不到这个订单号,就意味着这个订单确实还没使用过,手动给玩家补发商品即可。

清爽的列表式游戏背包设计

coeus_ui

周末花了一个下午的时间学习配色,给Coeus做了一个功能界面的美术原型图,总结了一些经验。实际上我也没有严格按照配色表的理论去搭配颜色,我觉得视觉效果带来的冲击力强度在不同场合是不一样的。

  • 针对游戏而言,游戏物品通常充当着功能性道具的角色,而根据我们以往的经验,物品名称的颜色值决定了玩家的第一感观,这也是我们为什么喜欢根据不同颜色的特性来划分游戏道具品质的原因。
  • 物品的描述我使用灰色,因为这段文本对游戏并没有影响(通常而言),灰色可能显得比较朴素优雅。
  • 绿色的TIPS则起到了一个很好的提示作用,因为建立在暗黑色的背景上,绿色实在是太鲜艳漂亮了(很明显是我自己认为的……)。
  • 对于道具效果加成,我使用了比米黄更深一点的暖黄色,其实之所以采用这个颜色,是因为其它色调不是被占用就是实在是搭配不起来了……
  • 物品数量采取圆圈包数字的方式实在算不上是好的设计,这有点像未读消息的数量,我想这也许能逼死不少强迫症……不过由于物品图标暂时不考虑使用框框,所以这个数量标记无论如何都要更加突出,只是要不要用圆形标记就等后面再进行优化了。

颜色搭配很鲜艳,也很有动感。长期玩游戏的人看着会很有冲击力和快感,算是一种很直观的男人在颜色艺术上的浪漫了。不过也有人会觉得花俏,我正在想办法让它看起来更加朴素深沉一些。

之前决定了不采取格子式布局的背包时,我就构思了这么一种清爽的列表背包,物品的信息一目了然,感觉也很清爽。传统的格子布局有个很大的诟病,取决于物品图标的样式,在风格统一的前提下会特别容易混淆,无法直观看到物品信息的情况就只能一个个查看(在PC游戏中通常是使用鼠标指针移过物品查看弹出的TIPS,移动设备则通常要多一次点击操作)。

其实早期的游戏也没有格子背包的概念,那是因为以前的游戏设计中物品通常很少,不需要用网格的方式进行布局。这也是我们现在采用列表式布局遇到的问题之一,不过我也想好了对策。因为玩家在找物品的时候都很有目的性,物品本身是有归类的,只要分类功能设计妥当其实我觉得并不比格子背包麻烦,毕竟列表式布局除了翻页(滚屏)带来的额外操作之外,物品的详情可以很容易被检索。

记GDC China 2014

从上海回到广州时已经是凌晨了,东航老是晚点。附近的店铺基本上都也已经打烊,吃不到好东西了。

说起这次GDC,我们主要是奔着IGF去的,我之前对独立游戏的概念并没有太深刻的印象,对现在的游戏行业来说,独立游戏和商业游戏之间的界限也变得越来越模糊,对于团队而言,在没有资金的影响下完成一个游戏项目,都可以称为独立游戏项目。也有一批纯粹的概念性粉丝认为,只有单纯地为游戏本身而开发才能算是独立游戏。

IMG_2537

据说这次展会的参与人数大约为24000人,刷新了往年记录。不过我在会场感受比较深刻的是外国人比较多,看来GDC在国内的影响力还不够,并且这次也是亚洲赛区的作品峰会。和我一起同行的有两人,是来自我们脑洞工作室的小伙伴,他们从北京赶到上海。

IGF的入围作品都很优秀,奖金总共为8000美元(5万人民币),分为职业组和学生组两个赛组。他们之间有已经在Steam或AppStore上卖的很好的游戏。

作品印象

职业组作品中我最喜欢的是《Duet》,在还没知道它是本届IGF亚洲赛区的参赛作品时,我就已经在AppStore上购买并且玩了一段时间,这是个很不错的游戏,作者是澳大利亚的Kumobius.

《巫剑神威控》是日本「ZENITH BLUE」社团的C84新作,也是我在现场体验过的唯一一款职业组作品。这是一款3D游戏,游戏主角是一名女高中生,以快速剑技为重要玩法,用不同的格斗技巧击杀敌人。画面很炫并且很有快感,用手柄玩起来也相当有快感,但是缺乏可玩性,战斗过程还是略显乏味。不过游戏的负责人很热情,我走到旁边他就拉着我问我是否要尝试一下,就是他教我操作时说日式英文实在太难懂了……

IMG_2535

职业组的两款中国的作品分别是《Zombie Commando(僵尸别动队)》以及《Ghost Blade》。

天宇在体验僵尸别动队的时候,一边和他们的创始人交流了起来。聊到了开发上的一些故事以及过程中遇到的问题。这款游戏在AppStore中国区免费帮前20名,起始团队只有3人,没有投资的情况下3人凑了2万,美术是外包的,因为国内几乎没有擅长像素画的外包公司,因此他们选择了海外的。另外,创始人提到他们的程序员非常牛。这款游戏的画面给人感觉很清新,8位像素风格,团队型战略即时战斗游戏,在Pad上体验很不错,但我在旁边用手机也玩了一会儿,由于分辨率的问题操作有些困难,主要是摇杆区域占了很大一部分比例。

IMG_2528

《Ghost Blade(剑无生)》是一款3D动作游戏,通过手势滑动进行技巧性攻击。给我第一印象是水果忍者划西瓜。但这款游戏的工作量看起来很大,美术方面不错,使用虚幻引擎开发,可跨平台。在Pad上默认的操作方式体验可能会有一些障碍,手指在操作的时候可能挡住屏幕。场景整体风格不错,特别是远景图,和画面整体风格相当切合。这款游戏并没有太多针对移动设备的特征,讲究操作技巧。作者现场促销并怂恿我们购买……

下面聊一下学生组的入围作品。学生组总共六款入围作品,但被迪吉彭理工学院新加坡分校(DigiPen Institute of Technology Singapore)占了三个名额,分别是《Iris》、《Lurking》和《Meowchine Mayhem》,另外的三个名额则都是代表中国的,分别是来自纽约大学游戏中心Team Boss的《Boss》、香港C4Cat的《Shadow of Life》以及中国传媒大学的《Xi(汐)》。

《Boss》是一款逃生游戏,通过声音吸引一直在追自己的Boss并且通关。

IMG_2542

《Lurking》是一个非常有创意的游戏,同时也是一款恐怖类的解谜游戏。这款3D游戏使用Unity开发,主要通过声音主题营造游戏的恐怖气氛,只有发出声音的主角才能看到游戏中的场景,并且需要用声音吸引“丧尸”的注意力并转移到其它地方以让自己获得逃走的机会,找到通关的办法。

以下是颁奖结果:

学生组
优秀学生作品奖:《Iris》、《Boss》
最佳学生作品奖:《Lurking》
(未获奖)入围作品:《Meowchine Mayhem》、《Shadow of Life》、《汐》(Xi)

职业组
最佳美术奖:《剑无生》(Ghost Blade)
最佳技术奖:《Lurking》(学生组作品)
最佳设计奖:《二重奏》(Duet)
最佳音效奖:《Nom Nom Galaxy》
最佳移动游戏奖:《僵尸别动队》(Zombie Commando)
最佳游戏奖:《国王联盟:奥德赛》(King’s League: Odyssey)
(未获奖)入围作品:《Sumoman》、《Battle Group 2》、《巫剑神威控》

关于独立游戏峰会

独立游戏峰会邀请了很多知名游戏制作人给我们分享了很多心得。我在现场简单做了一些笔记。Brandon Sheffield分享的“通过游戏测试改进游戏”,给我们分享的内容大致有以下几点:

1.了解自己游戏的设计意图。
2.把重心放在游戏上的好想法并且不要忘记游戏最初的设计目的。
3.最简单的解决方案或实现方式可能就是最好的。
4.必须要把握游戏中的一切,并且知道它们为什么要这样做,而不仅仅是为了存在而存在。
5.不要因为仅仅是已经过时了的创意而因此放弃它们。

内容相对比较空泛,并且因为是全英文的缘故,很多演讲细节没能很完整地理解。

《C-Wars(水晶战争)》可以算的上是现场给我感觉最好的游戏制作分享,由国内的傲逆软件创始人带来的分析报告。可以算的上是一款非常用心的游戏。C-Wars在KS上拿到了10万美元的众筹,可以说的上是国内最成功的独立游戏。除此之外还提及了如果发展海外市场,要杜绝文化差异的问题以及要注意本地话校对难度的问题。C-Wars是像素风格游戏,这类游戏在国内很小众,但对于大部分海外玩家来说却很受欢迎。但我觉得,这款游戏即使在国内也会受玩家青眯,这款游戏的画风真的相当赞!

IMG_2577

 

后话
这次的GDC让我对游戏行业有了一个比较新的认识。游戏作品可以用很多方式去表达,不论最终的目的是不是为了获得金钱上的收入,但在过程中都要把心思放在游戏的设计上,被结果捆绑的作品始终不能算是艺术品。

独立游戏比赛是一种不管卖座的盛会,和市场无关,这可能才是游戏的魅力所在,只要能带来快乐就好。游戏不应该用收入来定义成功。

烘焙:泡面的水果Pizza

我上次假期烤了一个烤肉pizza,因为和面的时候出了点意外(水太多),肉没有预处理,而且选的鸡肉不是鸡胸肉,骨头太多。另一方面,烤箱温度和时间都没控制好,因此最后吃起来一般般。吸取了上次的经验,这次把过程给记录了下来,虽然和面仍失水准,并且最后的结果虽然有点焦,但吃起来还是不错的!

我把我的步骤大致说说,也方便有想做pizza的同学参考一下。

继续阅读

小乌龟

这是以前流行的一首歌,如果不是突然听起我都差不多忘了还有这么一段温暖的回忆。
只是美好的东西不能长久,时间跑了就没了。

现在想起来还有点感慨,感谢插班生给我带来的青春邂逅,不知你现在可好。

好玩的charas.EX

天宇找了个好玩的2D纸娃娃系统,叫做charas.EX.

工具很不错,虽然有点儿简陋,不过想想已经十年历史了也挺正常的。charas.EX带了很多像素风格的素材,可以满足很多小游戏的需求。

“纸娃娃系统”的意思是把不同部件组装成一个新的游戏角色,这样就可以动态的更换身体部件,组成新的样式。传统的2D纸娃娃是在不同部件的图片都制作一套动画,再组装起来播放;还有一种是基于骨骼系统的,只有骨骼在运动,部件都是绑定在骨骼上的,这样可以省大量的美术成本。

因为软件比较古老了,有些界面上的英文词汇很随意,我就花了点间把这个工具给汉化了,部分词汇似乎是已经被抛弃了的功能,并且没法理解其上下文意思,我就没有汉化,除此之外的一些菜单项、对话框提示问吧、以及“你知道吗”都已经汉化了。

原版的charas.EX:
charas_ex_1

汉化后的界面:
charas_ex_2

这个工具很小巧,汉化的工作量不大,如果有感到不适的翻译请联系我~
另外在这个工具的Additionals下面是有福利的,分别带了这个工具的源代码和用到的FreeImage插件。

中文语言包:Chinese.zip
(解压到language目录下即可)

这个工具所有素材都来自在线资源库:http://charas-project.net/charas2/index.php
桌面版原版下载:http://charas-project.net/charas.ex/Charas.EX_04-10-02.zip

———————
国内部分地区可能会墙掉了原版下载地址,所以我在这里上传一个:
Charas.EX_04-10-02.zip

如果Windows8系统下崩溃,尝试用兼容模式。在执行charas.EX.exe之前,先执行Charas.Updater.exe

(桌面版在运行的时候会提示你更新素材库)

广东饮食文化

看了一期BBC美食纪录片,我也顺便介绍一下广东的饮食文化。

广东料理(Cantonese Cuisine)是我们俗称的粤菜,也包括了在潮汕那一带的客家菜。有句话说“四条腿除了板凳,带翅膀的除了飞机,广东人都敢吃”,虽是高级黑,但广东的饮食的确很丰富,这是因为很久以前这边很缺乏食物,所以吃的东西比较广。

平时在广东经常可以吃到什么呢?家禽类要属鸡肉最多了,白切鸡很有名,是我最喜欢的食物之一。它通常不是完全熟透的,基本上保持原味,可以配合很多种调料蘸着吃,所以有些外地人不能习惯。其次是海鲜,广东是沿海的省份,因此运输海鲜也不是很难的事,最经常吃到的就是清蒸鱼、生蚝(牡蛎, oyster)、花甲(蛤蜊,clam)、小虾(shrimp)。

大部分广东人口味淡,所以喜欢清蒸,因为这样可以保持鲜味。我是个很喜欢海鲜的人,几乎每次外出觅食都会点海鲜,并且聚餐的时候一定要点清蒸鱼,清蒸鱼其实不淡,但这要看厨师的功力,如果调味足够好,是一道非常不错的菜,鱼肉鲜美而且不会没有味道,它通常会带有姜、葱、香菜用于去腥,在广州的餐馆里最多的是鲈鱼和桂花鱼。清蒸鱼也是我最喜欢的食物之一。

然后要说一下生蚝,在传统酒楼的餐桌上其实很少点生蚝的,一般在吃烧烤的地方比较多,这几乎也成为在吃烧烤时必点的食物,生蚝也是我最喜欢的食物之一,我每次都会吃很多。

广东流行老火汤,传统的老火汤一般是用瓦锅或砂锅煮或者炖。煮出来的汤,食物的养分会完全在汤里面,有个古老习惯是汤里面的肉和食材是不和汤一起吃的,要先喝汤再吃。所以也有做法是把肉用来煮汤,煮完之后再把肉捞起来炒。

炖汤通常和比较名贵的药材一起,汤和里面的食材都可以吃,属于很滋补的汤类,也是我最喜欢的汤类做法。在广州常见的炖汤是乌鸡和花旗参,或者和当归枸杞一起,还可以用老母鸡加田七。除了滋补类的汤,还有比较清凉的,如排骨玉米和红萝卜汤。一般来说,汤里面都不会放姜、葱或香菜。有哪些汤可以用姜葱和香菜去腥呢?那就是带有水产品的汤,例如俗称可以减肥的鱼头豆腐汤、还有鱿鱼汤、瑶柱汤、花甲汤,他们都属于海鲜类。其实正常情况下汤一般要炖好几个小时,因此在餐馆或者酒楼里的汤大多都是速成的,食材也通常是煮熟之后冷藏的。如果在广东不喝上一些好喝的炖汤,那就白来啦。

然后说一下其它菜,扣肉、烧鹅、咕噜肉(甜酸肉)、叉烧、沙茶牛肉(潮汕)、猪手、炸子鸡、凤爪、炒田螺等。广州有很多其它地方的人,所以很多菜式逐渐在结合其它地方的菜式的口味,这也是一大特色,因此吃不到地道的粤菜也不会很奇怪。但是广东人开的小餐馆的粤菜就一定比较地道,因为那都是他们家乡的口味。