离开R-Tank

9 月 22 日了,记得去年年末的时候,我们开始了 R-tank 项目,经过两次的重构,并尝试了三种不同的实现方式,即使这个项目最终未能吸引很多人的注意,但也积累了不少的经验。

由于一直以来都是独立开发,所以并没有在博客上写起关于 R-tank 项目的细节。R-Tank 项目其实是由 Lu 学长发起的以 WIFI 远程控制为基础的智能玩具项目。想法其实在国外已经有实现了,不过在去年的国内,还是一个很新奇的想法。于是,我们(LuDa、WeiJianwen、GuoZiyi等)开始了这个项目的构建。

看着以前简陋的草图还觉得挺好笑的:

架构草图

不过可以体现出我还是很努力地尝试把这个项目构建好。上图中的所有线表示一个 TCP 连接或者内部调用,可惜当时没分清,所以都用实线了。这幅图应该是最后一次维护的时候画的,已经从 UDP 转移到 TCP 来管理连接。

简要地说明一下,NetBase 类是一个抽象的基类,负责提供一个消息传达者的作用,维护一个。里面有 3 个方法,分别是发送往第几个客户端的。然后交给子类来实现不同的网络操作。这样看上去的架构还是挺完善的,不过,可惜的是,不一致的网络消息发送导致维护成本的提高,以及用 TCP 导致广播消息的困难,都是这个项目的挑战;另一方面,消息协议的确定也是一个难题,如何同步游戏中各种数据也是一个难题。


一些小插曲:

  • 一开始的 UDP 本来也可以很好地工作,不过要耗掉很多电量用于同步。而用 UDP 实现注意的问题或许就在于同步信息的时机:不能频繁发送,也不能只发送一次。
  • TCP 与 UDP 论战,最后由于不了解 UDP 如何“不可靠”。于是,放弃 UDP 采用 TCP 。并用测试连接来确定网内的其他客户端。确实获得了更好的连接效率。
  • 有点错误地用 Java NIO 来实现 TCP 连接。而不阻塞的 IO 对于无状态网络服务来说应该是可用的,但不是所有的网络服务都是无状态的。而且,NIO 强调数据的可控制性,大量应用 Buffer 类,是否完成是不确定(因为不阻塞),所以考虑情况很多。导致这个项目在这个阶段耗费了大量时间。
  • 确定 NetBase 类的稳定 API 。采用原始 Java Socket 进行最后实现。

又到开学时

这周估计很多学校都开学了,虽然东北这边已经开学两周了。

这两周以来其实也没重要的事情。分析了目前的市场形势后,我们团队还是决定放弃原来的Rtank计划。学长也紧张地找工作了。而我打算把以前所做的工作在这里开放。估计会在9月20日左右开放源码。提供一个简易的网络开发模块。暂定名为RNetBase。这个模块的设计之初是为了支持远程控制玩具坦克的。也是我第一次尝试设计,这次也使我深深地感受到,不是各个模块设计好,连接就一定顺利的。现实世界还是被自然控制得很好,很多物件都很灵活,而虚拟世界里面,需要你自己去控制。

2012-8-23

昨天又回到沈阳了,准备新学期的学习。这个学期要学的内容真的很多,包括大学里学分最多的课都在这个学期了。三门重点课程更是我所希望了解的。不过,暂时对此还没有很多计划。不过可以肯定,必须更勤奋了。

在上个学期末,给这个假期定的计划是放松。不过,实际上真的放松不了。回家前定的两个项目,一个为视点网写的Android客户端以及学院希望我们提交的WindowsPhone程序。前一个错误地估计了HTML 5的普及,现在得用Android原生界面重写。大概在新学期的时候可以完成。

在完成Android的程序的时候,也发现了不少有趣的内容,例如,超越所有构造函数的匿名构造函数:

class TestClass {
	private int a;
	private Integer b;
	private long c;

	{
		a = 1;
		b = new Integer(a);
	}

	public TestClass(long c) {
		this.c = c;
	}
}

中间用 { ... } 括起来的就是一个匿名的构造函数,独立于所有构造函数,无论调用哪个构造函数,都会先调用这个构造函数。挺有用的吧。对于静态变量,可以用 static { ... } 来初始化。

另一些发现则是和Android的Looper、Handler、Message类框架有关的类。Looper类的构造和Thread类密切相关,而且Thread类的静态方法Thread.currentThread()可以唯一确定一个Thread然后制作一个线程池进行管理。Looper类的消息机制也建立与此。而且,利用Handler类的消息延迟发送功能,可以巧妙地构建动画,而且这个动画还在当前UI线程,可以安全地更新UI。

 

浅谈 HTML 5

当然,我知道,聪明的你肯定也知道,HTML 5只是一个噱头而已,真正讨论的是移动互联网开发。

近几年来,在Web标准沉默了很多 年以及IE 6独占市场很多年以后,HTML 5神话地打破了这个局面,使得Web标准重新成为标准,并不受一家限制。这个主要归功于成功的开源HTML解释引擎Webkit(感谢Webkit、感谢 Apple,不过,其实真正该感谢的还是KDE,因为不是KHTML严格的GPL,Apple不知道会不会把拿KHTML来改造的Webkit开源 呢~)。不受平台限制,所以最终在几乎所有手机浏览器的内核都是Webkit(自带浏览器)。

不过,HTML 5真的还有很长的路要走。

近 几年来,HTML 5标签的变化主要集中在替代Flash的解决方案上,包括Canvas、Video以及Audio标签,至于其他标签,实际上可以通过CSS进行定制来模 拟,甚至很多标签基本没有所谓的式样,只是语义。但语义Web,我觉得是,HTML从创建之初就是用来格式化的,为什么语义?语义也应该是格式化上的语 义。

相比Flash,从设计之处就支持打算支持硬件加速的Canvas、Video以及Audio标签使页面运行更为流畅、自然。三个功能 单一化的标签,使得维护更容易。Video和Audio现在的问题就是如何维持浏览器之间的兼容性。而Canvas,其中一个很严重的缺点就是内容难以描 述,基于位图操作的Canvas对于图表,描述性自然是很差的,但愿SVG动画能够填补这个空白。Canvas的出现大概是为了游戏。但 JavaScript引擎的设计大多数是基于单线程的,对于游戏设计来说性能还是不好。

但HTML 5实际上伴随的变化,还在于CSS 3建立的互动模型。由于Webkit的流行,支持HTML 5就等于支持CSS 3。而CSS 3的动画、过渡、坐标变换等内容大大增强了HTML 5的表现力,实际上从原来基于函数的操作转换为基于模型(利用CSS 3的选择器来建模,然后用JavaScript调用模型之间的变化关系,其余操作由CSS动画过渡模块来解决)。这样,动画交互设计变得容易,静态的内容 真正动态化、互动化,革新了以往对Web纯静态平面设计的概念。但CSS 3现在面临的问题是,缺少对动画状态的描述。

说到CSS 3,不得不提的是硬件加速。相对于用JavaScript来实现的动画来说,CSS 3动画显然会更为流畅(浏览器的绘制的优化)。于是,很多动画框架从CSS 3中寻找解决方案,希望利用CSS 3来实现流畅的动画效果。但由于现阶段的CSS 3还缺少流程控制,还有基于CSS 3本身基于模型的设计。到底应不应该用CSS 3来达到除了互动以外的动画特效目的?还是浏览器应该定义一套支持硬件加速的基本API(WebGL?)来实现?

HTML的设计到现在来说还有一个很严重的问题——页面跳转间没有过渡效果。这个问题在jQuery Mobile中通过AJAX拉取页面然后动态插入DOM来解决,但这样实际上做了很多复杂的工作,代码兼容上也有问题。模拟的就绪事件还是不能和DOM就绪事件相比。

HTML 5还有一个很重要的组成部分就是JavaScript,这个逻辑与表现的桥梁。动态语言的优点或许不用我说了。而JavaScript有着和动态语言的通 病:难以进行静态语法分 析来进行上下文提示(这或许也是JavaScript没有神什么好用的IDE的原因之一)。那么使用这套语言的人必须十分清楚对象是什么,以及类有什么 API,否则,面对一个JS对象将无从下手。动态语言屏蔽了类型差异,为快速开发打下基础,但是模糊的语义在某些情况下又使得开发难度增加。

好了,先说到这里吧,有时难免情绪化,若有些错误,希望大家指出。也希望大家给出自己的意见。感谢收听~

 

Java NIO笔记 Channel

记得第一次做计算机网络的实验课的时候,我用多线程实现了一个HTTP服务器,然后对能够同时对应多个客户端的读请求十分满意。没想过线程的开销问题。不过,后来在手机端设计一个需要同步读写的服务器的时候,才突然发现,要实现维护多个线程的同时,同步读写并不是那么容易的事情。

文中有什么问题,希望指出完善。:-)

Java NIO笔记 ByteBuffer

最近在做一个网络相关的应用,考虑到效率问题,参考了NIO库的实现。NIO库大概更接近C/C++的Socket编程,采用非阻塞的设计,以及Selector事件驱动的设计,感觉还是不错的实现。以下内容只是整理作为参考,可能有不少错误,希望对大家有帮助。如果有更好的实现方法,或者我理解上的一些问题,希望指出,共同学习。

关机脚本(Linux,依赖于ConsoleKit)

为了更方面地用 Awesome 作为主窗口管理器,于是参考了 Blingbling 模块的关机/重启按钮,写了两个小脚本。使用 ConsoleKit 来实现关机/重启操作,使用 zenity 图形化。

关机脚本(ck-shutdown,因为使用了ConsoleKit)

#!/bin/sh

if zenity --question \
          --title "Reboot?" \
          --text "Are you sure to reboot?";
then
    dbus-send --system --print-reply \
              --dest="org.freedesktop.ConsoleKit" \
              /org/freedesktop/ConsoleKit/Manager \
              org.freedesktop.ConsoleKit.Manager.Restart;
fi

重启脚本(ck-reboot):

#!/bin/sh

if zenity --question \
          --title "Shutdown?" \
          --text "Do you want to shutdown?";
then
    dbus-send --system --print-reply \
              --dest="org.freedesktop.ConsoleKit" \
              /org/freedesktop/ConsoleKit/Manager \
              org.freedesktop.ConsoleKit.Manager.Stop
fi

不过看到 freedesktop 上 ConsoleKit 项目的介绍,似乎 ConsoleKit 的开发并不活跃,可能被 Systemd 相关项目替代。不过至少现在可以正常在 Ubuntu 12.04 下使用……

Qt和HTML笔记:初始化

为了应对最近的比赛,但对很对 GUI 系统都不怎么熟悉,而且又要用 C++ 进行项目核心代码的编辑。RetVal 希望团队做出一个很炫的图形界面,不过,对 C++ 的窗口系统还真的不熟悉。于是尝试用 Qt 和 HTML 5 来进行界面的编程,也算是一个新挑战。

不过似乎关于 Qt 和 HTML 5 的中文资料还不多,于是整理一下笔记吧。这个博客也很久没更新了……

TankII 一点小更新

发现又很久没更新博客了。

用Box2D重写了TankII,然后绘制则用了AWT和类似于Page flipping的技术,在Windows上绘制看起来是挺流畅的。至于可能有点慢,并不是画面跟不上,而是我设的速度限制而已。这次的版本,虽然地图做的还是很次,但代码管理上应该有不少进步了。眼看就开学了,不知道还有多少时间会像现在这样慢慢地开发程序。不过,有期待的就会有收获。

快速按坐标分类的方法还是没找到,不过现在的绘制速度还可以,于是也没找别的方法来提高绘制速度了。有空还是得转向OpenGL,现在用的Java2D虽然也是跨平台,但是不一定得到很好的硬件加速。而且Android的开发似乎也会是OpenGL的。用OpenGL对于平台切换也简单点吧。

下载:http://www.box.com/s/17djfttkvrovpn05ognv 源码应该会在不久后也上传的,现在没整理好,就没上传了;大概也不是很多人会看……

今年回来,还是有点无奈。不过走到现在,其实有很多人帮助过我了,要知道感恩生活,才知道快乐。

迭代器

看了一下nihui的博客,看到了QList的使用,于是有点好奇,然后 csslayer 的讨论更挑起我的兴趣,于是去搜索QList和QMutableListIterator类,找到http://doc.trolltech.com/qq/qq12-qt4-iterators.html,Qt 4 的迭代器的使用。

其实我一直觉得 STL 的迭代器很奇怪,使用*、[]、++、--等运算符来操作,一开始我竟找不到如何使用这一套看似十分强大的库函数的方法,而且编程思路和很多调用不一致。

vector<int> a;
vector<int>::iterator iter = a.begin ();
while (iter != a.end ())
{
  cout << *iter << endl;
  iter ++;
}

为什么就想到用 * 来取元素呢?既然 iter 不是指针,这个操作符就不应该用啊……不过 C++ 还是用了,而且用得也很巧妙……

呃,我觉得很大程度上是因为我一开始学的是 Java 吧,现在越来越觉得其实编程语言的不同本质上是编程思想的不同,编程思想类似的语言,像 Python 和 C++ ,如果你知道怎么用 C++ 会很快就找到如何使用 Python 的。

很好奇为什么 Qt 的 QTL 居然可以和 STL 共存且兼容,可以使用 STL 里 agorithm 头文件里面声明的算法。然后那篇文章里提到的一点

The STL iterator syntax is modeled after the syntax of pointers into an array. This makes it possible to use STL's (or Qt's) generic algorithms on a plain C++ array.

然后我明白了,原来 C++ STL 里面的迭代器模型就是指针,所以所有关于指针取值、前后运算的操作符都可以用在迭代器上,而且是那么自然,更重要的是 C++ 的模板是没有类型检查的,只要最终类型支持在模板函数里用到的那些方法即可。

那篇文章里面提到的有关迭代器内容修改、遍历的问题我觉得都说的很有道理,不一一翻译了,推荐一看

更详细的 Qt 4 文档:http://developer.qt.nokia.com/doc/qt-4.8/containers.html