资料收集[置顶]
在这边放一些有用的资料索引,方便自用,慢慢收集整理了
git入门推荐,中文的哦
http://progit.org/book/zh/
twitter的scala教程
http://twitter.github.com/scala_school/index.html
stackoverflow的scala tag
http://stackoverflow.com/tags/scala/info
markdown语法
http://daringfireball.net/projects/markdown/syntax
虚跟模板可以兼得?!
由某个案例引发出来...
为什么要虚
在OOP的开发过程中,往往会有大量对象的定义和使用,很多时候我们需要将这些对象持久化的保持在外部文件里面,然后再在需要的时候将其读取进来。因为对象的类型数量都很多,一个一个去实现如何写入和读取就特别冗余且笨重。常见的解决方式便是序(反序)列化,简而言之就是为对象的基类都加上serialize/deserialize的虚方法,然后子类只需要实现如何组织需要写入和读取的数据就可以了。此后我们只要有一个serializable的对象便能对其进行读写了。
为什么要模板
但是关于具体的序列化的时候,便会遇到一些跟平台相关的问题,比如不能确定这个对象最后写入到的是一个本地文件、网络流还是JSON这样的中间载体的时候该怎么办?因此我们提供给序列化接口的序列化器这时变得不那么确定了。此外我们也不希望对象的序列化接口明确的知道序列化器是什么,因为这样会让其产生依赖使得对象的使用不独立。综上,我们希望一种模板化的序列化器,只有到对象用到它的时候才会被具体的展开使用。
虚跟模板可以兼得?!
所以我们需要给对象的基类定义一个方法看上去会是:
template<typename Serializer> virual void Serialize(Serializer& serializer);
但是遗憾的告诉你这是不可能的。为什么?
首先抛开C++的标准不说,单从编译器的实现上面就能否定这一点。虚函数具体是通过虚函数表来表现其多态性的,这个虚函数表实际上是一个函数地址的数组,在建立这个虚函数表的时候所有的虚函数都需要被实现了,这样才能找到有效的函数地址。但另一方面模板方法本身是并不存在的方法,只有在被用到的时候才被具体展开并实例化。因此模板方法的“不确定”性与虚函数的“必须确定”性在理论上便已经矛盾冲突了。
解决方案
首先,为了模板化,不得不先将virtual去掉,这样要求所有对象里面的序列号方法被重新声明为:
template<typename Serializer> void Serialize(Serializer& serializer);
但是作为序列化方法的调用者,它所能拿到的是所有对象的基类的指针或者引用,它也不能直接调用到子类里面的具体方法。为此目前我能想出的办法就是向下转型,例如:
void Serialize(Base& base)
{
FooSeraizlier fooSerializer;
switch(base.GetClassId())
{
case DeviedA::ClassID:
(static_cast<DeviedA*>(&base))->Serialize(fooSerializer);
break;
case DeviedB::ClassID:
(static_cast<DeviedB*>(&base))->Serialize(fooSerializer);
break;
case DeviedC::ClassID:
(static_cast<DeviedC*>(&base))->Serialize(fooSerializer);
break;
......
}
}
无奈的是类似这样switch case的向下转型必须要手写的,因此当类型过多的时候肯定是很悲剧的,但是如果你有类似python一类的脚本工具来帮你自动生成代码的话,那就放心的使用吧。
关于脚本
一些关于脚本的琐碎的思绪。
如果说Programming Language是对应基础框架以及底层兼容的偏硬性问题的解决方案,那Script Language便是某种意义上真正面向应用功能的解决方案。Programming Language的初衷是调用平台的各种资源与功能,为了达到最好的效果往往都是贴近底层开发的,在这方面“硬”的东西比较多,而且一旦敲定,便不会容易修改。简而言之,Hardcode大概就是这样一种意思。
太硬的东西无论是开发者还是客户都所不愿意见到的,他们不希望自己买了一辆自行车,轮子只能转到100圈,除非他们都是2B。
于是乎有一种叫Data Driven的概念出现了。大约来讲它属于已经被Hardcode编译成计算机本地指令的程序的外部配置信息。程序的代码已经实现了开发过程中能够预见的大多数功能,这些功能可以接收一定的可变的参数来达到一定程度的“动态性”。这基本上是目前绝大多数项目的一种比较统一的解决方案,无论是application,service或者game。
这种开发模式有一个比较重要的平衡点需要掌握:我们需要将多少功能给做出来,又需要将多少功能可以进行外部的配置。前者过多就会导致过多的硬编码,而后者过多就会导致过于零散的功能以及过于复杂的配置。
无论如何,硬编码是我们是在不想看到的,但是如果功能做得过于原子化,那外部的配置必然会相当复杂。要知道在一个团队里面,负责这部分数据生产的不一定都是城续猿。
有时候我们不能太明白的说明,我们到底想要一个什么样具体的功能,城续猿没办法做出一个抽象的模棱两可的功能然后再暴露一些有限的参数供团队里面其他成员使用,而后者往往也说不清楚自己到底想要什么样的东西。但就算双方能达成协议,通过修改代码来实现新功能以及调试的代价往往也是比较昂贵的。
那么,为何不让他们自己去做?
于是我们需要一种,简单,可用,且能比较高效开发的方式 —— 脚本。
理论上来讲脚本也是一种编码语言,它同样有分支,有循环,有变量,只不过其所在的层次不一样。脚本其实也是Data Driven里面的数据,只不过与单纯的贴图,动画,音效等纯数据相比它更有一种自我描述性。换言之它们能自己说明自己的目的,而不是简单的被贴到某个设置好了UV的模型上面去。
城续猿可以做好一系列的相对独立的功能,这些功能之间可以拼凑组合,相互调用,往往我们会将它们称之为API,最终它们会暴露给脚本使用。
在此基础上,如果说通过Programming Language实现的框架模型是“第一次开发”,那么通过Script Language我们可以在项目中进行“第二次开发”。这也就是一种理想的“准备阶段”往“生产阶段”过渡的方式。案例例如游戏中各种角色的AI,任务,界面UI等等。
待续…
Scala和Java的互操作
最近在实践中遇到一些Scala和Java互操作的问题,记录一下
BTW: gist + wordpress的gist插件各种好使啊 果断抛弃各种syntax highlighter插件
Scala Map Java Map
下面代码是两个隐式转换,用于在两者之间互转
Scala repeated parameters Java varargs
不好好看书就急着动手的杯具……纠结了很久才知道如何正确调用可变参数列表的Java方法
如果不使用: _*这个annotation告诉scala我要展开成varargs,不论你如果toArray如果反射new出Object数组都是没有用的,整个Array或者List会被作为一个Object传入,而不是展开成多个参数传入调用方法
来scala下Scala
Scala,所谓可伸缩可扩展,于是就蛋疼试试
首先因为scala的语句块都可以返回值,因此if else完全可以取代?:三元运算符的作用,不过写起来还是后者比较爽。那就自己扩展一把好了。
class BooleanEx(b: Boolean) {
def ?[T](func: Boolean => T) = {
func(b)
}
}
class AnyEx[T](o: T) {
def or(o1: T) = { b: Boolean =>
if (b) {
o
} else {
o1
}
}
}
object Helper {
implicit def Boolean2BooleanEx(b: Boolean) = new BooleanEx(b)
implicit def Any2AnyEx[T](o: T) = new AnyEx(o)
def main(args: Array[String]) {
(1 == 1) ? (true or false)
}
}
无奈的地方是没法使用冒号作为方法名(因为是关键字),以及?属于最高优先级层,所以后面的括号省略不能……
关于UI的若干纠结
话说最近哥对UI的感情那是各种的错综复杂,似乎业界使用Flash来做In Game UI逐渐成为主流。望着ScaleForm各种强大和稳健,看着自家的Homebrew的UI库,各种兴叹,无奈各种BOSS光环哥只能将错就错了。
既然说到UI不得不提到的就是走哪里都必须很吃香的PS各种版本,做UI总得画个图切个图啥的伐。不过PS各种切,Flash再各种导入,各种费时又费力。不过人家大牌厂家的东西都不是省油的灯,jsfl和jsx简直就是拯救哥于水火之中的各种救命草。(话说为什么我每次提到这些上面的人貌似有些漠视的感觉......)
简单来说Flash是支持只用导入一张完整的大图,然后基于这张大图创建若干小元件(Symbol,Movie Clip或者Graphic)的,原理就像CSS Spirit。不过如果你想人肉在Flash里面去切那你注定会各种杯具的,因为你会发现Flash的切图功能简直渣到几乎没有。
于是你必须需要jsfl了。我们可以通过jsfl来精确创建各种元件,所谓精切就是说你可以直接像素级别定为图块的各种上下左右而不是靠鼠标凭手感去割,于是:
// Get the document
var doc = fl.getDocumentDOM();
// Get the library
var lib = doc.library;
// Get the selected item in library
var libItem = lib.getSelectedItems()[0];
// Get current fill object
var fill = doc.getCustomFill();
// Set the style to "bitmap", available since CS4
fill.style = "bitmap";
// I don't know what is this neither
fill.bitmapIsClipped = false;
// Set the name of the selected item to the fill object
fill.bitmapPath = libItem.name;
// Well, to get some parameters about this bitmap, you have to instantiate one in the scene first
lib.addItemToDocument({x:0, y:0}, libItem.name);
// And then get the instance
var bitmap = doc.selection[0];
// Then you need to create a mystery matrix
var matrix = bitmap.matrix;
// The spirit's left bound
matrix.tx = -l;
// The spirit's top bound
matrix.ty = -t;
// God knows what does it mean
matrix.a = matrix.d = 20;
// Or Adobe either
matrix.b = matrix.c = 0;
// Set the matrix to the fill object
fill.matrix = matrix;
// And use it
doc.setCustomFill(fill);
// Then it is time to create the spirit
doc.addNewPrimitiveRectangle({left : 0, top : 0, right : r - l, bottom : b - t},0,false,true);
这随之而来就带来了第二个问题,我如何知道每个Spirit的各种上下左右边界,目测加人肉记录似乎可行,不过面对成百上千的各种图的时候,你只会喊破喉咙都没人能救你。 于是jsx这次向你伸出了上帝之手。
只要你在PSD里面将图按照每个Spirit一个图层的方式进行管理,并且每个图层之间相互没有重叠部分,那就可以通过jsx批量的将图层边界信息导出:
// Get the document
var doc = app.activeDocument;
// And prepare to store something
var code = "";
// Traverse all the layers
for(var i = 0; i < doc.layers.length; i++)
{
// Get current layer's bounds
var bounds = doc.layers[i].bounds;
// Concatenate the bounds info of every layer
if (code != "") code += "|";
// Make the bounds info of current layer
code += layer.name + "," + bounds[0] + "," + bounds[1] + "," + bounds[2] + "," + bounds[3];
}
然后你只需要将这生成的code里面的内容,通过各种方式整到之前的jsfl里面去,然后各种华丽你就懂得了。
呜喵王推倒达成
最近WOW国服+台服双线进行中。台服小战士85一身蓝绿环保人见人嫌排随机,国服小DK偶尔上线参加下活动。话说DK所在的10人固定团因为人员不太稳定,一直在各种便当,虽然开3.3第二个CD就见呜喵王了但却到昨天才成功推倒。想我的60、70年代都在各种AFK中渡过,终于参与开荒了80年代最终BOSS的我内牛满面。只是呜喵王的战斗虽然是我遇过的最复杂的(完全坑爹啊,0容错还得看脸),但是没有与之相衬的史诗感,总觉得没过瘾啊……
最近败了个台式机以及360就是贱啊
唔~顶不住诱惑败了个台式机。AMD羿龙IIX4 955、技嘉770T-UD3P、迪兰恒进HD6850~可以特效全开SC2的感觉太感动了……
但是买来后发现机箱中某风扇动静很大,开始以为是电源的……后来拆开按住CPU风扇发现不响了。好嘛,自带风扇果然不靠谱啊,看来又得出血败个风扇了。
然后为了看看CPU、显卡温度啥的,就去找来EVEREST,结果发现识别不到我的显卡,于是想起一个叫撸大湿的东西。放狗打开撸大湿主页,360旗下产品几个大字让我一下就缩卵了。事实证明这货果然是360的产品,安装后有一个bundle.exe偷偷的在我用户目录的temp目录下跑,打开看签名:Chengdu Qiying Technology Co. Ltd~没错,就是撸大湿的公司。先不管这东西是干嘛的,它偷偷摸摸跑在我temp目录下就可见用心不良,于是果断终止删掉然后卸载撸大湿。
btw:AIDA64,这个貌似就是EVEREST。原EVEREST已经不更新了,改这个名字了。
