2010-10-11 30 views
0

因此,我正在爲html5中的canvas元素編寫一個小型僞3D引擎。在下面的代碼中,我繪製了一系列具有不同位置和旋轉的方塊(圍繞z軸旋轉,因此不會變形)。命中測試僞3d空間

現在我想要知道用戶點擊哪個方塊。在對象數組中,項目由距離攝像機最遠的正方形開始的z位置支持(以便它們正確繪製)。所以給定一個相對於畫布角落左上角的3d點,我怎麼知道點擊了哪個方塊?

//Draw objects 
for (var i = 0; i < objects.length; i++) { 
    var object = objects[i]; 
    var cz = object.position.z - camera.position.z; 

    if (cz > 0) { 
     cz = 1/((cz - 1) * 0.75 + 1); 

     context.save(); 

     context.translate(halfWidth, halfHeight); //viewport transform 
     context.scale(1, -1); //invert y axis 
     context.scale(cz, cz); //perspective 
     context.translate(-camera.position.x, -camera.position.y); //camera transform 
     context.translate(object.position.x, object.position.y); //world transform 
     context.rotate(object.rotation); 

     context.fillStyle = object.color; 
     context.fillRect(-40, -40, 80, 80); 

     context.restore(); 
    } 
} 

P.S.如果我正在做任何奇怪或倒退,你知道一種改善的方式,我很樂意聽到建議

回答

0

我建議你用相同的轉換繪製對象到相同大小的隱藏畫布,但給每個正方形都有一個獨特的顏色(可能來自索引i)。

你會是這樣做的:

var col = index.toString(16);     // convert to hex 
while (col.length < 6) col = "0"+col;  // pad leading 0s 
ctx.fillStyle = "#"+col; 
ctx.fillRect(-40,-40,80,80); 

然後,當你拿到可見畫布上鼠標點擊事件,看看隱藏一個獲取所選對象的顏色(指數)在該位置:

var colData = ctx.getImageData(clickX, clickY, 1, 1).data; 
var index = (colData[2]<<16) | (colData[1]<<8) | colData[0]; 

這將適用於多達16M的對象,並且相當簡單。

+0

我希望能獲得更多基於數學的東西,但這是一個非常有創意的解決方案 – 2010-10-12 14:07:42

+0

這是一種對複雜場景進行點擊測試的常用方法。 – andrewmu 2010-10-12 14:41:29

+0

另一種方法是用編程方式生成畫布在形狀上進行的轉換,在生成點上執行該轉換以在場景中創建光線,然後計算出任何形狀是否與光線相交(以及如果有最近)。 – andrewmu 2010-10-12 14:50:15