一、简介
我们要做的是怎样一款游戏?
  在前不久成都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、环境搭建流程:
  1. 连接上Kinect v2
  2. 安装 KinectSDK-v2.0
  3. 安装 Nodejs
  4. 安装 Node-Kinect2
  1. npm install kinect2

  

四、实例演示
说什么都不如给我一个例子!
如下图所示,我们演示如何获取人体骨骼,并标识脊椎中段及手势:

1、服务器端
创建web服务器,并将骨骼数据发送到浏览器端,代码如下:
  1. var Kinect2 = require('../../lib/kinect2'),
  2. express = require('express'),
  3. app = express(),
  4. server = require('http').createServer(app),
  5. io = require('socket.io').listen(server);
  6.  
  7. var kinect = new Kinect2();
  8. // 打开kinect
  9. if(kinect.open()) {
  10. // 监听8000端口
  11. server.listen(8000);
  12. // 指定请求指向根目录
  13. app.get('/', function(req, res) {
  14. res.sendFile(__dirname + '/public/index.html');
  15. });
  16. // 将骨骼数据发送给浏览器端
  17. kinect.on('bodyFrame', function(bodyFrame){
  18. io.sockets.emit('bodyFrame', bodyFrame);
  19. });
  20. // 开始读取骨骼数据
  21. kinect.openBodyReader();
  22. }

  

2、浏览器端
浏览器端获取骨骼数据,并用canvas描绘出来,关键代码如下:

  1. var socket = io.connect('/');
  2. var ctx = canvas.getContext('2d');
  3. socket.on('bodyFrame', function(bodyFrame){
  4. ctx.clearRect(0, 0, canvas.width, canvas.height);
  5. var index = 0;
  6. // 遍历所有骨骼数据
  7. bodyFrame.bodies.forEach(function(body){
  8. if(body.tracked) {
  9. for(var jointType in body.joints) {
  10. var joint = body.joints[jointType];
  11. ctx.fillStyle = colors[index];
  12. // 如果骨骼节点为脊椎中点
  13. if(jointType == 1) {
  14. ctx.fillStyle = colors[2];
  15. }
  16. ctx.fillRect(joint.depthX * 512, joint.depthY * 424, 10, 10);
  17. }
  18. // 识别左右手手势
  19. updateHandState(body.leftHandState, body.joints[7]);
  20. updateHandState(body.rightHandState, body.joints[11]);
  21. index++;
  22. }
  23. });
  24. });

  

很简单的几行代码,我们便完成了玩家骨骼捕获,有一定 javascript基础的同学应该很容易能看明白,但不明白的是我们能获取哪些数据?如何获取?骨骼节点名称分别是什么?而node-kienct2并没有文档告诉我们这些。

五、开发文档
 
Node-Kinect2并没有提供文档,我将我测试总结的文档整理如下:
1、服务器端能提供的数据类型;
  1. kinect.on('bodyFrame', function(bodyFrame){}); //还有哪些数据类型呢?

  

bodyFrame 骨骼数据
infraredFrame 红外数据
longExposureInfraredFrame 类似infraredFrame,貌似精度更高,优化后的数据
rawDepthFrame 未经处理的景深数据
depthFrame 景深数据
colorFrame 彩色图像
multiSourceFrame 所有数据
audio 音频数据,未测试
2、骨骼节点类型
  1. 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、讲解之前,我们首先需要了解下游戏流程。

1.1、通过手势触发开始游戏

1.2、玩家化身四代,左右跑动躲避九尾攻击

1.3、摆出手势“奥义”,触发四代大招

1.4、用户扫描二维码获取自己现场照片

 
2、服务器端
游戏需要玩家骨骼数据(移动、手势),彩色图像数据(某一手势下触发拍照),所以我们需要向客户端发送这两部分数据。值得注意的是,彩色图像数据体积过大,需要进行压缩。
  1. var emitColorFrame = false;
  2. io.sockets.on('connection', function (socket){
  3. socket.on('startColorFrame', function(data){
  4. emitColorFrame = true;
  5. });
  6. });
  7. kinect.on('multiSourceFrame', function(frame){
  8.  
  9. // 发送玩家骨骼数据
  10. io.sockets.emit('bodyFrame', frame.body);
  11.  
  12. // 玩家拍照
  13. if(emitColorFrame) {
  14. var compression = 1;
  15. var origWidth = 1920;
  16. var origHeight = 1080;
  17. var origLength = 4 * origWidth * origHeight;
  18. var compressedWidth = origWidth / compression;
  19. var compressedHeight = origHeight / compression;
  20. var resizedLength = 4 * compressedWidth * compressedHeight;
  21. var resizedBuffer = new Buffer(resizedLength);
  22. // ...
  23. // 照片数据过大,需要压缩提高传输性能
  24. zlib.deflate(resizedBuffer, function(err, result){
  25. if(!err) {
  26. var buffer = result.toString('base64');
  27. io.sockets.emit('colorFrame', buffer);
  28. }
  29. });
  30. emitColorFrame = false;
  31. }
  32. });
  33. kinect.openMultiSourceReader({
  34. frameTypes: Kinect2.FrameType.body | Kinect2.FrameType.color
  35. });

  

3、客户端
客户端业务逻辑较复杂,我们提取关键步骤进行讲解。
3.1、用户拍照时,由于处理的数据比较大,为防止页面出现卡顿,我们需要使用web worker

  1. (function(){
  2. importScripts('pako.inflate.min.js');
  3.  
  4. var imageData;
  5. function init() {
  6. addEventListener('message', function (event) {
  7. switch (event.data.message) {
  8. case "setImageData":
  9. imageData = event.data.imageData;
  10. break;
  11. case "processImageData":
  12. processImageData(event.data.imageBuffer);
  13. break;
  14. }
  15. });
  16. }
  17. function processImageData(compressedData) {
  18. var imageBuffer = pako.inflate(atob(compressedData));
  19. var pixelArray = imageData.data;
  20. var newPixelData = new Uint8Array(imageBuffer);
  21. var imageDataSize = imageData.data.length;
  22. for (var i = 0; i < imageDataSize; i++) {
  23. imageData.data[i] = newPixelData[i];
  24. }
  25. for(var x = 0; x < 1920; x++) {
  26. for(var y = 0; y < 1080; y++) {
  27. var idx = (x + y * 1920) * 4;
  28. var r = imageData.data[idx + 0];
  29. var g = imageData.data[idx + 1];
  30. var b = imageData.data[idx + 2];
  31. }
  32. }
  33. self.postMessage({ "message": "imageReady", "imageData": imageData });
  34. }
  35. init();
  36. })();

  

3.2、接投影仪后,如果渲染面积比较大,会出现白屏,需要关闭浏览器硬件加速。

3.3、现场光线较暗,其它玩家干扰,在追踪玩家运动轨迹的过程中,可能会出现抖动的情况,我们需要去除干扰数据。(当突然出现很大位移时,需要将数据移除)

  1. var tracks = this.tracks;
  2. var len = tracks.length;
  3.  
  4. // 数据过滤
  5. if(tracks[len-1] !== window.undefined) {
  6. if(Math.abs(n - tracks[len-1]) > 0.2) {
  7. return;
  8. }
  9. }
  10. this.tracks.push(n);

  

3.4、当玩家站立,只是左右少量晃动时,我们认为玩家是站立状态。

  1. // 保留5个数据
  2. if(this.tracks.length > 5) {
  3. this.tracks.shift();
  4. } else {
  5. return;
  6. }
  7.  
  8. // 位移总量
  9. var dis = 0;
  10. for(var i = 1; i < this.tracks.length; i++) {
  11. dis += this.tracks[i] - this.tracks[i-1];
  12. }
  13. if(Math.abs(dis) < 0.01) {
  14. this.stand();
  15. } else {
  16. if(this.tracks[4] > this.tracks[3]) {
  17. this.turnRight();
  18. } else {
  19. this.turnLeft();
  20. }
  21. this.run();
  22. }

  

七、展望
 
1、使用HTML5开发Kinect体感游戏,降低了技术门槛,前端工程师可以轻松的开发体感游戏;
2、大量的框架可以应用,比如用JQuery、CreateJS、Three.js(三种不同渲染方式);
3、无限想象空间,试想下体感游戏结合webAR,结合webAudio、结合移动设备,太可以挖掘的东西了……想想都激动不是么!

使用HTML5开发Kinect体感游戏的更多相关文章

  1. OpenNI结合Unity3D Kinect进行体感游戏开发(转)

    OpenNI结合Unity3D Kinect进行体感游戏开发(转) 楼主# 更多 发布于:2012-07-17 16:42     1. 下载安装Unity3D(目前版本为3.4)2. 下载OpenN ...

  2. 【CityHunter】基于LBS的AR体感游戏设计理念

    本人目前还不是游戏行业的圈内人士,并不懂得,游戏行业的生态圈,也不懂得,所谓的什么“中国市场环境”.所以不敢发表关于这方面的见解,不过我在这里想要插一句话,就是我认为啊,行业内,人与人之间还是有分层次 ...

  3. Kinect外包团队(长年承接微软Kinect体感项目外包,有大型Kinect案例)

    承接Kinect体感企业项目.游戏项目外包 北京公司.专业团队,成员为专业WPF产品公司一线开发人员,有大型产品开发经验: 提供优质的售后服务,保证产品质量,轻量级产品可以提供规范清晰的源代码,有业务 ...

  4. Kinect外包-就找北京动点飞扬软件(长年承接微软Kinect体感项目外包,有大型Kinect案例)

    承接Kinect体感企业项目.游戏项目外包 有丰富案例提供演示,可公对公签正规合同,开发票. 我们是北京的公司.专业团队,成员为专业WPF产品公司一线开发人员,有大型产品开发经验: 提供优质的售后服务 ...

  5. [体感游戏] 1、MPU6050数据采集传输与可视化

    最近在研究体感游戏,到目前为止实现了基于51单片机的MPU6050数据采集.利用蓝牙模块将数据传输到上位机,并利用C#自制串口数据高速采集软件,并且将数据通过自制的折线图绘制模块可视化地展示出来等功能 ...

  6. 使用unity3d和tensorflow实现基于姿态估计的体感游戏

    使用unity3d和tensorflow实现基于姿态估计的体感游戏 前言 之前做姿态识别,梦想着以后可以自己做出一款体感游戏,然而后来才发现too young.但是梦想还是要有的,万一实现了呢.趁着p ...

  7. 制作Kinect体感控制小车教程 &lt;一&gt;

    转载请注明出处:http://blog.csdn.net/lxk7280                                        Kinect体感控制小车        Kine ...

  8. scratch编程体感游戏

    体感游戏有很多种,最常见的就是摄像头和声控了,今天我们要用scratch编写一系列的体感游戏!!!是不是很激动呢? 首先我们来编摄像头类的: No.1拳头打幽灵 挥动头就能打到幽灵了哟! 具体程序如下 ...

  9. C#开发体感游戏 Kinect应用知识

    Kinect首先是一个XBox 360外接体感设备,通过无线方式捕捉动作感知.由PrimeSense提供Range Camera技术,同类产品如任天堂Wii.Play Station Move,必须让 ...

随机推荐

  1. Python的单元测试(二)

    title: Python的单元测试(二) date: 2015-03-04 19:08:20 categories: Python tags: [Python,单元测试] --- 在Python的单 ...

  2. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

  3. .NET平台开源项目速览(13)机器学习组件Accord.NET框架功能介绍

    Accord.NET Framework是在AForge.NET项目的基础上封装和进一步开发而来.因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注重与机器 ...

  4. 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的?

    在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.总的来说,管道由一个服务器和一个HttpApplication构成 ...

  5. PHP之用户验证和标签推荐的简单使用

    本篇主要是讲解一些最简单的验证知识 效果图 bookmark_fns.php <?php require_once('output_fns.php'); require_once('db_fns ...

  6. ntp

    一: 在一台可以连接外网的服务器A上配置ntp: 配置  /etc/ntp.conf  文件: server 202.120.2.101            # local clock (LCL) ...

  7. BPM与 SAP & Oracle EBS集成解决方案分享

    一.需求分析 SAP和Oracle EBS都是作为全球顶级的的ERP产 品,得到了众多客户的青睐.然而由于系统庞大.价格昂贵以及定位不同,客户在实施过程中经常会面临以下困惑: 1.SAP如何实现&qu ...

  8. https 安全验证问题

    最近为了满足苹果的 https 要求, 经过努力终于写出了方法 验证 SSL 证书是否满足 ATS 要求 nscurl --ats-diagnostics --verbose https://你的域名 ...

  9. Mysql 忘记root密码处理办法

    一.更改my.cnf配置文件 1.用命令编辑/etc/my.cnf配置文件,即:vim /etc/my.cnf 或者 vi /etc/my.cnf 2.在[mysqld]下添加skip-grant-t ...

  10. Idea下用SBT搭建Spark Helloworld

    没用过IDEA工具,听说跟Eclipse差不多,sbt在Idea其实就等于maven在Eclipse.Spark运行在JVM中,所以要在Idea下运行spark,就先要安装JDK 1.8+ 然后加入S ...