2013-03-13 61 views
1

我試圖在我的畫布遊戲中實現像素完美碰撞檢測,但是我似乎無法從我的精靈中獲取像素信息。從畫布精靈獲取圖像像素數據

我需要精靈的每個像素的x和y值,並且從我讀過的內容中我使用getImageData()方法來做到這一點。

然而,這不起作用:

this.sprite = new Image(); 
this.sprite.src = 'img/player.png'; 
console.log(this.sprite.getImageData()); 

我是否可能使用了錯誤類型的精靈?因爲我在控制檯收到此錯誤:

Uncaught TypeError: Object # has no method 'getImageData'

+0

'getImageData()'是一種用於畫布的方法,而不是圖像。 「從我的精靈中獲取像素信息」是什麼意思? – romainberger 2013-03-13 20:03:25

+0

框檢測並不困難 - 基於像素形狀的檢測可能會非常耗費流程。 請參閱:http://stackoverflow.com/questions/8017541/javascript-canvas-collision-detection和:http://stackoverflow.com/questions/4871669/collision-detection-in-javascript-game – 2013-03-13 20:08:39

+0

啊,我認爲它可能是。我的意思是我想知道畫布上x和y座標的每個像素在我的精靈中。 @Diodeus,沒有你想象的那麼多。雖然它可以帶有很多對象,但我一次只能在畫布上放置幾個精靈。此外,由於精靈不是矩形,因此盒檢測對於此目的不夠好。 – 2013-03-13 20:11:05

回答

5

下面介紹如何使用精靈的像素數據通常做完美的像素命中測試

首先,畫你的精靈你看到畫布上。

enter image description here

的隱藏畫布創建精靈的紅蒙面副本。此副本與精靈的尺寸完全相同,但僅包含透明或紅色像素。

enter image description here

軌道可見精靈的邊界框。單擊邊界框時,計算與精靈邊界框(不涉及畫布)相關的鼠標單擊的X/Y。

然後,請參考紅色遮罩的sprite,看看該X/Y處的對應像素是紅色還是透明的。如果像素爲紅色,則您的像素完美匹配。如果像素是透明的,則沒有命中。

在此圖中,假設藍色點是X/Y點擊位置。由於紅色遮罩畫布中相應的X/Y像素爲「紅色」,因此這是一個HIT。

enter image description here

下面是代碼來創建一個紅掩蓋精靈。我沒有在這裏顯示命中測試的代碼,但是如果您嘗試並且無法編寫命中測試代碼,我也會花時間對代碼測試進行編碼。

重要提示:要使此代碼運行,您必須避免跨域安全限制。確保您的圖片源位於您的本地域,否則您將遇到跨域安全違規,並且屏蔽圖像將不會被繪製...因此,您無法爲您的精靈源執行此操作:http://otherDomain.com/picture.jpg

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 

<style> 
    body{ background-color: ivory; padding:10px; } 
    canvas{border:1px solid blue;} 
</style> 

<script> 
    $(function(){ 

     var c=document.getElementById("canvas"); 
     var ctx=c.getContext("2d"); 

     var img=new Image(); 
     img.onload=function(){ 
      ctx.drawImage(this,100,25); 

      // make a red-masked copy of just the sprite 
      // on a separate canvas 
      var canvasCopy=document.getElementById("canvasCopy"); 
      var ctxCopy=canvasCopy.getContext("2d"); 
      canvasCopy.width=this.width; 
      canvasCopy.height=this.height; 
      ctxCopy.drawImage(img,0,0); 

      // make a red-masked copy of the sprite on a separate canvas 
      var imgData=ctxCopy.getImageData(0,0,c.width,c.height); 
      for (var i=0;i<imgData.data.length;i+=4) 
      { 
       if(imgData.data[i+3]>0){ 
        imgData.data[i]=255; 
        imgData.data[i+1]=0; 
        imgData.data[i+2]=0; 
        imgData.data[i+3]=255; 
       } 
      } 
      ctxCopy.putImageData(imgData,0,0);   

     } 
     img.src = "houseIcon.png"; 

    }); // end $(function(){}); 
</script> 

</head> 

<body> 
    <p>Original sprite drawn on canvas at XY:100/25</p> 
    <canvas id="canvas" width="400" height="300"></canvas> 
    <p>Red-masked on canvas used for hit-testing</p> 
    <canvas id="canvasCopy" width="300" height="300"></canvas> 

</body> 
</html> 

要做到2個精靈之間的像素完美的碰撞測試中,你會:

創建兩個精靈#1和#精靈2紅蒙面畫布。

首先測試2個精靈的邊界框是否碰撞。如果邊界框沒有碰撞,那麼2個精靈不會相互碰撞,所以你可以在這裏停止命中測試。

如果2個精靈是可能使用邊界框測試進行碰撞,請爲碰撞測試創建第三個畫布。

您將使用畫布的合成方法通過在第三個畫布上繪製精靈#1和精靈#2來測試精靈#1和精靈#2之間的碰撞。使用合成,只有2個精靈的像素將被繪製在第三個畫布上。

以下是如何與「目標輸入」合成的工作原理:現有畫布內容保留在新形狀(sprite#2)和現有形狀(sprite#1)內容重疊的位置。其他一切都是透明的。

所以......

繪製精靈#在變換狀態下的進入第三畫布1 (轉換可能是移動,旋轉,縮放,傾斜 - 什麼!)。

將globalCompositeOperation設置爲destination-in。

context.globalCompositeOperation = 'destination-over'; 

繪製子畫面#2 在其轉化的狀態到第三畫布。

此拉伸之後,第三畫布包含只的子畫面#1和子畫面#2

測試在第三畫布非透明像素的每個像素的碰撞部。如果您發現任何不透明的像素,則2個精靈將進行COLLIDING。

根據您想要在碰撞時採取什麼動作,您可能只是在找到第一個碰撞像素時才紓困。

+0

哇。 [15個字符] – 11684 2013-04-07 12:57:04

+0

謝謝你的回答@markE。但是有一個問題,如果我們要使用'目標進入',爲什麼我們需要紅色掩蓋精靈?不重疊的像素不會被繪製,然後我們繼續搜索不透明的像素。 – Airwavezx 2017-09-14 21:21:53