与iPhone应用运营有关的一些想法

昨夜睡前突然想到了一些iPhone应用的运营思路,越想越兴奋,结果失眠了,sigh = =

由于每次更新iPhone应用的客户端的版本都需要苹果的审核,因此面对紧急的bug时,在客户端非常难做及时的调整。所以,基本的思路就是,要将客户端做得非常灵活,一些关键逻辑可以做到从后台控制,这样在发生突发状况时可以直接在后台发布新版本来更新整个应用的功能。最极端的状况是把客户端做成一个脚本解释器,通过从后台下载脚本来完成应用或者游戏的功能。这样对客户端的要求可能就要高一些了,在脚本解释方面一定不能出现bug,= =..

具体到游戏的运营,可以考虑这样做:客户端集成渲染引擎和基础游戏逻辑,然后将关卡数据、游戏素材等通过后台来将配置下发,这样更新的关卡或调整数值时就不用发布新的客户端版本了。同时游戏外层的菜单逻辑完全可以考虑采用脚本编写,提供最大的灵活性。

想到这里,其实可以再多想一些,何不把这种技术做成一种平台/服务?我们提供的是一个易于发布和维护iOS应用的平台,将应用运行框架(其实说白了就是一个脚本解释器..)做成一种中间件,开发者只需让应用初始化上架一次,其它的更新就可以通过这个平台来进行后台发布。。。

Flash Player的fps最大值

做项目时遇到一个很令人纠结的问题:在IE下,将fps设置为40,然后会发现两帧之间的interval在16ms和32ms之间跳动,十分不稳定,无法保持稳定的25ms,导致物体位移位置不够精确。
在网上找了些资料,最后翻到了这篇古老的文章,学到了一些与Flash Player相关的细节。
不同形式的Flash Player拥有不同的最大帧率,这取决于插件的内部实现。像IE里的FP插件,受IE浏览器对其的限制,插件的clock发出timer事件的频率最快也只有一秒60次,所以FP插件可能最大帧率也只有60fps,也就是说,两帧之间的时间差最大为16ms。对于独立的Flash Player,接收的是直接来自系统的timer信号,往往频率会很高,fps甚至能跑到120左右。

结合“40 fps下frame interval在16ms和32ms左右波动”基本可以猜测出IE下的FP的FPS相关逻辑是如何实现的:收到底层的timer事件后对自身时间值进行累积,超过设定的frame时刻就启动帧的enterframe、跑代码、渲染等各种逻辑。真正执行逻辑的时候都是在收到底层timer信号的时间点上,而往往不是真正的理想中的frame刷新时刻。这也就基本解释了为什么frame interval会在16ms和32ms之间波动。

对于开发者而言,这种实现形式可能造成的结果是,每两帧之间的流逝时间可能不尽相同,所以如果开发对时间精度要求比较高的游戏,逻辑可以写在enterframe里,但是位移之类的东东,要像Tweenlite的实现一样,根据当前的时间进行计算,而不是简单的每帧增加一些位移(这样会导致视觉上的“卡”)。

防止Flash游戏被破解的N种做法

前言:
本文受《Flash Player Security Advanced Walkthrough》的启发,查看原文请猛击此处

做游戏加密之前,您需要了解以下事实:
1、Flash字节码的意义都是公开的, 所以如果cracker真的有足够的耐心,他最终还是可以破解掉你的Flash。我们能做的只是尽量提高Flash被破解的门槛,让cracker破解它需要消耗的时间大于自己更新版本的间隔就好了。
2、Flash自身无法(或者说很难)知道自己是否被篡改过。
3、Flash里有ApplicationDomain用于对不同域的类定义进行区分。

下面将由浅入深列出几种保护Flash游戏的做法。

1、关键数据加密
适用防范对象:
使用内存修改工具妄图直接修改关键数据的初级cracker
原理:
关键数据不使用明文保存
具体做法:
对关键数据的存取使用AES或XOR等算法进行处理,保证关键数据在内存中不以明文保存

2、修改数据包
适用防范对象:
使用Fiddler等各种工具篡改回包或使用假数据发包的初中级cracker
原理:
加密数据包,并在数据包里面加入防伪信息
具体做法:
对数据包内容进行简单的AES或XOR加密,并在其中加入类似TCP/IP协议的Sequence ID,前后台共同对数据包进行校验。

3、Flash初级加密
适用防范对象:
会用Flash破解工具破解之后,尝试对Flash源码进行修改的中高级cracker
原理:
提高使用工具破解Flash之后读懂源码并进行修改的门槛
具体做法:
直接使用工具(如:DoSWF等)对Flash的关键代码进行加密和混淆

4、Flash高级加密
适用防范对象:
没有足够的时间和耐心的高级cracker
原理:
使用各种恶心的技巧对自己的Flash关键内容进行保护
具体做法:
(1)对关键代码进行混淆 ——提高破解后读懂代码的门槛
(2)将保有关键逻辑的main.swf以二进制形式嵌入到工程里,在外层使用loader的loadBytes()方法进行读取并实例化 ——提高直接被抓包抓到关键SWF的门槛,需要cracker解析文件内容才能拿出来关键的swf
(3)加载main.swf之前,检测关键类是否已经被定义过,并且将main.swf加载到与loader.swf不同的ApplicationDomain ——防止cracker使用修改mm.cfg嵌入preloader等方法事先定义关键类用来顶替main.swf中的同名关键类,提高类替换的门槛

综上,可以采用的几点技巧为:
1、对内存里的关键数据进行加密;
2、对数据包进行加密;
3、对主swf文件进行加密和隐藏,对preloader进行高度混淆;
4、主swf文件加载到与preloader不同的ApplicationDomain,并在加载之前检测关键类是否已被定义
5、让用户读到的preloader尽量保持为最新的

同时,后端也要特别注意的验证数据的有效性,包括但不限于:
1、服务器端需要校验所有的交易数据
2、提交的分数要通过用户的游戏数据(用户操作序列、游戏各关键数值随时间的变化情况等)进行深度校验

附送小技巧:
其实你可以定位cracker的存在喔~
由preloader读取并实例化主swf文档类时,可以增加一个特殊的参数,当这个参数没有被设定为特定的值时,主swf就可以认为自己被独立运行了。此时极有可能是cracker在尝试破解这个swf,所以你可以偷偷的上报一些加密后的用户数据(IP等各种信息)传到一个名字看上去不容易引起怀疑的CGI(比如get_friends_data之类)。定位到IP之后,你应该就可以找到他发到的所有包了,对这些请求进行特殊处理(比如全都返回随机的乱码数据包)能够极大的延缓他破解Flash的进程。
同时,后端应该也可以记录下来所有构造不当的数据包,对这些发包源也进行适当的记录,通过发包频率等特征来判断是否为cracker,然后对这cracker进行惨无人道的随机乱码回包处理(听起来好邪恶呀-_-b)。
特别注意:一定不要发送诸如“你已经被我们发现了”的信息引起他的注意,他会很快发现这个上报机制并且进行去除的。

 

《Candy Crush Saga》破解

1、准备工具
硕思Flash反编译工具5.5,用于粗略查看反编译的代码,梳理程序逻辑。网上有很多这个工具的下载点,这里就不再提供下载页的地址了。
字节码修改软件Yogda,用于修改关键逻辑。
2、准备文件
完整地玩一关游戏,用Fiddler记录请求,找到所有的目标swf,Save Sessions。
3、开始动手
首先,从之前破解Bubble Witch Saga的经验推断出,King.com旗下的这些游戏无一例外的都有GameConsole这个东西。所以破解的第一步是从preloader里把GameConsole还原出来。
GameConsole初始化时的构造参数里,有一个debugMode字段,其为true的话在游戏中按Esc就可以调出控制台了。
用硕思找到PreloaderMain.as文件,找到粗略还原出来的代码:
不难看出,开发者的意图是要在没有URL,或者URL中包含dev.midasplayer或candycrushqa.midasplayer.com时才启用控制台。
如何令其在facebook上也可以使用呢?方法多种多样,对源代码改动最小的方法或许就是稍稍修改一下判断条件,把“包含”改为“不包含”。
目标明确之后,直接用Yogda打开preloader.swf,定位至PreloaderMain类的init函数,把greaterthan改为equals,将新的swf文件保存。
用Fiddler替换一下preloader,再次进入游戏后按ESC,果然弹出了控制台的界面。
话说回来,这个“控制台”又是什么东西呢?
通过分析反编译出来的代码可知,它是提供给开发人员或者客服进行调试用的工具。理所当然的,它也会在游戏中提供一些很好的功能帮助我们过关。
进入游戏,按ESC调出控制台,发现游戏模块多注册了几个命令。
其中:
add_moves 给自己增加步数,增加数量是自己指定的
spawnitem 预生成强力糖果
hammer 启用一次糖果锤
win 直接胜利
为了增强成就感,让我们再看一下相应道具的价格吧…
直接”spawnitem color”就可以生成的color类型的糖果折合人民币要1.91元….一个肉包的钱呀!!!
这个价格更是触目惊心,用一次“spawnitem fish”命令就可以生成的jellyfish,折合人民币居然要4.03元…一个肉夹馍的钱啊!!!
糖果锤对游戏的帮助也是相当大的,使用一次折合人民币也要4.03元…这种虚拟物品卖到这样的价格,会令肉夹馍会很伤心的…
4、事后总结
控制台这种东西可以有,但是在release版本中最好不要带控制关键逻辑的功能,仅提供调试数据的查看就可以了,不然会极大的降低破解门槛。游戏一旦被破解,那些游戏道具瞬间就变得毫无价值了…
5、相关下载
点此可以下载破解过的Preloader (Last updated on 2012/12/25)
只需拿Fiddler将facebook上的preloader本地替换掉即可调出控制台了。

使用Starling框架的一些心得

一、侦听MovieClip播放结束,设置其loop为false
如果要监听动画是否播放到最后一帧,有至少如下两种方式:
1、监听starling.events.Event.COMPLETE事件
2、在starling.events.Event.ENTER_FRAME事件中判断mc的currentFrame
需要注意的是,要将mc的loop设为false,原因是Starling采用了类似TweenLite的advancedTime机制,使动画播放效果不受Flash的fps影响,如果mc的loop是true,这种机制对如上两种方式造成的影响分别是:
1、发出这个事件的时候,mc有可能播回了第一帧,影响显示效果;
2、帧脚本执行时间太长,使advancedTime增大,可能会导致mc跳过最后一帧直接播到下一次loop的前几帧,绕过了ENTER_FRAME里的currentFrame判断
建议:如果对mc播放结束有侦听,一定要设置loop为false

二、将Starling代码作为项目的源路径时的”多名称引用”报错
建议:删除Starling项目里默认包的Starling.as
三、多个Starling的实例引发Texture失效的问题
Starling实例在被new出来的时候会被自动设置为当前的活动实例,而生成Texture的时候,会为其当前活动实例的Context3D调用uploadFromBitmapData()将素材数据上传。而不同的Context3D之间的数据无法共用,所以在旧Starling实例活动的时候生成的Texture是无法在新的Starling实例里显示的。
建议:用一个Starling实例即可。
四、与传统显示对象的配合
对于Starling的Sprite有nativeOverlay返回Context3D之上的native Sprite
Starling官方提示:在Context3D上叠加传统显示对象可能会导致效率受到影响,所以要谨慎使用;
个人理解是,PC机上没问题,移动设备上要慎重使用

Starling框架之MovieClip用法初探

关于播放控制:
starling.display.MovieClip并没有flash.display.MovieClip中诸如gotoAndPlay和gotoAndStop之类的用法,取而代之的是如下几种方法:
1、play()
从当前帧开始播放
2、pause()
停止动画播放,保留当前帧
3、stop()
停止动画播放,并且将当前帧置0
4、 set currentFrame()
设定当前帧
与flash.display.MovieClip的比较:
flash.display.MovieClip优势在于流媒体播放,play()的时候是可以边加载边播的,这种特性导致了难于使用程序精准地控制MovieClip的TimeLine,难于使用程序改变MovieClip每帧的内容;
而starling.display.MovieClip优势在于使用stage3D加速2D的播放,但其所受到的根本限制是需要提前准备好每一帧的Texture,正是这一限制,或者说是特性,决定了它可以提供API设置每帧的播放时间、动态改变每一帧的内容,为游戏开发者提供了更多的灵活性。