September 19, 2016

ephemeron table 对 property tables 的意义

今天在公司群里,Net bug 同学提出了一个问题,围绕这个问题大家展开了一系列讨论。讨论中谈及了 lua 中的一个常见的模式:property table ,我觉得挺有意思,记录一下。

最初的问题是:当一个对象的某些属性并不常用,希望做惰性初始化的话,应该怎么实现。

我认为,property table 是一个很符合这个案例的常见模式。

比如,对象 f 有三个可能的成员 a b c ,我们可以不把 f.a f.b f.c 记录在 f 这个 table 里,而是额外有三张大表,a b c 。利用 metatable ,可以在访问 f.a 的时候,实际访问的是 a[f] 。也就是说,所有同类对象的 a 属性,都是从 a 这张表里访问的。

a 这张表的 key 就是对象,value 是对象对应的 a 属性值。

阅读全文 "ephemeron table 对 property tables 的意义" »

September 14, 2016

Shop Heroes 的公会系统

上一篇谈到了 Shop Heroes 的经济系统,这一篇想谈谈它的公会系统。

和很多其它网络游戏不同,Shop Heroes 的公会系统并不是一个可以被剥离的系统,它和整个游戏,包括其经济系统是密不可分的。我觉得这个系统是为了完成其游戏的根本设计目的:引导玩家差异化发展从而制造出市场需求,而设计出来的东西。

在游戏中,不存在未加入公会的玩家。玩家在新手教学阶段就会被强制引导到一个叫做外城的环境,也就是游戏中的公会。你必须选择加入一个已有公会,或是自己创建一个单人公会,否则游戏无法进行下去。

在游戏的前几十小时,一个人玩其实也没有任何障碍。你可以把公会建筑看成是个人资产的一部分,该升级升级。但在上一篇提到过,游戏中用来升级的金币最终会成为紧缺资源,总有一天你的收入会承担不起。当然,作为一个固执的 RMB 战士,你还是可以一个人玩下去的,城市升级可以用钻石替代。而且很贴心的设计成非线性对应关系。正如上一篇提到的,金币随等级不同(生产能力成指数上升),其价值也不同。所以如果你想投资 20K 金币,可以用 80 钻替代;而一次投资 500K 的话,就只需要 300 钻而不是 2000 钻了。

相比一个人用钻石经营一座城市,更经济的方法是加入一个公会,大家共同建设一座城市;对于个人来说只有好处,没有任何坏处,何乐而不为呢。

阅读全文 "Shop Heroes 的公会系统" »

Shop Heroes 的经济系统

最近两周在玩一个叫做 Shop Heroes 的游戏。知道这款游戏是因为它前两个月在 Steam 上线了 PC 版,玩了一下觉得有点意思。由于其 UI 一眼看上去就是手机风格,便在 app store 上搜索了一下,改到 ios 上玩。

游戏设计的很好,对我这种资深游戏玩家有莫大的吸引力(对于快餐手游氛围下进入的新玩家可能因为系统过于复杂而玩不进去)。它设计了无数个斯金纳箱,营造出文明的那种 one more turn 的心理感受,让人欲罢不能。具体不展开讲,有兴趣的同学自己玩玩试试。

让我感兴趣的是游戏内部的经济系统,经过数十小时的游戏体验,我隐约感觉的到设计者希望设计出一个以玩家交易税收为主体的商业模式。而这种模式很多人都提出(我从 10 年前就反复考虑,在 blog 上也做过一些思考记录)并希望实现,可全部都失败了。比如著名的 Diablo 3 ,曾经就宣称自己打算用交易税来维持游戏的利润,最后因为破坏了游戏体验而关闭了现金拍卖场。国内也有征途等打着以交易税为收入来源旗号的游戏,而实际上却只是个幌子。

而 Shop Heroes 似乎真正做到了这点。从结果上看,在市场上的中高等级玩家之间流通的物品全部是用钻石结算的。而游戏本身,玩家提交求购或售卖单的时候,都可以自由选择用钻石(现实货币)或金币(游戏货币)结算。虽然我是一个免费游戏玩家,但我尝试过用(免费获得的)钻石提单到市场,均快速成交,能感受的到市场的活跃。在这些钻石交易里,系统是要收取 25% 的交易税的。

我思考了好几天,游戏是怎么做到:引导玩家(同时包括 RMB 战士和免费玩家)进行钻石交易从而收税,这一点的呢?

阅读全文 "Shop Heroes 的经济系统" »

August 28, 2016

Lua 稀疏数组

Lua 的 table 可以做数组用,但是前提是数组里不能有空洞。也就是不能在数组里保存 nil ,否则取长度和迭代的行为都是不确定的。

能不能用比较小的额外代价在 Lua 中实现一个支持空洞的数组呢?

首先,我们定义一下,带空洞的 array 的正确行为应该是怎样的:

  1. 数组只能用正整数做 key ,设置其它 key 会抛出 error 。

  2. 可以用 pairs 迭代数组,和普通的 table 一样,迭代器会跳过那些值为 nil 的键值对。但要求迭代器一定从 1 开始从小到大按次序迭代。

  3. 用取长度 (#) 操作符,可以正确的返回数组的大小,即最大一个正整数 key 。

  4. ipairs 的行为不变,会在第一个 nil 处停下来。

阅读全文 "Lua 稀疏数组" »

August 19, 2016

pvp 游戏如何解决玩家匹配等待时间过长的问题

按局打的纯 PVP 机制的游戏,面临最大的问题将是,在一个玩家想找人对战的时候,找不到对手匹配。

如果游戏的在线玩家达不到一定人数,那么这个问题会恶化:等不到人和你一起玩、放弃等待、新的玩家更找不到对手。

像皇室战争、王者荣耀、炉石传说这些火爆的 pvp 游戏都属于迈过了线的作品,玩家不太愁等不到人一起玩,提升了游戏体验,聚集了更多的玩家。而当玩家群有限时,同类产品就很难竞争,只要在线用户掉到一定限度以下,很可能导致(无非找到对手)体验下降,更多玩家流失。

那么,有没有办法解决初期玩家过少的问题呢?

直观的想法就是没人玩 AI 凑。可 AI 并不是真人,和 AI 在公平规则下对战乐趣会少很多,且高水品 AI 开发起来也非常困难。最关键的是,一旦玩家乐于和 AI 对战(无论是因为对战本身的乐趣,还是可以刷分刷掉落),你会进一步失去在线用户。

阅读全文 "pvp 游戏如何解决玩家匹配等待时间过长的问题" »

August 11, 2016

群星的汉化及其它

最近一个月,玩群星(Stellaris) 有点着魔。不同于 P 社之前我最喜欢的维多利亚2 ,这个上手更舒服。是我玩过的把大战略和 4X 结合的最好的游戏了。我很欣赏 P 社这种尽力降低玩家门槛的做法,让大战略和 4x 游戏不那么高冷,普通玩家也能很快领略其中的乐趣。

这里有我写了一篇评测。大致谈了群星是一个怎样的游戏,如何快速入门。小提示:即使是新手,也推荐用铁人/疯狂模式。第一次玩只需要把银河调小一点就好了。这样乐趣才能充分体现出来。

这次 P 社的引擎革新后,汉化变得很容易了。之前,大多数人和我一样使用的 3dm 版汉化 mod ;但这个 mod 翻译的时候,译者并没有怎么玩游戏,所以很多地方用词不当,还有一些仓促翻译导致的错别字。我实在受不了老式的闷头汉化的模式了,发现问题反馈到修正的周期太长,所以就自己维护了一个汉化 mod 。

需要的同学可以直接订阅。个人认为,利用 github 做合作创作,对于做汉化这件事特别合适。这个 mod 直接放在了 github 上

游戏文本的版本更新,可以直接体现在 diff 里。路人发现有错别字也可以顺手提个 pr 。而我自己一般是在玩游戏时瞟见翻译的不合理的地方,立刻打开文本编辑器校对一下。也正因为如此,游戏里出现的 event 都特别仔细的阅读;群星的开发者真是脑洞大开啊,游戏里的 event 涵盖了几乎我所有阅读过的科幻小说,看过的科幻电影的梗。光这一点就值回了票价。

在群星发布前,我还十分担心,如果没有了维多利亚里那种厚重的历史感,一个科幻题材的战略游戏该如何给玩家代入感;没想到它是通过这个手法来完美的解决了这个问题。

阅读全文 "群星的汉化及其它" »

July 13, 2016

在 skynet 中如何实现多 actor 协作的事务

今天在 qq 群中,有个同学问,在 skynet 中,如果多个 actor 需要协作时,能否有事务来保证一系列操作的过程中,状态不会被破坏。

他举了个例子:

如果有一段业务逻辑是:

local a = skynet.call(A, ...)
local b = skynet.call(B, ...)
if a and b then
  dosomething()
end

如何保证 a and b 这个条件有效呢?也就是说,在第一行从 A 处获取状态后,还要向 B 查询一个状态;如果希望两者查询完毕,一直到 dosomething() 结束前,A 和 B 的状态都不要改变。期间,如果有请求发到了 A 或者 B ,最后都暂时挂起。

阅读全文 "在 skynet 中如何实现多 actor 协作的事务" »

Misc

Categories

Archives

Recent Comments