首页 > 编程 > HTML > 正文

HTML5开发Kinect体感游戏实例详解

2020-03-24 15:58:26
字体:
来源:转载
供稿:网友
一、简介

我们要做的是怎样一款游戏

在前不久成都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();// 打开kinectif(kinect.open()) { // 监听8000端口 server.listen(8000); // 指定请求指向根目录 app.get( / , function(req, res) { res.sendFile(dirname + /html' target='_blank'>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节点名称0spineBase脊椎基部1spineMid脊椎中部2neck颈部3head头部4shoulderLeft左肩5elbowLeft左肘6wristLeft左腕7handLeft左手掌8shoulderRight右肩9elbowRight右肘10wristRight右腕11handRight右手掌12hipLeft左屁13kneeLeft左膝14ankleLeft左踝15footLeft左脚16hipRight右屁17kneeRight右膝18ankleRight右踝19footRight右脚20spineShoulder颈下脊椎21handTipLeft左手指(食中无小)22thumbLeft左拇指23handTipRight右手指24thumbRight右拇指

3、手势,据测识别并不是太准确,在精度要求不高的情况下使用

0unknown不能识别1notTracked未能检测到2open手掌3closed握拳4lasso剪刀手,并合并中食指

4、骨骼数据

body [object] {

bodyIndex [number]:索引,允许6人

joints [array]:骨骼节点,包含坐标信息,颜色信息

leftHandState [number]:左手手势

rightHandState [number]:右手手势

tracked [boolean]:是否捕获到

trackingId

}

5、kinect对象

on监听数据open打开Kinectclose关闭openBodyReader读取骨骼数据open**Reader类似如上方法,读取其它类型数据六、实战总结

火影体感游戏经验总结

接下来,我总结一下TGC2016《火影忍者手游》的体感游戏开发中碰到的一些问题。

1、讲解之前,我们首先需要了解下游戏流程。

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

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

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

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

2、服务器端

游戏需要玩家骨骼数据(移动、手势),彩色图像数据(某一手势下触发拍照),所以我们需要向客户端发送这两部分数据。值得注意的是,彩色图像数据体积过大,需要进行压缩。

var emitColorFrame = false;io.sockets.on( connection , function (socket){ socket.on( startColorFrame , function(data){ emitColorFrame = true; }); kinect.on( multiSourceFrame , function(frame){ // 发送玩家骨骼数据 io.sockets.emit( bodyFrame , frame.body); // 玩家拍照 if(emitColorFrame) { var compression = 1; var origWidth = 1920; var origHeight = 1080; var origLength = 4 * origWidth * origHeight; var compressedWidth = origWidth / compression; var compressedHeight = origHeight / compression; var resizedLength = 4 * compressedWidth * compressedHeight; var resizedBuffer = new Buffer(resizedLength); // ... // 照片数据过大,需要压缩提高传输性能 zlib.deflate(resizedBuffer, function(err, result){ if(!err) { var buffer = result.toString( base64  io.sockets.emit( colorFrame , buffer); });  emitColorFrame = false;kinect.openMultiSourceReader({ frameTypes: Kinect2.FrameType.body | Kinect2.FrameType.color});

3、客户端

客户端业务逻辑较复杂,我们提取关键步骤进行讲解。

3.1、用户拍照时,由于处理的数据比较大,为防止页面出现卡顿,我们需要使用web worker

(function(){ importScripts( pako.inflate.min.js  var imageData; function init() { addEventListener( message , function (event) { switch (event.data.message) { case setImageData : imageData = event.data.imageData; break; case processImageData : processImageData(event.data.imageBuffer); break; function processImageData(compressedData) { var imageBuffer = pako.inflate(atob(compressedData)); var pixelArray = imageData.data; var newPixelData = new Uint8Array(imageBuffer); var imageDataSize = imageData.data.length; for (var i = 0; i imageDataSize; i++) { imageData.data[i] = newPixelData[i]; for(var x = 0; x 1920; x++) { for(var y = 0; y 1080; y++) { var idx = (x + y * 1920) * 4; var r = imageData.data[idx + 0];  var g = imageData.data[idx + 1];  var b = imageData.data[idx + 2];  self.postMessage({ message : imageReady , imageData : imageData }); init();})();

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

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

var tracks = this.tracks;var len = tracks.length;// 数据过滤if(tracks[len-1] !== window.undefined) { if(Math.abs(n - tracks[len-1]) 0.2) { return;this.tracks.push(n);

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

// 保留5个数据if(this.tracks.length 5) { this.tracks.shift();} else { return;// 位移总量var dis = 0;for(var i = 1; i this.tracks.length; i++) { dis += this.tracks[i] - this.tracks[i-1];if(Math.abs(dis) 0.01) { this.stand();} else { if(this.tracks[4] this.tracks[3]) { this.turnRight(); } else { this.turnLeft(); this.run();}

七、展望

1、使用HTML5开发Kinect体感游戏,降低了技术门槛,前端工程师可以轻松的开发体感游戏;

2、大量的框架可以应用,比如用JQuery、CreateJS、Three.js(三种不同渲染方式);

3、无限想象空间,试想下体感游戏结合webAR,结合webAudio、结合移动设备,太可以挖掘的东西了……想想都激动不是么!

以上就是HTML5开发Kinect体感游戏实例详解的详细内容,其它编程语言

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表