自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何利用Leap Motion創(chuàng)建支持手勢(shì)操控的Web游戲

譯文
移動(dòng)開(kāi)發(fā)
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)人心。

有了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ù):

  1. <html> 
  2.    <head> 
  3.      <script src="http://js.leapmotion.com/leap-0.4.2.js"></script> 
  4.    </head> 
  5.    <body>    
  6. </body>    
  7. <script type="text/javascript"> 
  8.      Leap.loop(function(frame) { 
  9.        if (frame.pointables.length > 0) 
  10.           console.log(frame.pointables); 
  11.      }); 
  12.    </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):

  1. Leap.loop(function(frame)  
  2. {   if (frame.pointables.length > 0) 
  3.    {     var position = frame.pointables[0].tipPosition;
  4.      console.log("X: " + position[0] + " Y: " + position[1]); 
  5.    } 
  6.  }); 

在多數(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ū)域的高度與寬度相乘即可:

  1. Leap.loop(function(frame) { 
  2.    if (frame.pointables.length > 0) {  
  3.     var position = frame.pointables[0].stabilizedTipPosition;
  4.      var normalized = frame.interactionBox.normalizePoint(position);  
  5.          var x = window.innerWidth * normalized[0]; 
  6.      var y = window.innerHeight * (1 - normalized[1]);
  7.       console.log("X: " + x + " Y: " + y); 
  8.    } 
  9.  }); 

在屏幕上繪制手指位置

利用標(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ù)用于定位:

  1. <html> 
  2.    <head> 
  3.      <script src="http://js.leapmotion.com/leap-0.4.2.js"></script> 
  4.      <style type="text/css"> 
  5.        #position { 
  6.          width: 25px; 
  7.          height: 25px; 
  8.          position: absolute; 
  9.          background-color: blue; 
  10.        } 
  11.      </style> 
  12.    </head> 
  13.    <body> 
  14.      <div id="position"></div> 
  15.    </body> 
  16.    <script type="text/javascript"> 
  17.      Leap.loop(function(frame) { 
  18.          if (frame.pointables.length > 0) {  
  19.           var position = frame.pointables[0].stabilizedTipPosition; 
  20.            var normalized = frame.interactionBox.normalizePoint(position);  
  21.           var element = document.getElementById("position"); 
  22.             element.style.left = window.innerWidth * normalized[0];  
  23.           element.style.top = window.innerHeight * (1 - normalized[1]); 
  24.          } 
  25.      }); 
  26.    </script> 
  27.  </html> 

這樣一來(lái),當(dāng)用戶在Leap Motion控制器前方移動(dòng)自己的手指時(shí),屏幕上的div元素也將隨之發(fā)生位移。在目前為止的示例中,我們只涉及單一手指的處理,也就是使用pointables數(shù)組中的第一個(gè)元素。在接下來(lái)的示例中,我們將逐步探尋數(shù)組中第一個(gè)元素的作用、從而使每根手指都成為可操作對(duì)象。這一次,我們將在HTML 5 Canvas上描繪手指位置、而不再使用DOM元素:

  1. <html> 
  2.   <head> 
  3.     <script src="http://js.leapmotion.com/leap-0.4.2.js"></script>
  4.    </head>
  5.    <body>
  6.      <canvas id="canvas" width="800" height="600"></canvas>
  7.    </body>
  8.    <script type="text/javascript">
  9.      var canvas = document.getElementById("canvas");
  10.      var ctx = canvas.getContext("2d");
  11.           Leap.loop({frameEventName: "animationFrame"}, function(frame) {
  12.          ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  13.           frame.pointables.forEach(function(pointable) {
  14.            var position = pointable.stabilizedTipPosition;
  15.            var normalized = frame.interactionBox.normalizePoint(position);
  16.             var x = ctx.canvas.width * normalized[0];
  17.            var y = ctx.canvas.height * (1 - normalized[1]);
  18.             ctx.beginPath();
  19.            ctx.rect(x, y, 20, 20);
  20.            ctx.fill();
  21.          });
  22.      });
  23.    </script>
  24.  </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)中:

  1. var canvas = document.getElementById("canvas"); 
  2.  var ctx = canvas.getContext("2d"); 
  3.   var options = { 
  4.    enableGestures: true,   frameEventName: "animationFrame" }; 
  5.   Leap.loop(options, function(frame) { 
  6.    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
  7.     frame.gestures.forEach(function(gesture) { 
  8.      if (gesture.type != "swipe") return; 
  9.      var start = frame.interactionBox.normalizePoint(gesture.startPosition); 
  10.      var end = frame.interactionBox.normalizePoint(gesture.position); 
  11.       var startX = ctx.canvas.width * start[0]; 
  12.      var startY = ctx.canvas.width * (1 - start[1]); 
  13.       var endX = ctx.canvas.width * end[0]; 
  14.      var endY = ctx.canvas.width * (1 - end[1]); 
  15.       ctx.beginPath(); 
  16.      ctx.moveTo(startX, startY); 
  17.      ctx.lineTo(endX, endY); 
  18.      ctx.stroke(); 
  19.    }); 
  20.  }); 

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)看游戲代碼:

  1. <html> 
  2.    <head> 
  3.      <script src="assets/pixi.dev.js" type="text/javascript"> 
  4. </script> 
  5.      <script src="http://js.leapmotion.com/leap-0.4.2.js"> 
  6. </script> 
  7.       <style type="text/css"> 
  8.        #game { 
  9.          margin-left: auto; 
  10.          margin-right: auto; 
  11.           width: 800px; 
  12.          height: 600px; 
  13.        } 
  14.      </style> 
  15.     </head> 
  16.    <body> 
  17.      <div id="game"></div> 
  18.    </body> 
  19.     <script type="text/javascript"> 
  20.       var stageWidth = 800
  21.      var stageHeight = 600
  22.       //創(chuàng)建關(guān)卡與渲染引擎 
  23.      var stage = new PIXI.Stage(0xFFFFFF); 
  24.      var render = new PIXI.autoDetectRenderer(stageWidth, stageHeight);      document.getElementById("game").appendChild(render.view); 
  25.       // 創(chuàng)建動(dòng)態(tài)星空背景 
  26.      var spacebg = PIXI.Texture.fromImage("assets/spacebg.png"); 
  27.      var space = new PIXI.TilingSprite(spacebg, stageWidth, stageHeight); 
  28.      stage.addChild(space); 
  29.       // 創(chuàng)建飛船對(duì)象 
  30.      var rocket = PIXI.Sprite.fromImage("assets/rocketship.png"); 
  31.      stage.addChild(rocket); 
  32.       //這條變量用于控制游戲狀態(tài)。 
  33.      //當(dāng)飛船與短文碰撞時(shí),此變量將被設(shè)置為“true”, 
  34.      //這時(shí)draw loop中止并顯示“游戲結(jié)束”字樣 
  35.     var collided = false
  36.       //在計(jì)時(shí)器中設(shè)置初始值 
  37.      //更多關(guān)于時(shí)間與游戲速度的詳細(xì)信息 
  38.      var timer = window.performance.now(); 
  39.       //設(shè)置Leap Motion控制器loop 
  40.      var options = {frameEventName: "animationFrame"}; 
  41.      var controller = Leap.loop(options, function(frame) { 
  42.         //我希望游戲中的各個(gè)元素能夠始終以同樣的速度進(jìn)行移動(dòng)。 
  43.        //如果激活了draw loop, 
  44.        //游戲速度將根據(jù)幀速率進(jìn)行變化。 
  45.        //我利用渲染時(shí)間差來(lái)確定實(shí)際距離 
  46.       //場(chǎng)景中的每個(gè)元素都應(yīng)該以每一幀為單位進(jìn)行移動(dòng)。 
  47.        var now = window.performance.now(); 
  48.        var delta = Math.min(now - timer, 100); 
  49.        timer = now
  50.         //讓星空背景保持移動(dòng) 
  51.        space.tilePosition.x -0.2 * delta; 
  52.         //檢查“游戲結(jié)束”是否處于活動(dòng)狀態(tài) 
  53.        if (collided) { 
  54.          //創(chuàng)建并顯示“游戲結(jié)束”標(biāo)題 
  55.          var caption = new PIXI.Text("Game Over", { 
  56.            font: "50px Helvetica", fill: "red" 
  57.          }); 
  58.           caption.x = stageWidth / 2 - caption.width / 2; 
  59.          caption.y = stageHeight / 2; 
  60.           stage.addChild(caption); 
  61.           //渲染該幀并調(diào)用返回結(jié)果 
  62.          //場(chǎng)景中的各元素保持靜態(tài) 
  63.          return render.render(stage); 
  64.        } 
  65.         //遍歷關(guān)卡當(dāng)中的每一艘敵方船只 
  66.        space.children.forEach(function(child) { 
  67.          // 使敵方船只向前移動(dòng) 
  68.          child.x -0.2 * delta; 
  69.           //測(cè)宇宙飛船的中心點(diǎn)是否處于敵方船只的邊界當(dāng)中。 
  70.       //這是一種非常簡(jiǎn)單的處理方式。 
  71.          //大家也可以選擇采用更為智能的多碰撞檢測(cè)機(jī)制 
  72.          //即利用“hitArea”設(shè)置更為精確的碰撞邊界。 
  73.         //如果用戶與敵機(jī)接觸,則變更“collided”值以結(jié)束游戲 
  74.          if (child.getBounds().contains(rocket.x, rocket.y)) 
  75.            collided = true
  76.           //移除移動(dòng)至屏幕邊緣以外的敵方船只 
  77.          if (child.x < -child.width
  78.            space.removeChild(child); 
  79.        }); 
  80.         //找到剛剛被添加到關(guān)卡當(dāng)中的宇宙飛船 
  81.        var last = space.children[space.children.length - 1]; 
  82.         //如果屏幕上不存在宇宙飛船,則加入一艘新的船只 
  83.        //如果剛剛添加的船只距離右側(cè)邊緣超過(guò)250px,則再增加一艘新的船只。 
  84.        //這就是我們?cè)谟螒蛑信汕矓撤酱坏姆绞?。在?shí)際游戲中, 
  85.       //大家可以進(jìn)一步調(diào)低250px這一空間設(shè)置以增加游戲難度 
  86.        if (space.children.length == 0 || last.x < (stageWidth - 250)) {  
  87.         var item = PIXI.Sprite.fromImage("assets/enemy.png"); 
  88.          item.y = Math.floor((Math.random() * (stageHeight - 100))); 
  89.          item.x = stageWidth
  90.          space.addChild(item); 
  91.        } 
  92.         if (frame.pointables.length > 0) { 
  93.          //獲取標(biāo)準(zhǔn)化手指位置 
  94.          var pos = frame.pointables[0].stabilizedTipPosition; 
  95.          var normPos = frame.interactionBox.normalizePoint(pos, true); 
  96.           //將宇宙飛船移動(dòng)至標(biāo)準(zhǔn)化手指位置 
  97.          rocket.x = stageWidth * normPos[0]; 
  98.          rocket.y = stageHeight * (1 - normPos[1]); 
  99.        } 
  100.         // 渲染場(chǎng)景 
  101.        render.render(stage); 
  102.      }); 
  103.     </script> 
  104.  </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)擊查看原文。

責(zé)任編輯:閆佳明 來(lái)源: 51CTO譯文
相關(guān)推薦

2013-02-22 10:11:42

leap motion體感交互

2013-02-22 10:27:31

leap motion體感交互

2014-07-16 13:36:30

MotionLinux監(jiān)控

2013-07-15 10:14:29

leap motion體感交互

2013-02-28 15:38:19

Leap Motion應(yīng)用商店Airspace

2013-08-22 10:59:00

手勢(shì)操控iOS

2023-08-30 11:03:47

Java工具

2013-08-29 09:53:04

HTML5MongoDB位置感知

2014-10-13 13:44:00

AngularJS2048

2013-05-21 11:20:37

Android游戲開(kāi)發(fā)View手勢(shì)識(shí)別

2021-12-06 10:27:32

XWayland觸摸板手勢(shì)開(kāi)發(fā)

2022-06-02 15:42:05

Python機(jī)器學(xué)習(xí)

2013-08-13 11:25:56

屏幕尺寸Android應(yīng)用

2022-05-17 12:25:59

物聯(lián)網(wǎng)智能建筑樓宇自控

2013-09-10 17:13:57

移動(dòng)網(wǎng)站性能優(yōu)化移動(dòng)web

2022-05-06 10:11:21

開(kāi)源游戲桌游

2009-05-30 09:33:10

Palm PreWebOS移動(dòng)OS

2016-11-14 16:00:31

html5javascript

2010-03-30 10:44:05

Nginx啟動(dòng)

2023-06-08 09:34:12

Linux操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)