使用HTML5开发Kinect体感游戏

news2024/11/16 11:50:10

一、简介

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

  在前不久成都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

 

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节点名称
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打开Kinect
close关闭
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、结合移动设备,太可以挖掘的东西了……想想都激动不是么!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Makerbase SimpleFOC ESP32 例程5 双电机闭环位置测试

Makerbase SimpleFOC ESP32 例程5 双电机闭环位置测试 第一部分 硬件介绍 1.1 硬件清单 序号品名数量1ESP32 FOC V1.0 主板12YT2804电机2312V电源适配器14USB 线156pin杜邦线2 注意&#xff1a;YT2804是改装的云台无刷电机,带有AS5600编码器&#xff0c;可实现360连续运转。…

香蕉派(Banana Pi) BPi-P2 Zero开源硬件物联网开发板评测

我们从制造商处收到的样品 BPi-P2 Zero 和 BPi-P2 Maker SBC 用于本次审查的体验非常好。这些都是基于多年H3/H2 SoC使用经验的高质量硬件实现。 优点 优良的价格和适用性稳定且经过验证的架构低散热供电电源WiFi / 蓝牙 kod 零模型完美平衡的 Maker 模型 Banana Pi BPi-P2 的…

设备树与pinctrl

设备树与pinctrl 原理&#xff1a;芯片内部有个内存控制器访问芯片的各个控制器单元&#xff08;如IIC、USB等&#xff09;&#xff0c; 阅读手册设置其相应功能即可。 设备树 是一种描述硬件的数据结构,由专门文件格式与语法结构。 pinctrl Pinctrl&#xff1a;Pin Contr…

vue-router(element侧导栏,子组件内容切换,不传参)使用的详细步骤

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

如何申请免费ChatGPT 2500刀初创金

近日OpenAI 推出了OpenAI for Startups项目&#xff0c;那么什么是Startups项目呢&#xff1a; 它是由全球知名的人工智能研究公司 OpenAI 推出的一个开放式的创业计划&#xff0c;旨在为初创公司提供一种新的激励机制和技术推广方式。 也就是说我们可以用自己账号申请&#x…

【软件工程题库】第四章 概要设计

&#x1f57a;作者&#xff1a; 迷茫的启明星 学习路线C语言从0到1C初阶数据结构从0到1 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

淬体归元,运营商资源域元数据管理

资源元数据是通信行业资源管理业务开展的基础性支撑要素&#xff0c;它定义了资源业务领域相关概念、关系和规则&#xff0c;即各种设施、缆线、设备、链路等网络资源的规格、属性、字典及相关存储模型等信息。高质量的元数据是提升业务效率、加强管理与分析能力的必要条件&…

多线程安全的案例展示与解决方案

一、概念 1. 什么是线程安全 当多个线程访问一个对象时&#xff0c;如果不用考虑这些线程在运行时环境下的调度和交替执行&#xff0c;也不需要进行额外的同步&#xff0c;或者在调用方进行任何其他的协调操作&#xff0c;调用这个对象的行为都可以获得正确的结果&#xff0c…

为什么HTTPS是安全的?

在谈论 HTTPS 协议之前&#xff0c;先来回顾一下 HTTP 协议的概念。 1. HTTP 协议 1.1 HTTP 协议介绍 HTTP 协议是一种基于文本的传输协议&#xff0c;它位于 OSI 网络模型中的应用层。 HTTP 协议是通过客户端和服务器的请求应答来进行通讯&#xff0c;目前协议由之前的 RFC…

Java程序设计入门教程--成员变量

成员的分类 实例成员 实例成员是属于对象的&#xff0c;即属于对象级别&#xff0c;包括实例成员属性&#xff08;也称为实例成员变量&#xff09;和实例成员方法&#xff0c;只有创建了对象之后才能访问实例成员属性和实例成员方法。 类成员 类成员属于类的&#xff0c;类成…

Stable Diffusion学习笔记

文章目录 参考资料△ 安装与环境配置○ 安装Python 人工智能真是厉害。。。 我也不能落后 虽然前面pytorch还没有学完&#xff0c;但是热点总是在变的嘛&#xff0c;现在大模型和生成式AI这么火&#xff0c;我也来蹭蹭热度。 就从学习怎么用AIGC工具生成 老婆 纸片人开始吧 …

app的动态导航栏及自定义图标的开发

效果展示 我的代码 <template><div class"nav-container"><!-- 动态底部导航栏 start--><div class"nav-content"><van-tabbar style"background-image: linear-gradient(135deg, #EE9AE5 10%, #5961F9 100%) !import…

防火墙之流量管理

防火墙流量管理 原理概述&#xff1a; 防火墙&#xff08;英语&#xff1a;Firewall&#xff09;技术是通过有机结合各类用于安全管理与筛选的软件和硬件设备&#xff0c;帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障&#xff0c;以保护用户资料与信息安全性的一…

【Python 文本分析】零基础也能轻松掌握的学习路线与参考资料

Python 常用的文本分析工具有很多&#xff0c;如 Natural Language Toolkit (NLTK)、TextBlob、spaCy、Jieba等。本文将分别介绍这些工具及其对应的学习路线、参考资料和优秀实践。 Natural Language Toolkit (NLTK) Natural Language Toolkit (NLTK) 是 Python 中文本分析研…

记一次Java生成SQL脚本文件换行格式为window/unix的笔记

今天在做一个SQL脚本文件生成需求&#xff0c;其中&#xff0c;需要设置&#xff1a; 文件编码为&#xff1a;UTF-8文件换行格式为&#xff1a;UNIX UTF-8这个好说&#xff0c;因为java代码可以指定文件编码&#xff0c;如&#xff1a; 但是Unix换行格式就很神奇了&#xff0…

职场恶霸00后,看完这篇你就知道了

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&#x…

032:Mapbox GL实现卷帘功能,可开启、关闭

第032个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中实现地图卷帘功能,这里可以设置开启、关闭卷帘。根据参数的不同,可以配置相关的功能,请参考底部的API信息。本示例比较重要的一点是要知道如何引用mapbox-gl-compare插件。 直接复制下面的 vue+mapbox源…

SpringData 进阶篇-上

SpringData 一&#xff1a;背景介绍二&#xff1a;XML配置 与JavaConfig配置2.1 XML配置2.1.1 配置文件2.1.2 具体使用 2.2 JavaConfig配置2.2.1 配置类2.2.2 具体使用&#xff1a; 三&#xff1a;SpringDataJpa的CRUD3.1 接口代码3.2 具体使用3.3 其它方法3.4 分页方法 四&am…

【数据集处理】中国地面气候资料日值数据集(V3.0)

1 数据集介绍-中国地面气候资料日值数据集(V3.0) 中国地面气候资料日值数据集(V3.0)包含以下气象数据资料(包括降水、气温、风速等)。 2 数据处理 以湿度数据(RHU) 处理为例,数据文件如下: 2.1 步骤1:从文件中提取数据 首先提取所有需要的有效信息,查看【数据表格…

sql_server数据库入门学习(二)

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集&#xff01; &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指…