2011-11-05 48 views
6

Tôi đang tạo trò chơi bằng Javascript sử dụng canvas yêu cầu phát hiện va chạm, trong trường hợp này nếu trình phát của người chơi chạm vào một ô, người chơi không được phép thông qua hộp.Phát hiện va chạm canvas Javascript

Tôi có một mảng toàn cầu được gọi là blockList chứa tất cả các hộp được vẽ vào canvas. Nó trông giống như thế này:

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

Và họ đang bị lôi kéo vào khung như thế này:

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

Tôi cũng có một đối tượng người chơi, trong đó có một phương pháp cập nhật và một phương pháp bốc thăm. Cập nhật đặt vị trí của trình phát dựa trên đầu vào bàn phím v.v. và vẽ được sử dụng bởi vòng lặp trò chơi chính để vẽ trình phát đến canvas. Người chơi đang được rút ra như thế này:

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; } 
      } 
     } 
    } 

Bây giờ, người chơi có tính chất nhất định là player.xpos, player.ypos, player.width, player.height. Các thuộc tính giống nhau tồn tại cho các khối. Vì vậy, tôi có tất cả mọi thứ tôi cần để cấy ghép phát hiện va chạm, tôi chỉ không có ý tưởng làm thế nào để làm điều đó. Tôi đã thử thực hiện những việc như:

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

nhưng không hoàn hảo hoặc có thể chơi được.

Có ai biết phương pháp hoặc chức năng đơn giản để có thể trả lại giá trị đúng hoặc sai dựa trên hai đối tượng có va chạm không?

Trả lời

8

tôi sử dụng các chức năng sau đây để phát hiện va chạm giữa hai hình chữ nhật:

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); 
}; 

này sẽ xác định xem hai hình vuông, tập trung ở (x1, y1)(x2, y2), với bên độ dài 2*size12*size2, tương ứng, được chồng chéo. Cần phải dễ dàng thay đổi các định nghĩa của left1, right1, v.v. để đối phó với hình chữ nhật chung thay vì chỉ hình vuông và sử dụng định dạng dữ liệu khác.

Cụ thể, left1 là phía bên trái của hình vuông đầu tiên, right1 phía bên phải, vv Lưu ý rằng, trong hệ tọa độ của tôi, trục y được đảo ngược (top1 < bottom1).

2

Bạn chỉ muốn biết hai hình chữ nhật trùng nhau?

Đây là một chức năng chống đạn dành cho bạn:

// 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; 
} 

Nếu chương trình của bạn có thể chắc chắn rằng những con số sẽ luôn luôn là hữu hạn, bạn có thể sử dụng một phiên bản đơn giản:

// 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; 
} 

làm gì nó là tìm kiếm ở phía bên phải và phía dưới cùng của hai hình chữ nhật, sau đó nó sẽ thấy nếu hình chữ nhật thứ hai bắt đầu từ bên ngoài hình chữ nhật đầu tiên hoặc nếu hình chữ nhật thứ nhất bắt đầu từ bên ngoài hình chữ nhật thứ hai.

Nếu một trong hai hình chữ nhật bắt đầu sau khi hình chữ nhật kia kết thúc, thì không có xung đột nào. Nếu không thì phải có va chạm.

0

Theo ý kiến ​​của tôi, tôi không phải là người hâm mộ các hàm yêu cầu nhiều tham số.

Đây là cách tôi sẽ thực hiện:

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; 
} 
Các vấn đề liên quan