どんなゲームを作りますか?
少し前の成都TGC2016展示会で、私たちは主にモバイルゲームの章「九尾の攻撃」をシミュレートする「ナルトモバイルゲーム」の体性感覚ゲームを開発しました。ユーザーは四代目となり、九尾と競争します。 、多くのプレイヤーが参加し注目を集めました。 表面的には、このゲームは他の体性感覚体験と何ら変わりません。実際、ブラウザー Chrome で実行されています。言い換えれば、それに基づいた Web ベースの体性感覚ゲームを開発するために必要なのは、対応するフロントエンド技術だけです。キネクト。
実装のアイデアは何ですか?
H5 を使用して Kinect ベースの体性感覚ゲームを開発します。動作原理は実際には非常に単純です。Kinect は、人間の骨格などのプレイヤーおよび環境データを収集し、ブラウザーがこれらのデータにアクセスできるようにします。
1. データを収集する
Kinect には 3 つのレンズがあり、通常のカメラと同様にカラー画像を取得します。左右のレンズは赤外線により深度データを取得します。 Microsoft が提供する SDK を使用して、次の種類のデータを読み取ります。
カラー データ: カラー画像;
深度データ: カラー トライアル情報;
上記のデータに基づいて計算、人間の骨格データを取得しました。
2. ブラウザを Kinect データにアクセスできるようにする
私が試して理解したフレームワークは、基本的にソケットを使用して、ブラウザ プロセスがデータ送信のためにサーバーと通信できるようにします。
Kinect-HTML5 を使用して、サーバー、カラー データ、トライアル データ、スケルトン データがすべて提供されます。
ZigFu は H5、U3D、および Flash 開発をサポートしており、API は比較的完成されており、有料であるようです。ブラウザ プラグインの形式
Node-Kinect2 は Nodejs を使用してサーバー側を構築し、比較的完全なデータと多くの例を提供します。
最終的にはNode-Kinect2を選択しました。ドキュメントはありませんが、フロントエンドエンジニアには馴染みのあるNodejsを使用しています。また、著者のフィードバックは比較的速いです。
Kinect: 深度画像、カラー画像などのプレーヤーデータをキャプチャします。
インターフェース
を適用してプレイヤーデータを取得し、ゲーム開発を完了します。
インストール
KinectSDK-v2.0ジェスチャー
を示します:1. サーバー側
Webサーバーを作成して骨データを送信します。ブラウザへのコードは次のとおりです:npm install kinect2
2. ブラウザ側
ブラウザ側はボーンデータを取得し、canvas
を使用して描画します: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(); }
javascript
の基本を理解している学生なら簡単に理解できるはずですが、彼らが理解していないのは、どのようなデータを取得できるのかということです。入手方法は?ボーンノードの名前は何ですか?これについては、node-kienct2 に関するドキュメントはありません。 Node-Kinect2 はドキュメントを次のようにまとめました。1. サーバーが提供できるデータ型
;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、讲解之前,我们首先需要了解下游戏流程。
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体性感覚ゲームの開発事例を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。