2011-11-05 18 views
6

私は、衝突検出が必要なキャンバスを使用してJavascriptでゲームを構築しています。この場合、プレーヤースプライトがボックスに当たった場合、プレーヤーはボックスを通過できません。Javascript canvas collision detection

私はblockListというグローバル配列を持ち、キャンバスに描画されるすべてのボックスを保持しています。それは次のようになります。

var blockList = [[50, 400, 100, 100]]; 

そして、彼らはこのようなキャンバスに描かれている:私も更新方法とdrawメソッドを持っている選手オブジェクトを、持っている

c.fillRect(blockList[0][0], blockList[0][1], blockList[0][2], blockList[0][3]); 

。 Updateは、キーボード入力などに基づいてプレーヤーの位置を設定し、メインのゲームループが描画を使用してプレーヤーをキャンバスに描画します。プレイヤーは次のように描かれている:

this.draw = function(timestamp) { 
     if(this.state == "idle") { 
      c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight); 
      if(timestamp - this.lastDraw > this.idleSprite.updateInterval) { 
       this.lastDraw = timestamp; 
       if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; } 
      } 
     } else if(this.state == "running") { 
      var height = 0; 
      if(this.facing == "left") { height = 37; } 
      c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, height, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight); 
      if(timestamp - this.lastDraw > this.runningSprite.updateInterval) { 
       this.lastDraw = timestamp; 
       if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; } 
      } 
     } 
    } 

さて、プレイヤーがplayer.xposplayer.yposplayer.widthplayer.heightである特定の性質を有します。ブロックには同じプロパティが存在します。だから、私は衝突の検出を促すために必要なこと全てを持っているので、それをどうやって行うのか分かりません。私は次のようなことをやろうとしました:

if(player.x > blockList[0][0] && player.y > blockList[0][1]) 

しかし、それは完璧か再生可能ではありません。

誰かが、2つのオブジェクトが衝突しているかどうかに基づいて、trueまたはfalseを返すことができる簡単なメソッドまたは関数を知っていますか?

答えて

8

Iは、2つの長方形の間の衝突検出のために、以下の関数を使用する:

rect_collision = function(x1, y1, size1, x2, y2, size2) { 
    var bottom1, bottom2, left1, left2, right1, right2, top1, top2; 
    left1 = x1 - size1; 
    right1 = x1 + size1; 
    top1 = y1 - size1; 
    bottom1 = y1 + size1; 
    left2 = x2 - size2; 
    right2 = x2 + size2; 
    top2 = y2 - size2; 
    bottom2 = y2 + size2; 
    return !(left1 > right2 || left2 > right1 || top1 > bottom2 || top2 > bottom1); 
}; 

これは、それぞれ辺の長さ2*size12*size2(x1, y1)(x2, y2)を中心とする2つの正方形は、重複しているか否かを判定する。 left1,right1などの定義を変更して、正方形ではなく一般的な四角形を扱い、異なるデータ形式を使用するのは簡単です。

すなわち、left1等最初の正方形、right1右側、左側がなおある、私の座標系において、y軸は(top1 < bottom1)反転されます。

2

2つの矩形が重なっているかどうかを知りたいだけですか?そのやっている何

// returns true if there is any overlap 
// params: x,y,w,h of two rectangles 
function intersects(x1, y1, w1, h1, x2, y2, w2, h2) { 
    w2 += x2; 
    w1 += x1; 
    if (x2 > w1 || x1 > w2) return false; 
    h2 += y2; 
    h1 += y1; 
    if (y2 > h1 || y1 > h2) return false; 
    return true; 
} 

:あなたのプログラムは、数字は常にあなたが簡単なバージョンを使用することができ、有限になることを確信できる場合

// returns true if there is any overlap 
// params: x,y,w,h of two rectangles 
function intersects(x1, y1, w1, h1, x2, y2, w2, h2) { 
    if (w2 !== Infinity && w1 !== Infinity) { 
    w2 += x2; 
    w1 += x1; 
    if (isNaN(w1) || isNaN(w2) || x2 > w1 || x1 > w2) return false; 
    } 
    if (y2 !== Infinity && h1 !== Infinity) { 
    h2 += y2; 
    h1 += y1; 
    if (isNaN(h1) || isNaN(y2) || y2 > h1 || y1 > h2) return false; 
    } 
    return true; 
} 

:ここ

はあなたのために防弾機能です2つの矩形の右辺と底辺がどこにあるのかを見つけると、2番目の矩形が最初のものの外側で開始するか、最初のものが2番目の矩形の外側で開始するかどうかがわかります。

いずれかの矩形が終了した後にいずれかの矩形が始まる場合、衝突はありません。さもなければ衝突がなければならない。

0

私の意見では、多くのパラメータを必要とする関数のファンではありません。ここで

は、私はそれを行うだろう方法は次のとおりです。

function collisionCheckRectRect(rectOne, rectTwo){ 

    var x1=rectOne.x, y1 = rectOne.y, height1 = rectOne.height, width1 = rectOne.width; 
    var x2=rectTwo.x, y2 = rectTwo.y, height2 = rectTwo.height, width2 = rectTwo.width; 

    return x1 < x2+width2 && x2 < x1+width1 && y1 < y2+height2 && y2 < y1+height1; 
}