我之前在MAX大会中谈过一个主题,是将游戏控制器集成到FLEX/AIR/ActionScript应用里面,从而让游戏的互动更加流畅自然。目前已经有很多使用Wii控制器的例子--鉴于下一代视频游戏平台即将到来,我最好想花一些时间在近期最棒的Microsoft Kinect上。
对于那些不太了解Kinect的人,可以将它看成是一对摄像头,一个是RGB(和平常的摄像头一样),另一个是红外线摄像头。两个摄像头在一起(也包括一对电子元器件和软件)允许Kinect深度探测。这意味着追踪人,手的行为变得不那么复杂。Microsoft Kinect 事实上是 PrimeSense开发的,它最早是为PC提供这种装备,而不是游戏平台。这说明这个装备实际上是兼容PC的,而不必再去借助一堆不常见的方法。
让Kinect工作起来最困难的事是搞定所有需要的组成部分,并让他们一起工作 。文档支持很少(通常在GitHub的文本文档中找到)。综合起来问题是,多则上百,少则几十的开源的项目--不幸的是,它们每个都依赖不同的驱动,中间件和API -- 很多都相互不兼容。
我要说明的是我并不是这些所有领域的专家,但是我根据一个线索顺来展开工作(在很多失败的尝试后)。Matt LeGrand和我打算开一个独立站点和博客来探索其他更多的方法来帮助人们做正确的筛选。我的经验首先是开Windows 7上运行Kinect,我知道我的老的Mac笔记本不足以支持Kinect。是的,你需要更先进的电脑来使用Kinect。
然后,从哪开始?很明显,你需要Microsoft Kinect控制器的实物。目前有两种型号--一种是USB only,另一种是USB+能量供应。USB only的版本只能搭配Xbox。USB+能量供应的版本搭配PC(Kinect使用一点小的电量可以让Xbox通过USB提供)。两者不同的地方是能量盒和USB能量注入模块。如果你因型号问题没有成功,可以尝试购买能量盒和USB能量注入模块。我并不确定哪里可以买到。我是从Best Buy上的视频游戏翻版通道购买的(使用优惠券后,大约是100美元)。新的大约是140美元。
在使用前,你需要安装驱动、中间件和API。有三个知名的驱动包和中间件,有一个是我直接从PrimeSence下载的,它被我选用。驱动和中间件存放在OpenNI的官网http://www.openni.org/downloadfiles/opennimodules。有三个你需要下载--OpenNI模块(OpenNI Binaries),PrimeSense NITE中间件,PrimeSense驱动(OpenNI适用的硬件驱动)。下载32-bit的文件,及时你使用的是64位的Windows 7。使用的64位的驱动会碰到很多的问题,让事情中断。安装好驱动,然后是中间件,然后是OpenNI的驱动。
最后,你需要AS3模块。有一个开源的项目叫做AS3OpenNI,它让对于OpenNI API的编程变得非常简单。因为AIR不能直接和API通讯,你必须使用内置的C++应用代理驱动调用TCP/IP连接。我确信这会在后续的AIR版本中变得更加简单。AS3OpenNI取得从OpenNI返回处理过的数据,然后给到骨骼数据(作为一个类),RGB,深度或者多点触控点数据。通过这些数据,你可以从多个用户读取返回的数据,然后追踪他们的手,投,脖子,腿等等。我是基于稳定的1.3.0版本创建应用。
看一下AS3OpenNI项目中的例子--它们充分展现,一旦你让所有部件都一同工作,它们会运行得很好。
然后,我用Kinect做什么呢?我的第一个游戏是“太空入侵者”的简易版本。我使用AS3OpenNI追踪右手让玩家从左到右移动,当右手在脖子的中间点经过的时候,会发射一枚导弹。以下的代码是必须的全部代码(除了玩家的建立部分,等等):
protected function gotShipMove(event:ONISkeletonEvent):void
{
var rightHand3D:NiPoint3D = event.rightHand; // get the right hand's x,y,z
var rightHand:NiPoint2D = NiPoint3DUtil.convertRealWorldToScreen(rightHand3D, this.stage.width, this.stage.height);
shipIcon.x = rightHand.pointX;
if ((event.skeleton.rightHand.pointY > event.skeleton.neck.pointY) && canFire)
{
if (!fireInProgress)
{
fireInProgress = true; // prevent 5,000 missiles from firing at once...
var missile:MissileItem = new MissileItem(spaceInvadersCluster);
missile.x = rightHand.pointX;
missile.y = height - 64;
missile.addEventListener("MissileFireComplete", missileFireComplete);
missile.addEventListener("MissileFireHit", missileFireComplete);
addElement(missile);
}
}
else
{
fireInProgress = false;
}
}
可以查看我的Twitter来获取更多关于我们(Matt和我)专门Kinect和AS3网站的信息,在MAX大会上,我会更多地涉及到游戏,所以届时一定要来。