html5体感游戏开发,使用HTML5开发Kinect体感游戏

npm install kinect2

四、实例演示

说什么都不如给我一个例子!

如下图所示,我们演示如何获取人体骨骼,并标识脊椎中段及手势:

9eb557170a9de76e5dd19b62cde954c4.png

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){}); //还有哪些数据类型呢?

1df3bda0d42776a195b0ab3038cf66b3.png

2、骨骼节点类型

body.joints[11] // joints包括哪些呢?

244414f27d90642e3dabdcf1f52ed335.png

c8f88362f70d0c503f2a4e94f1eda688.png

4、骨骼数据

body [object] {

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

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

leftHandState [number]:左手手势

rightHandState [number]:右手手势

tracked [boolean]:是否捕获到

trackingId

}

c16549fe665219824226434f7827ce7e.png

8822bd569e32282792c223b5c5249332.png

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、接投影仪后,如果渲染面积比较大,会出现白屏,需要关闭浏览器硬件加速。

8841103f296c296bc9748852a9042bd1.png

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、结合移动设备,太可以挖掘的东西了……想想都激动不是么!

评论

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值