如何利用Leap Motion創(chuàng)建支持手勢(shì)操控的Web游戲
譯文有了Leap Motion,大家可以跟游戲手柄說(shuō)拜拜了。
現(xiàn)代智能手機(jī)憑借著以手勢(shì)與觸控為核心的新型用戶界面為我們帶來(lái)前所未有的使用體驗(yàn)。隨著時(shí)間的不斷推移,我們幾乎可以肯定地認(rèn)為,在計(jì)算的未來(lái)中觸控技術(shù)將扮演愈發(fā)重要的關(guān)鍵性角色。不過(guò)話雖如此,一系列艱難挑戰(zhàn)仍然橫亙?cè)陂_(kāi)發(fā)者面前、使他們很難在臺(tái)式設(shè)備上充分發(fā)揮觸控機(jī)制的巨大優(yōu)勢(shì)。
深度相機(jī)與3D位置追蹤器的出現(xiàn)隱隱給觸控式互動(dòng)操作的迅速普及指出了一條光明的發(fā)展道路。雖然目前的最新一代技術(shù)仍然遠(yuǎn)遠(yuǎn)無(wú)法與《少數(shù)派報(bào)告》中的展示效果相提并論,但其中蘊(yùn)含的可觀潛力卻絕對(duì)不容置疑。
就在去年,我們?cè)?jīng)對(duì)Leap Motion控制器進(jìn)行過(guò)一番評(píng)測(cè)——這款設(shè)備利用高精度動(dòng)作捕捉與手指追蹤技術(shù)成功在任何標(biāo)準(zhǔn)化臺(tái)式機(jī)上實(shí)現(xiàn)了手勢(shì)輸入機(jī)制。作為一套經(jīng)由標(biāo)準(zhǔn)USB端口連接的設(shè)備,Leap Motion控制器通過(guò)其內(nèi)置攝像頭與紅外LED來(lái)捕捉用戶手指與手部的細(xì)微活動(dòng)。Leap Motion軟件會(huì)對(duì)圖像數(shù)據(jù)加以處理,并將這些信息翻譯成手勢(shì)以及觸控事件。
Leap Motion提供一套指向性極廣的SDK,旨在幫助開(kāi)發(fā)人員更輕松地在自己的應(yīng)用程序當(dāng)中實(shí)現(xiàn)對(duì)該設(shè)備的支持。它支持跨越多種平臺(tái)的一系列不同編程語(yǔ)言——除了原生桌面軟件之外,Leap Motion還提供一套JavaScript庫(kù),從而通過(guò)構(gòu)建Leap兼容性網(wǎng)站的方式將開(kāi)發(fā)成果在Web瀏覽器上加以呈現(xiàn)。
Leap Motion SDK非常容易上手,掌握之后能為我們帶來(lái)極為豐厚的回報(bào)。它以抽象化方式消除了控制器所固有的大部分復(fù)雜因素,通過(guò)高級(jí)別API實(shí)現(xiàn)了對(duì)手部及手指追蹤數(shù)據(jù)的捕捉。在今天的文章中,我們將共同探討如何構(gòu)建起一款能夠充分發(fā)揮Leap Motion追蹤功能優(yōu)勢(shì)的前端Web應(yīng)用程序。作為初始內(nèi)容,我們先來(lái)說(shuō)明如何在HTML Canvas元素上渲染手指定位點(diǎn),而后再一步步討論怎樣利用Pixi.js圖形庫(kù)來(lái)配合Leap Motion控制機(jī)制開(kāi)發(fā)出簡(jiǎn)單的2D游戲。
正式開(kāi)始
Leap Motion JavaScript庫(kù)依賴于WebSockets將來(lái)自控制器的數(shù)據(jù)提交并顯示在用戶的Web瀏覽器之上。WebSockets標(biāo)準(zhǔn)的設(shè)計(jì)目標(biāo)在于允許JavaScript代碼運(yùn)行在網(wǎng)頁(yè)當(dāng)中,從而確保網(wǎng)頁(yè)與遠(yuǎn)程服務(wù)器之間始終保持有長(zhǎng)效連接——這一特性通常被用于創(chuàng)建基于瀏覽器的聊天客戶端以及其它一些實(shí)時(shí)類Web應(yīng)用程序。
當(dāng)用戶部署好了自己的Leap Motion設(shè)備、并為其安裝了附帶的軟件及驅(qū)動(dòng)程序之后,其中作為內(nèi)置軟件組件之一的輕量級(jí)WebSocket服務(wù)器就會(huì)運(yùn)行在用戶計(jì)算機(jī)的后臺(tái)進(jìn)程當(dāng)中。由Leap Motion控制器捕捉到的數(shù)據(jù)會(huì)被發(fā)往WebSocket服務(wù)器,這是為了能夠讓相關(guān)數(shù)據(jù)直接交由Web瀏覽器使用、而無(wú)需另行安裝額外的瀏覽器插件。Leap Motion JavaScript庫(kù)與本地WebSocket服務(wù)器相連,負(fù)責(zé)捕捉數(shù)據(jù)并利用部分簡(jiǎn)單API進(jìn)行打包以保證其易于使用。
作為開(kāi)發(fā)工作的第一步,讓我們首先創(chuàng)建一個(gè)網(wǎng)頁(yè),并在其中載入Leap Motion JavaScript庫(kù)、獲取來(lái)自設(shè)備的數(shù)據(jù)并記錄下瀏覽器調(diào)試控制臺(tái)中的部分?jǐn)?shù)據(jù):
- <html>
- <head>
- <script src="http://js.leapmotion.com/leap-0.4.2.js"></script>
- </head>
- <body>
- </body>
- <script type="text/javascript">
- Leap.loop(function(frame) {
- if (frame.pointables.length > 0)
- console.log(frame.pointables);
- });
- </script> </html>
上述代碼的head元素中包含一個(gè)script標(biāo)簽,它的作用是從公司的CDN處下載Leap Motion JavaScript庫(kù)。Leap Motion針對(duì)生產(chǎn)使用環(huán)境推出一套精簡(jiǎn)版本,此外還針對(duì)開(kāi)發(fā)用途提供非精簡(jiǎn)版本。在這里我們使用的是非精簡(jiǎn)版本,這是為了能夠在需要使用瀏覽器的JavaScript調(diào)試器時(shí)能夠更輕松地對(duì)代碼進(jìn)行單步調(diào)試。大家可以點(diǎn)擊此處訪問(wèn)Leap Motion官方網(wǎng)站,并在這里下載到前面提到的這兩種版本。
在第二個(gè)script標(biāo)簽中,也就是頁(yè)面body之下,我們利用Leap.loop方法對(duì)來(lái)自設(shè)備的數(shù)據(jù)進(jìn)行捕捉。Leap Motion驅(qū)動(dòng)程序會(huì)發(fā)出數(shù)據(jù)“幀(frame)”,這些幀也就是經(jīng)過(guò)處理的控制器視頻流快照。該軟件每秒大約會(huì)產(chǎn)生30幀數(shù)據(jù),從而持續(xù)不斷地為應(yīng)用程序的運(yùn)行提供必要信息。被傳遞至該loop中的匿名函數(shù)在每次接收到新幀時(shí)都會(huì)執(zhí)行一次。
Leap Motion API大大簡(jiǎn)化了對(duì)手部、手指以及工具位置的檢測(cè)流程。這里的“工具”被認(rèn)定為一種延長(zhǎng)狀物體,例如鉛筆,其中一端由用戶把持在手中。在Leap Motion的表述體系當(dāng)中,通用術(shù)語(yǔ)“指向物(pointable)”被用于描述作為工具或者手指存在的對(duì)象。幀對(duì)象當(dāng)中包含一項(xiàng)名為pointables的屬性,用于顯示一系列顯示在幀內(nèi)的指向物對(duì)象。
在前面的示例中,每一幀內(nèi)所包含的一系列pointables都被輸出至控制臺(tái)當(dāng)中。如果大家檢查這些被推送至控制臺(tái)的指向物對(duì)象,就會(huì)發(fā)現(xiàn)其中有多項(xiàng)屬性被用于描述顯示信息——例如指向物的長(zhǎng)度與寬度、指向物末端的空間坐標(biāo)以及該指向物末端的移動(dòng)速度等。
在火狐開(kāi)發(fā)者控制臺(tái)中查看指向物對(duì)象。
計(jì)算標(biāo)準(zhǔn)化手指位置
利用指向物數(shù)據(jù),我們將建立一套簡(jiǎn)單的演示范例,用戶可以利用它通過(guò)移動(dòng)手指控制屏幕上某個(gè)元素的位置。第一步,我們需要獲取指尖的具體位置。下面的示例代碼為如何獲取單個(gè)指向物的原始坐標(biāo):
- Leap.loop(function(frame)
- { if (frame.pointables.length > 0)
- { var position = frame.pointables[0].tipPosition;
- console.log("X: " + position[0] + " Y: " + position[1]);
- }
- });
在多數(shù)情況下,大家都會(huì)優(yōu)先使用Leap Motion軟件所提供的自動(dòng)穩(wěn)定功能,而不太可能直接使用原始tipPosition數(shù)據(jù)。Leap Motion控制器會(huì)以極高的精度對(duì)圖像中的活動(dòng)對(duì)象加以檢測(cè),并從中甄別出使用者手部幾乎難以察覺(jué)的細(xì)微搖晃及活動(dòng)。另一項(xiàng)名為stabilizedTipPosition的備選屬性則允許我們收集同樣的數(shù)據(jù),但在結(jié)果中過(guò)濾掉上述細(xì)微活動(dòng)?,F(xiàn)在我們已經(jīng)獲得了用戶手指的物理坐標(biāo),接下來(lái)要做的就是將其與瀏覽器窗口內(nèi)的位置進(jìn)行關(guān)聯(lián)。
在Leap Motion的術(shù)語(yǔ)體系中,由控制器加以追蹤的大型虛擬空間被稱為互動(dòng)框(interaction box)。幀對(duì)象的interactionBox屬性當(dāng)中包含多種方法與屬性,它們負(fù)責(zé)提供與互動(dòng)框及其維度相關(guān)的具體信息。它采用一種便捷的標(biāo)準(zhǔn)化方法,即將某個(gè)物理點(diǎn)的原始坐標(biāo)換算成能夠代表該點(diǎn)在互動(dòng)框中相對(duì)位置的等效數(shù)值。
標(biāo)準(zhǔn)化定位機(jī)制非常實(shí)用,因?yàn)樗軒椭覀儷@取手指的原始位置、并將其與應(yīng)用程序窗口中的對(duì)應(yīng)點(diǎn)加以映射。標(biāo)準(zhǔn)化坐標(biāo)使用浮點(diǎn)數(shù)值格式,具體數(shù)值在0到1之間浮動(dòng)。要想獲取瀏覽器窗口中對(duì)應(yīng)點(diǎn)的相對(duì)數(shù)值,大家只需將X與Y值同目標(biāo)區(qū)域的高度與寬度相乘即可:
- Leap.loop(function(frame) {
- if (frame.pointables.length > 0) {
- var position = frame.pointables[0].stabilizedTipPosition;
- var normalized = frame.interactionBox.normalizePoint(position);
- var x = window.innerWidth * normalized[0];
- var y = window.innerHeight * (1 - normalized[1]);
- console.log("X: " + x + " Y: " + y);
- }
- });
在屏幕上繪制手指位置
利用標(biāo)準(zhǔn)化定位機(jī)制,現(xiàn)在我們已經(jīng)可以在網(wǎng)頁(yè)上繪制手指的具體位置。為了簡(jiǎn)單起見(jiàn),這篇文章將只向大家展示如何利用DOM元素實(shí)現(xiàn)這一目標(biāo)。只需創(chuàng)建一個(gè)具備絕對(duì)位置的div,而后將其top與left屬性分別設(shè)置為對(duì)應(yīng)的X與Y坐標(biāo),我們就能將Leap Motion loop中的標(biāo)準(zhǔn)化函數(shù)用于定位:
- <html>
- <head>
- <script src="http://js.leapmotion.com/leap-0.4.2.js"></script>
- <style type="text/css">
- #position {
- width: 25px;
- height: 25px;
- position: absolute;
- background-color: blue;
- }
- </style>
- </head>
- <body>
- <div id="position"></div>
- </body>
- <script type="text/javascript">
- Leap.loop(function(frame) {
- if (frame.pointables.length > 0) {
- var position = frame.pointables[0].stabilizedTipPosition;
- var normalized = frame.interactionBox.normalizePoint(position);
- var element = document.getElementById("position");
- element.style.left = window.innerWidth * normalized[0];
- element.style.top = window.innerHeight * (1 - normalized[1]);
- }
- });
- </script>
- </html>
這樣一來(lái),當(dāng)用戶在Leap Motion控制器前方移動(dòng)自己的手指時(shí),屏幕上的div元素也將隨之發(fā)生位移。在目前為止的示例中,我們只涉及單一手指的處理,也就是使用pointables數(shù)組中的第一個(gè)元素。在接下來(lái)的示例中,我們將逐步探尋數(shù)組中第一個(gè)元素的作用、從而使每根手指都成為可操作對(duì)象。這一次,我們將在HTML 5 Canvas上描繪手指位置、而不再使用DOM元素:
- <html>
- <head>
- <script src="http://js.leapmotion.com/leap-0.4.2.js"></script>
- </head>
- <body>
- <canvas id="canvas" width="800" height="600"></canvas>
- </body>
- <script type="text/javascript">
- var canvas = document.getElementById("canvas");
- var ctx = canvas.getContext("2d");
- Leap.loop({frameEventName: "animationFrame"}, function(frame) {
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- frame.pointables.forEach(function(pointable) {
- var position = pointable.stabilizedTipPosition;
- var normalized = frame.interactionBox.normalizePoint(position);
- var x = ctx.canvas.width * normalized[0];
- var y = ctx.canvas.height * (1 - normalized[1]);
- ctx.beginPath();
- ctx.rect(x, y, 20, 20);
- ctx.fill();
- });
- });
- </script>
- </html>
在上面的示例中,我們利用forEach方法對(duì)pointable項(xiàng)目進(jìn)行了遍歷。它會(huì)對(duì)每一個(gè)標(biāo)準(zhǔn)化位置進(jìn)行識(shí)別,而后將其作為矩形繪制在屏幕當(dāng)中。此外,clearRect方法在處理每一幀圖像時(shí)都會(huì)被調(diào)用一次,旨在確保前一幀所繪制的矩形切實(shí)得到清除。
上述示例當(dāng)中還引入了另一項(xiàng)新功能,即frameEventName選項(xiàng)。在默認(rèn)狀態(tài)下,Leap.loop回調(diào)將被調(diào)用至每一個(gè)提取自Leap Motion控制器的幀數(shù)據(jù)。對(duì)frameEventName選項(xiàng)中的“animationFrame”值進(jìn)行設(shè)置會(huì)改變這一行為機(jī)制,從而令Leap.loop與瀏覽器的繪制周期保持一致。它會(huì)利用瀏覽器的requestAnimationFrame API,從而確保該回調(diào)只在瀏覽器準(zhǔn)備進(jìn)行繪制時(shí)被調(diào)用。
檢測(cè)手勢(shì)
除了手指位置,Leap Motion SDK還能夠識(shí)別出其它幾種手勢(shì)動(dòng)作,其中包括掃動(dòng)與點(diǎn)觸。Leap Motion幀對(duì)象當(dāng)中包含一個(gè)手勢(shì)屬性,能夠提取從幀數(shù)據(jù)中檢測(cè)出的一系列手勢(shì)信息。以下示例代碼顯示了如何對(duì)掃動(dòng)手勢(shì)進(jìn)行迭代、對(duì)其起始與結(jié)束位置進(jìn)行標(biāo)準(zhǔn)化處理并最終將結(jié)果繪制在Canvs當(dāng)中:
- var canvas = document.getElementById("canvas");
- var ctx = canvas.getContext("2d");
- var options = {
- enableGestures: true, frameEventName: "animationFrame" };
- Leap.loop(options, function(frame) {
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- frame.gestures.forEach(function(gesture) {
- if (gesture.type != "swipe") return;
- var start = frame.interactionBox.normalizePoint(gesture.startPosition);
- var end = frame.interactionBox.normalizePoint(gesture.position);
- var startX = ctx.canvas.width * start[0];
- var startY = ctx.canvas.width * (1 - start[1]);
- var endX = ctx.canvas.width * end[0];
- var endY = ctx.canvas.width * (1 - end[1]);
- ctx.beginPath();
- ctx.moveTo(startX, startY);
- ctx.lineTo(endX, endY);
- ctx.stroke();
- });
- });
Leap Motion SDK在默認(rèn)狀態(tài)下不會(huì)顯示手勢(shì)。為了獲取手勢(shì)數(shù)據(jù),我們必須將選項(xiàng)對(duì)象的enableGestures屬性設(shè)為true,而后再將其傳遞至Leap.loop方法當(dāng)中。如果該選項(xiàng)沒(méi)有經(jīng)過(guò)設(shè)置,那么frame.gestures數(shù)組將直接為空。
每一種手勢(shì)都具備一項(xiàng)type屬性,用于描述該手勢(shì)的相關(guān)性質(zhì)。在forEach loop當(dāng)中,首先利用條件表達(dá)式來(lái)忽略不屬于掃動(dòng)的手勢(shì)動(dòng)作。接下來(lái),利用interactionBox對(duì)手勢(shì)的起始與結(jié)束位置進(jìn)行標(biāo)準(zhǔn)化處理。最后,利用標(biāo)準(zhǔn)Canvas繪制API來(lái)描繪由起始位置到結(jié)束位置的線條。
在面對(duì)Leap Motion設(shè)備進(jìn)行手部掃動(dòng)操作時(shí),大家應(yīng)該能夠在Canvas上看到自己的動(dòng)作軌跡線條。手勢(shì)檢測(cè)在更為廣義的互動(dòng)操作之下起著非常關(guān)鍵的作用。舉例來(lái)說(shuō),大家可以通過(guò)向左或者向右的掃動(dòng)操作幫助用戶導(dǎo)航至相冊(cè)界面的上一個(gè)或者下一個(gè)顯示條目當(dāng)中。
為了找到更多明確的黑色方塊,大家往往盡快得焦頭爛額。
下頁(yè)精彩內(nèi)容繼續(xù)
#p#
利用Leap Motion與Pixi.js創(chuàng)建一款簡(jiǎn)單游戲
現(xiàn)在我們已經(jīng)介紹了關(guān)于Leap Motion開(kāi)發(fā)的基礎(chǔ)知識(shí),是時(shí)候嘗試建立一些更具現(xiàn)實(shí)意義的實(shí)驗(yàn)性成果了。在接下來(lái)的示例中,我們將一步步幫助大家構(gòu)建起一款能夠與Leap Motion控制器相對(duì)接的互動(dòng)游戲。在該游戲中,大家可以移動(dòng)自己的手指來(lái)控制屏幕上的宇宙飛船。玩家必須小心駕駛自己的飛船,從而避免與敵人的船只相撞。
我們利用Pixi.js——一套簡(jiǎn)單的2D圖形庫(kù)——進(jìn)行游戲創(chuàng)建,它能夠幫助大家輕松創(chuàng)建并操作HTML Canvas元素。底層Leap Motion控制方案則基于文章前面提到的單手指操作示例。在游戲中,經(jīng)過(guò)標(biāo)準(zhǔn)化X與Y坐標(biāo)處理的手指位置將被映射到畫面中的飛船之上,也就是玩家所需要操作的對(duì)象。
為了幫助大家更輕松地遵照示例進(jìn)行,我們?cè)诖a當(dāng)中穿插注釋來(lái)幫助各位讀者順利理解。下面來(lái)看游戲代碼:
- <html>
- <head>
- <script src="assets/pixi.dev.js" type="text/javascript">
- </script>
- <script src="http://js.leapmotion.com/leap-0.4.2.js">
- </script>
- <style type="text/css">
- #game {
- margin-left: auto;
- margin-right: auto;
- width: 800px;
- height: 600px;
- }
- </style>
- </head>
- <body>
- <div id="game"></div>
- </body>
- <script type="text/javascript">
- var stageWidth = 800;
- var stageHeight = 600;
- //創(chuàng)建關(guān)卡與渲染引擎
- var stage = new PIXI.Stage(0xFFFFFF);
- var render = new PIXI.autoDetectRenderer(stageWidth, stageHeight); document.getElementById("game").appendChild(render.view);
- // 創(chuàng)建動(dòng)態(tài)星空背景
- var spacebg = PIXI.Texture.fromImage("assets/spacebg.png");
- var space = new PIXI.TilingSprite(spacebg, stageWidth, stageHeight);
- stage.addChild(space);
- // 創(chuàng)建飛船對(duì)象
- var rocket = PIXI.Sprite.fromImage("assets/rocketship.png");
- stage.addChild(rocket);
- //這條變量用于控制游戲狀態(tài)。
- //當(dāng)飛船與短文碰撞時(shí),此變量將被設(shè)置為“true”,
- //這時(shí)draw loop中止并顯示“游戲結(jié)束”字樣
- var collided = false;
- //在計(jì)時(shí)器中設(shè)置初始值
- //更多關(guān)于時(shí)間與游戲速度的詳細(xì)信息
- var timer = window.performance.now();
- //設(shè)置Leap Motion控制器loop
- var options = {frameEventName: "animationFrame"};
- var controller = Leap.loop(options, function(frame) {
- //我希望游戲中的各個(gè)元素能夠始終以同樣的速度進(jìn)行移動(dòng)。
- //如果激活了draw loop,
- //游戲速度將根據(jù)幀速率進(jìn)行變化。
- //我利用渲染時(shí)間差來(lái)確定實(shí)際距離
- //場(chǎng)景中的每個(gè)元素都應(yīng)該以每一幀為單位進(jìn)行移動(dòng)。
- var now = window.performance.now();
- var delta = Math.min(now - timer, 100);
- timer = now;
- //讓星空背景保持移動(dòng)
- space.tilePosition.x -= 0.2 * delta;
- //檢查“游戲結(jié)束”是否處于活動(dòng)狀態(tài)
- if (collided) {
- //創(chuàng)建并顯示“游戲結(jié)束”標(biāo)題
- var caption = new PIXI.Text("Game Over", {
- font: "50px Helvetica", fill: "red"
- });
- caption.x = stageWidth / 2 - caption.width / 2;
- caption.y = stageHeight / 2;
- stage.addChild(caption);
- //渲染該幀并調(diào)用返回結(jié)果
- //場(chǎng)景中的各元素保持靜態(tài)
- return render.render(stage);
- }
- //遍歷關(guān)卡當(dāng)中的每一艘敵方船只
- space.children.forEach(function(child) {
- // 使敵方船只向前移動(dòng)
- child.x -= 0.2 * delta;
- //測(cè)宇宙飛船的中心點(diǎn)是否處于敵方船只的邊界當(dāng)中。
- //這是一種非常簡(jiǎn)單的處理方式。
- //大家也可以選擇采用更為智能的多碰撞檢測(cè)機(jī)制
- //即利用“hitArea”設(shè)置更為精確的碰撞邊界。
- //如果用戶與敵機(jī)接觸,則變更“collided”值以結(jié)束游戲
- if (child.getBounds().contains(rocket.x, rocket.y))
- collided = true;
- //移除移動(dòng)至屏幕邊緣以外的敵方船只
- if (child.x < -child.width)
- space.removeChild(child);
- });
- //找到剛剛被添加到關(guān)卡當(dāng)中的宇宙飛船
- var last = space.children[space.children.length - 1];
- //如果屏幕上不存在宇宙飛船,則加入一艘新的船只
- //如果剛剛添加的船只距離右側(cè)邊緣超過(guò)250px,則再增加一艘新的船只。
- //這就是我們?cè)谟螒蛑信汕矓撤酱坏姆绞?。在?shí)際游戲中,
- //大家可以進(jìn)一步調(diào)低250px這一空間設(shè)置以增加游戲難度
- if (space.children.length == 0 || last.x < (stageWidth - 250)) {
- var item = PIXI.Sprite.fromImage("assets/enemy.png");
- item.y = Math.floor((Math.random() * (stageHeight - 100)));
- item.x = stageWidth;
- space.addChild(item);
- }
- if (frame.pointables.length > 0) {
- //獲取標(biāo)準(zhǔn)化手指位置
- var pos = frame.pointables[0].stabilizedTipPosition;
- var normPos = frame.interactionBox.normalizePoint(pos, true);
- //將宇宙飛船移動(dòng)至標(biāo)準(zhǔn)化手指位置
- rocket.x = stageWidth * normPos[0];
- rocket.y = stageHeight * (1 - normPos[1]);
- }
- // 渲染場(chǎng)景
- render.render(stage);
- });
- </script>
- </html>
如大家所見(jiàn),Leap Motion SDK讓創(chuàng)建實(shí)時(shí)手勢(shì)交互游戲變得相對(duì)簡(jiǎn)單了一些。利用代碼示例中所涉及的開(kāi)發(fā)技術(shù),大家可以很輕松地創(chuàng)建出多種不同類型的游戲或者應(yīng)用程序。如果大家擁有自己的Leap Motion控制器,不妨嘗試?yán)醚豖軸進(jìn)行手指操控的方式開(kāi)發(fā)“打磚塊”或者“是男人就下一百層”之類的游戲。大家還可以通過(guò)多種方式對(duì)上述代碼進(jìn)行深入擴(kuò)展,從而添加更多更為豐富的功能。舉例來(lái)說(shuō),我們可以利用指向物的touchZone屬性讓宇宙飛船在識(shí)別到用戶的指向劃動(dòng)操作時(shí)發(fā)射激光武器。
“手指?在向前行進(jìn)時(shí),我們不需要手指。”
我們?cè)贕itHub資源庫(kù)中發(fā)布了本篇文章中所用到的全部代碼內(nèi)容,感興趣的朋友可以點(diǎn)擊此處進(jìn)行查看。除此之外,作為獎(jiǎng)勵(lì)內(nèi)容我們還利用Three.js制作了一份粗糙的WebGL示例,它能夠顯示出手指位置在三維空間中的追蹤軌跡——點(diǎn)擊此處查看。
游戲中所使用的圖像資源來(lái)自Daniel Cook發(fā)布的SpaceCute圖像合集,大家可以點(diǎn)擊此處進(jìn)行下載。如果各位希望使用其它用于游戲原型設(shè)計(jì)的免費(fèi)圖形資源,也不妨點(diǎn)擊此處看看Cook同志收集的其它好東西。背景圖像來(lái)自O(shè)penGameArt的宇宙飛行游戲入門素材,點(diǎn)擊此處查看。
總結(jié)
Leap Motion硬件也許僅僅算是邁向未來(lái)的第一步(但卻絕對(duì)堪稱是‘人類的一大步’),很明顯其實(shí)際表現(xiàn)與《少數(shù)派報(bào)告》等電影中展示的效果還存在著巨大的差距,不過(guò)它的出現(xiàn)已經(jīng)標(biāo)志著我們向手勢(shì)驅(qū)動(dòng)類計(jì)算系統(tǒng)吹響了進(jìn)軍的號(hào)角。由于引入了三維空間概念,這扇剛剛開(kāi)啟的大門完全有可能引領(lǐng)我們走入更為豐富也更為復(fù)雜的交互新時(shí)代——這要比我們習(xí)以為常的平面觸控機(jī)制更加激動(dòng)人心。
這份教程當(dāng)中涉及到了JavaScript使用場(chǎng)景,不過(guò)Leap Motion還提供面向更多其它不同編程環(huán)境的多種SDK。大家既可以輕松創(chuàng)建原生應(yīng)用,也可以根據(jù)實(shí)際需要使用腳本化語(yǔ)言。
另外值得一提的是,除了本篇教程中所提到的功能之外、Leap Motion還提供更多有待發(fā)掘的珍貴資源。要詳細(xì)了解Leap Motion SDK所支持的各項(xiàng)功能,我們強(qiáng)烈建議大家點(diǎn)擊此處查看官方發(fā)布的說(shuō)明文檔。
請(qǐng)大家繼續(xù)期待我們本系列專題中的下一篇文章,屆時(shí)我們將向大家展示如何利用Pixi.js創(chuàng)建一款更為完整的游戲成品。我們將向其中添加更多游戲性功能——包括更為深入的卷軸滾動(dòng)周期以及游戲循環(huán)機(jī)制。此外,我們還會(huì)探討如何利用新的HTML 5 Gamepad API讓玩家能夠通過(guò)傳統(tǒng)的游戲主機(jī)手柄進(jìn)行操作。
核子可樂(lè)譯,點(diǎn)擊查看原文。