一、简介
我们要做的是怎样一款游戏?
在前不久成都TGC2016展会上,我们开发了一款《火影忍者手游》的体感游戏,主要模拟手游章节《九尾袭来 》,用户化身四代,与九尾进行对决,吸引了大量玩家参与。 表面上看,这款游戏与其它体感体验无异,实际上,它一直运行于浏览器Chrome下,也就是说,我们只需要掌握前端相应技术,就可以开发基于Kinect的网页体感游戏。
二、实现原理
实现思路是什么?
使用H5开发基于Kinect的体感游戏,其实工作原理很简单,由Kinect采集到玩家及环境数据,比如人体骨骼,使用某种方式,使浏览器可以访问这些数据。
1、采集数据
Kinect有三个镜头,中间镜头类似普通摄像头,获取彩色图像。左右两边镜头则是通过红外线获取深度数据。我们使用微软提供的SDK去读取以下类型数据:
色彩数据:彩色图像;
深度数据:颜色尝试信息;
人体骨骼数据:基于以上数据经计算,获取到人体骨骼数据。
2、使浏览器可访问到Kinect数据
我尝试和了解过的框架,基本上是以socket让浏览器进程与服务器进行通信 ,进行数据传输:
Kinect-HTML5 用C#搭建服务端,色彩数据、尝试数据、骨骼数据均有提供;
ZigFu 支持H5、U3D、Flash进行开发,API较为完整,貌似收费;
DepthJS 以浏览器插件形式提供数据访问;
Node-Kinect2 以Nodejs搭建服务器端,提供数据比较完整,实例较多。
我最终选用Node-Kinect2,虽然没有文档,但是实例较多,使用前端工程师熟悉的Nodejs,另外作者反馈比较快。

Kinect: 捕获玩家数据,比如深度图像、彩色图像等;
Node-Kinect2: 从Kinect获取相应数据,并进行二次加工;
浏览器: 监听node应用指定接口,获取玩家数据并完成游戏开发。
三、准备工作
先得买个Kinect啊
1、系统要求:
这是硬性要求,我曾在不符合要求的环境下浪费太多时间。
USB3.0
支持DX11的显卡
win8及以上系统
支持Web Sockets的浏览器
当然Kinect v2传感器是少不了的
2、环境搭建流程:
连接上Kinect v2
安装 KinectSDK-v2.0
安装 Nodejs
安装 Node-Kinect2
npm install kinect2
四、实例演示
说什么都不如给我一个例子!
如下图所示,我们演示如何获取人体骨骼,并标识脊椎中段及手势:

1、服务器端
创建web服务器,并将骨骼数据发送到浏览器端,代码如下:
var Kinect2 = require('../../lib/kinect2'),
express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
var kinect = new Kinect2();
// 打开kinect
if(kinect.open()) {
// 监听8000端口
server.listen(8000);
// 指定请求指向根目录
app.get('/', function(req, res) {
res.sendFile(dirname + '/public/index.html');
});
// 将骨骼数据发送给浏览器端
kinect.on('bodyFrame', function(bodyFrame){
io.sockets.emit('bodyFrame', bodyFrame);
});
// 开始读取骨骼数据
kinect.openBodyReader();
}
2、浏览器端
浏览器端获取骨骼数据,并用canvas描绘出来,关键代码如下:
var socket = io.connect('/');
var ctx = canvas.getContext('2d');
socket.on('bodyFrame', function(bodyFrame){
ctx.clearRect(0, 0, canvas.width, canvas.height);
var index = 0;
// 遍历所有骨骼数据
bodyFrame.bodies.forEach(function(body){
if(body.tracked) {
for(var jointType in body.joints) {
var joint = body.joints[jointType];
ctx.fillStyle = colors[index];
// 如果骨骼节点为脊椎中点
if(jointType == 1) {
ctx.fillStyle = colors[2];
}
ctx.fillRect(joint.depthX * 512, joint.depthY * 424, 10, 10);
}
// 识别左右手手势
updateHandState(body.leftHandState, body.joints[7]);
updateHandState(body.rightHandState, body.joints[11]);
index++;
}
});
});
很简单的几行代码,我们便完成了玩家骨骼捕获,有一定 javascript基础的同学应该很容易能看明白,但不明白的是我们能获取哪些数据?如何获取?骨骼节点名称分别是什么?而node-kienct2并没有文档告诉我们这些。
五、开发文档
Node-Kinect2并没有提供文档,我将我测试总结的文档整理如下:
1、服务器端能提供的数据类型;
kinect.on('bodyFrame', function(bodyFrame){}); //还有哪些数据类型呢?
| bodyFrame | 骨骼数据 |
| infraredFrame | 红外数据 |
| longExposureInfraredFrame | 类似infraredFrame,貌似精度更高,优化后的数据 |
| rawDepthFrame | 未经处理的景深数据 |
| depthFrame | 景深数据 |
| colorFrame | 彩色图像 |
| multiSourceFrame | 所有数据 |
| audio | 音频数据,未测试 |
2、骨骼节点类型
body.joints[11] // joints包括哪些呢?
| 节点类型 | JointType | 节点名称 |
| 0 | spineBase | 脊椎基部 |
| 1 | spineMid | 脊椎中部 |
| 2 | neck | 颈部 |
| 3 | head | 头部 |
| 4 | shoulderLeft | 左肩 |
| 5 | elbowLeft | 左肘 |
| 6 | wristLeft | 左腕 |
| 7 | handLeft | 左手掌 |
| 8 | shoulderRight | 右肩 |
| 9 | elbowRight | 右肘 |
| 10 | wristRight | 右腕 |
| 11 | handRight | 右手掌 |
| 12 | hipLeft | 左屁 |
| 13 | kneeLeft | 左膝 |
| 14 | ankleLeft | 左踝 |
| 15 | footLeft | 左脚 |
| 16 | hipRight | 右屁 |
| 17 | kneeRight | 右膝 |
| 18 | ankleRight | 右踝 |
| 19 | footRight | 右脚 |
| 20 | spineShoulder | 颈下脊椎 |
| 21 | handTipLeft | 左手指(食中无小) |
| 22 | thumbLeft | 左拇指 |
| 23 | handTipRight | 右手指 |
| 24 | thumbRight | 右拇指 |
3、手势,据测识别并不是太准确,在精度要求不高的情况下使用
| 0 | unknown | 不能识别 |
| 1 | notTracked | 未能检测到 |
| 2 | open | 手掌 |
| 3 | closed | 握拳 |
| 4 | lasso | 剪刀手,并合并中食指 |
4、骨骼数据
body [object] {
bodyIndex [number]:索引,允许6人
joints [array]:骨骼节点,包含坐标信息,颜色信息
leftHandState [number]:左手手势
rightHandState [number]:右手手势
tracked [boolean]:是否捕获到
trackingId
}
5、kinect对象
| on | 监听数据 |
| open | 打开Kinect |
| close | 关闭 |
| openBodyReader | 读取骨骼数据 |
| open**Reader | 类似如上方法,读取其它类型数据 |
六、实战总结
火影体感游戏经验总结
接下来,我总结一下TGC2016《火影忍者手游》的体感游戏开发中碰到的一些问题。
1、讲解之前,我们首先需要了解下游戏流程。
您可能想查找下面的文章:文章分类最近更新的内容 |

