九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

多重继承不好的观点是错误的 -- 小评<松本行弘的程序世界>

首先得说, 一般某种语言的发明人写的关于自己语言的东西都是非常值得阅读的, 从别的牛人那里你也许能学会很多奇技淫巧, 但从语言发明人那里你能学到语言发明人本身设计的初衷, 以及设计时的一些抉择. 这种思路是独一无二, 绝无仅有的. 所以我在学习一个新语言时, 假如语言发明人有写书, 一定优先阅读.

阅读全文....

写递归函数的正确思维方法

递归是编程中一个相对难以理解但是却又很重要的概念. 对于从命令式语言开始学习编程的程序员天生对此有理解缺陷, 而对于从类似C++这种对函数式编程范式不友好的语言开始学习编程的程序员就更加如此了.(比如我自己) 碰巧(其实不巧)最近在读这本书, 这本书国内没有引进, 网上只有巨贵的[亚马逊卖的原版](http://www.amazon.cn/gp/product/0133708756/ref=as_li_ss_tl?ie=UTF8&tag=jtianlinsblog-23&linkCode=as2&camp=536&creative=3132&creativeASIN=0133708756), 我读的是[网上的中文版](http://acl.readthedocs.org/en/latest/), Paul Graham在书中讲述的如何写递归函数的部分, 让我印象深刻. 因为原书是讲Lisp的, 当然这个部分也是用Lisp作为例子描述的, 考虑到国内会看这本书的人太少, 能看懂Lisp的就更不多了, 我这里根据自己的理解, 重新整理一下. 最重要的是, 书中原来的例子太少, 太简单, 我自己提供了一些额外的, 并且更加复杂的例子. 以期对问题能有更好的理解.

阅读全文....

语言的界限就是一个人世界的界限

语言的界限就是一个人世界的界限	
-- 维特根斯坦

Ruby on Rails的世界

很多人会告诉你, 学习不同编程语言能够让你看到新的世界, 改变你思考的方式, 在程序员修炼之道中甚至会建议’每年至少学习一门新语言’, 也有Peter Norvig在十年学会编程中提出的那样, 学会至少半打语言. 我是比较赞同这种观点的.

阅读全文....

用Markdown + VimPress写博客

这次把CSDN的文章移过来的时候, 发生了格式混乱的不愉快体验. 虽然以前的那些文章有些很稚嫩, 早期的文章现在看来甚至很可笑, 但是, 这种记录还是很值得保留, 毕竟是成长的过程.
整理一些文章格式的时候, 还发现一个有趣的故事, 原来我现在这么喜欢Vim, 来自于当时刚到北京, 用一个巨老无比的笔记本, 图形界面几乎没法用, 所以才无奈之下真正的耐下心来学习Vim, 见买了个新显示器. 而这已经是我第3次开始尝试使用Vim了, 从那以后, 我几乎没有Vim就没法工作了.
闲话少说, 综上所述, 我决定好好的管理一下自己的博客, 虽然现在已经用上了自己可以控制的Wordpress, 但是谁知道将来会不会再发生忘记缴费, 数据被删的事情呢, 即使我用上了Wordpress的备份, 我还是需要给自己写的文章做一个自己的备份, 并且可以用Git来管理, 这个才叫真的备份, 连历史记录都备份了. 同时, 因为格式上的原因, 我决定用某种文本格式来保存我的文章, 当然, 我可不准备手写HTML, 这样才不会出现用Windows Live Write写博客那样的悲剧, 并且, 作为离线写博客的方式, 用Vim来处理文本就方便了, 不用再去找各个平台的啥离线工具.

阅读全文....

做一些新尝试

我以前最喜欢的博客可能吧昨天破天荒的更新了,在可能吧获得国家认证以后,更新越来越少,直到昨天,作者真正的宣布了可能吧“可能”从此停止更新。

作者的理由是“能支配的时间、精力、激情都在减少,写博客的动力自然就不存在了。”“或许博客这种形式不太适合移动互联网传播,我尝试过Tumblr,还是太重,尝试用Twitter,过轻。微信,是我接下来要尝试的。”

心里突然有些悲凉。可能吧是我最为赞赏的坚持输出自己价值观的博客,在谷歌退出事件中力挺谷歌,因此获得了国家认证,对比那些发发牢骚,不痛不痒的博客来说,可能吧更加让人尊敬。而国家认证,事实上也毁掉了可能吧,的确,没有读者,那为什么写作,对于绝大部分现在还能看到可能吧的读者来说,输出的价值观早已被认可了,而看不到的人,可能才是更加应该去看的人,这真是吊诡。这也是国家认证的威力,让围墙中的人永远不知道自己其实活在围墙里面。一方面囚禁你,一方面告诉你你很幸福,这就是现实。

另外一个我很喜欢的博客,刘未鹏的博客最近更新也少了,可能作者忙于微软的输入法项目吧。目前真正能看的博客,可能只剩下阮一峰的博客了。有些感概。

CsdnBlogMover的帮助下,把CSDN的文章和评论都搬过来了,算是一种纪念吧,结果发现格式很乱,特别是当时心血来潮用windows live writer设计好看的模版写的那一系列文章,乱的一塌糊涂,基本不能看,同时windows live writer的保存格式又是一种私有格式,非得用windows live writer才能打开。再次印证了一切把人圈起来的东西,包括软件,都是万恶的。追求自由,往大了说追求言论自由,往小了说,使用一个软件的时候,拥有将来某个时间点不再使用这个软件的自由都是很重要的,这就要求这个软件的设计出发点不是企图把人圈起来,坏的典型就是windows live writer,好的例子,比如Evernote, Evernote在菜单上就有Export All Notes的功能,导出为公开格式的文本文件(甚至包括HTML)假如你愿意的话,你可以在任何时候离开Evernote,这是一种开放的精神,也是一种自信的气魄。不知道国内那么多模仿者,学习了这种精神没有。

我的博客最近很少更新,虽然也的确有最近比较忙的原因,同时,学的东西实在太杂了,虽然一直在学习新东西,但是都是广度上的,深度上没有突破,很多东西其实都比较浅,感觉不值得分享。我甚至都不好意思把那些肤浅的东西写下来,以免贻笑大方。但是这样下去,这个博客就没得东西可以更新了。

我也进行一些新的尝试吧,作为程序员,技术上,我会介绍一些自己感兴趣的库(最近爱上了github),同时自己应该也会有机会开源一些自己的库。同时,引进一些项目的想法,希望有人可以一起来完成。

除了技术,还有关于产品的想法,对游戏设计的想法,比如分享玩过游戏啥的。

还有,既然换了新地方,这也不是CSDN了,我将来会更多的分享我看过的书,看过的电影,体验过的设备,写些和技术无关的东西。这样的模式,最后可能接近阮一峰的博客 ,不知道最后能发展成什么样,都尝试一下吧。

阅读全文....

UnityScript程序设计语言

UnityScript(即javaScript for Unity)的教程网上千千万, 中文的也不少, 但是讲Unity3D界面操作的多, 讲UnityScript这个语言的少, 同时对于UnityScript的描述部分, 也是入门的教程多, 对语言特性的描述少, 能够成系统的我就根本没有找到过. 连续的看了不少的Unity3D的文章, 书籍, 但是发现写代码的时候, 对UnityScript的细节掌握仍然不甚了了, 也就是对怎么写UnityScript效率更高, 更加符合语言设计的目的, 风格等事情并还没有清晰的认识. 这个对于习惯写脚本的人来说, 可能是常态, 对于习惯C++我来说, 简直难以忍受.

看到这样的名字, 学过编程的人都知道我是模仿了经典的C语言教材, 目的也是一样. 本文的目的不是再多写一个教程, 而是希望对UnityScript这个语言进行一个较为深入细节, 并且准确的描述. 也就是说, 相对于教程, 本文会更加像一个语言说明书. 同时, 更不用说的就是, 本文会甚少涉及Unity3D本身的界面操作, 仅仅关注于UnityScript这个语言, 不要希望通过本文学会Unity3D, 但是, 当你对Unity3D有了些基本的了解后, 希望写一个大型游戏时, 本文会对你该怎么写脚本, 怎么写对脚本, 怎么样写好脚本, 并且避免掉进语言的陷阱中有一些帮助.
更进一步的说, 因为UnityScript完全是Unity3D控制的语言, 同时仅在Unity3D中可用, 所以对于UnityScript来说, 甚至于连哪些是属于语言本身的特性, 哪些属于库的扩展, 这些都分不清楚. 这比Objective C还混乱… 在Unity里面想要完全的区分开库和语言几乎不可能, 但是本文还是会尽量做这方面的尝试, 尽量将本文的主要关注点放在语言上, 而不是库上.

阅读全文....

怎样在Unity3D中使用Json

Unity3D中的javascript有些特异,和普通的javascript差异很大,其中eval就没法在iOS下使用(其实我在桌面版本也没有使用成功过)使得Json解析这种在javascript中非常原生态的事情变得不那么直接了。

直接使用eval后Unity3D给的错误信息很高端,我是没有看懂,应该是没有找到eval这个通用的函数:

Mono: AssemblyAssets/Scripts/Example/JTianLingExample.js(1,1): BCE0172: `UnityScript.Scripting.IEvaluationDomainProvider' interface member implementation must be public or explicit.

在网上找到了litjson库,通过这个支持.Net的库来曲线救国,折腾了一下,基本搞定。看网上讲litjson的资料很少,并且以C#居多,我这里就记录一下。

LitJson配置步骤

1.讲litjson的源代码中所有.cs文件放到Unity3d的assets中的plugins目录下,当然,在plugins下再建一个目录最好。Unity3D文档描述中plugins目录中的脚本会先运行,这样保证在我们写其他脚本的时候,litjson已经加载并运行好了。不然的话,等着报这种错误吧:
Mono: Image addref Mono.Cecil 0x1757740 -> /Applications/Unity/Unity.app/Contents/FramAssets/Scripts/Example/JTianLingExample.js(5,20): BCE0018: The name 'LitJson.JsonData' does not denote a valid type ('not found').

2.讲源代码放到plugins目录下后,会发现在Unity3d的editor中运行已经正常了,但是monodevelop中写javascript来调用litjson还是会报错误,也就是说monodevelop还是没有先运行litjson。因为C#的代码和javascript的代码在Unity3d生成的 项目中实际在几个不同的Project中,我们需要再配置一下:
在MonoDevelop中的Project->Edit Reference->Projects中,选择一下引用项(就像VS中添加项目依赖一样)
这里我们也会看到,放在plugins目录下的会放在Assembly-CSharp-firstpass中,而一般的脚本会放在Assembly-CSharp目录中。选上Assembly-CSharp-firstpass。

此时再在MonoDevelop中编译代码,顺利编译成功。

LitJson使用方式

1.解析json:

var s : String = '{"name":"jtianling", "phone" : ["135xxx", "186xxx"]}';
var json : LitJson.JsonData = LitJson.JsonMapper.ToObject(s);
print(json['name']);

if (json['phone'].IsArray) {
  for (var json_data : LitJson.JsonData in json['phone']) {
    print(json_data);
  }
}

输出名字和两个电话号码,如上所示,其实直接把JsonData当一个Map使用就好了,同时,还有一堆用于判断类型的IsXXX变量。比如,上例中,判断是否是数组的变量就是IsArray。

2.生成json字符串:

var data : Hashtable = Hashtable();
data['name'] = 'aaa';
var array : Array = Array();
array.Add('haha');
array.Add('haha2');
data['good'] = array;
var data_string : String = LitJson.JsonMapper.ToJson(data);
print(data_string);

输出:{"good":["haha","haha2"],"name":"aaa"}

也就是把使用map的过程反过来而已,不详细描述了。

另外,我们读取配置文件的时候常常是从文件中读取,我发现用Unity3D读取文件也值得单独写写,这个下次再讲。

原创文章作者保留版权 转载请注明原作者 并给出链接
九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

UnityScript风格指南(UnityScript Style Guide)

公司最近要开新的Unity3d项目了,Google虽然有JavaScript Style Guide,但是UnityScript和JavaScript的区别实在大到了几乎不是同一种语言的地步,这个只能自己动手了。好在起码还能参考一下Google的style guide。

阅读全文....

疯狂猎鸟项目小结 -- 技术篇(主要是cocos2d-x相关)

上次写了篇关于自己浅薄的管理经验的博客,被一些筒子们批评了,这次还是写篇技术贴吧,这样就不会有人说了,因为......那些人看不懂。该文早就和肖寒泉说了要写,但是因为写完后感觉好话不多,技术不多,就一直没有发布,现在我们又要开新项目了,而且不使用cocos2d-x了,那就发布了吧。

先说游戏引擎,疯狂猎鸟用的游戏引擎是cocos2d-x。

在一年多前(大概有这么久吧)就搜遍互联网,去寻找一个能跨win32,iphone平台的开源引擎,以方便进行iphone游戏的开发,只有很少的几个选项,甚至尝试过irrlicht不成熟的opengl es版,最后也尝试了orx,其实都不算特别理想,那个时候cocos2d-x刚刚出来没有多久,第一个支持的手机种类是沃phone,而iphone版本的demo都跑不顺畅,所以没敢使用。那个那时真的是有心自己写一个,无奈能力有限,但是很认可cocos2d-x的方向。

一年以后,当我开始再次为团队选择游戏引擎的时候,又一次的看了一下cocos2d-x,在查看了一下已经与cocos2d无异的demo后,说实话,相当长信心啊,我觉得自己能用到的特性也不会超过cocos2d-x的demo多少,那这样说的话,cocos2d-x就能用了,即使还有bug或者有什么平台相关的问题,因为cocos2d-x是开源引擎,那也不用怕,这也算是开源引擎的一个竞争优势,那就是不用100%成熟就能让人有信心使用。

初步研究后,作为传统的C++开发者(请允许我这样称呼自己),会有些受不了在C++中模拟objc的那种内存管理方式和类的初始化方式。看了cocos2d-x官网上的《Cocos2dxSimpleGame & Tutorials for beginners》后,就能很直接的感受到,cocos2d-x就是为移植而生的,所以文中一再的强调从cocos2d(objc)到cocos2d-x(C++) 几乎句句对译的优势,其实这个优势在真正用C++做原生开发的时候,就比较悲剧,因为这样的使用方式,根本就不是C++ style,你会感觉到内存不是完全在自己的控制之下。再进一步的看到cocos2d-x用C++实现的CCObject,CCAutoreleasePool,用于模拟objc的内存管理方式时,我觉得很悲催,cocos2d-x的作者们太辛苦了....然而,这还不算什么, CCArray,CCSet等objc容器和CCImage出现的时候,我近乎老泪纵横了,这是准备用C++实现一个objc吗?还带cocoa的......这可是GNU组织都没有实现的目标啊......开源社区的强大,让我感叹不已。

技术上,我能讲的东西不多,因为2D方面的东西也的确没有太多好讲。内存管理上,对于初学者,特别是刚刚毕业,学了点C++,连C++本身的内存管理都还没有弄明白的人,看到cocos2d-x绝对是晕的。建议是了解一些objc+cocoa的东西,最好是用过cocos2d,那样你就会明白那么多看起来别扭的设计是怎么来的了。其中,假如真的团队是初学者,那么可以完全限定不用autorelease那一套(也就是SpriteWithXXX那种接口),完全要求使用new来完成对象的创建,同时只是使用Release接口来完成内存释放,其中的管理还是自己完全接手即可,需要注意一个问题在于讲cocos2d-x编译成动态库时(iphone上不存在此问题),这样的做法不满足内存在哪分配在哪释放的原则(内存空间不同的问题),会crash。使用类似autoreleasepool时,实际相当于把最后一次引用技术放到了内存池中,每个循环都会集中清理一次,不用当心完全不会释放。
delegate的模拟机制做的不是很好,因为C++天生就不是适合干这个事情的材料,再加上Object的引用计数等问题,比如Action的回调使用时,保持Action的回调对象存在,一直加一个引用计数啥的(不知道是不是这个意思),容易导致内存管理混乱,同时,delegate的使用很混乱,因为用的是一个单独的基类来管理所有的回调类型。C++11的function,bind假如能用在这里,感觉设计上会清楚无数倍。
抽象上,cocos2d本身是单平台引擎,所以底层的设计本来就没有太多的考虑跨平台的事情,cocos2d-x比较单纯的去模仿,所以在平台抽象上做的就不是很好,比如渲染引擎的切换(opengl,opengl es,directx之间)就没有,导致win32上长期是opengl es加模拟(依赖于厂商的),平台的抽象也不是很好。建议参考irrlicht的抽象方式,哪怕是orx也好。
上面讲了那么多不好的地方,都是我们实际使用的时候碰到的问题,但是总体来说,cocos2d-x还是目前你想开发跨平台2d游戏最好的选择,上面也许只能说是爱之深恨之切吧。
其他的技术方面,texture packer很好用,值得买,particle designer也是粒子编辑器不二的选择。

阅读全文....