最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Detect which side of a rectangle is colliding with another rectangle - Stack Overflow

programmeradmin6浏览0评论

i'm trying to develop a game using HTML5 canvas with javascript and I am having problems detecting collisions without hard coding it using the (x,y) coordinates of the two objects. In my code based from research, found out the mon algorithm in checking if the two objects are colliding which is

Object1 = a moving player
Object2 = fixed (x,y) points. Non movable object

(object1.x < object2.x + object2.width  && object1.x + object1.width  > object2.x &&
    object1.y < object2.y + object2.height && object1.y + object1.height > object2.y)

I tried it and developed it with other codes and it works, it detects the collisions. But I have an issue with the collisions, it works with the condition in the left side but when the object1 goes to the top, bottom or right of the object2 it goes back to the object2's left side. In other words, if the object1 goes to the top/bottom or right it goes back to the left side. Any kind of help would be much appreciated.

function collide(object1, object2){

    //object1 player
    this.x = object1.x;
    this.y = object1.y;
    this.w = object1.w;
    this.h = object1.h;

    //object2 any object 
    this.x2 = object2.x;
    this.y2 = object2.y;
    this.w2 = object2.w;
    this.h2 = object2.h;

    //collisions 
    var isCorrect = false;
    var side = 0;

    if ((this.x < this.x2 + this.w2) && (this.x + this.w > this.x2) 
        && (this.y < this.y2 + this.h2) && (this.h + this.y > this.y2)){
        isCorrect = true;
    }

    if (this.x + this.w > this.x2){
        //left check
        side = 1;
    }else if (this.x < this.x2 + this.w2){
        //right check
        side = 2;
    }else if (this.y + this.h > this.y2){
        //bottom check
        side = 3;
    }else if (this.y < this.y2 + this.h2){
        //top check
        side = 4;
    }

    if (isCorrect){
        if ((this.x + this.w > this.x2) && side == 1){
            playerObj.x -= 5;
        }else if ((this.x < this.x2 + this.w2) && side == 2){
            playerObj.x += 5;
        }else if ((this.y + this.h > this.y2) && side == 3){
            playerObj.y += 5;
        }else if ((this.y < this.y2 + this.h2) && side == 4){
            playerObj.y -= 5;
        }
    }
}

i'm trying to develop a game using HTML5 canvas with javascript and I am having problems detecting collisions without hard coding it using the (x,y) coordinates of the two objects. In my code based from research, found out the mon algorithm in checking if the two objects are colliding which is

Object1 = a moving player
Object2 = fixed (x,y) points. Non movable object

(object1.x < object2.x + object2.width  && object1.x + object1.width  > object2.x &&
    object1.y < object2.y + object2.height && object1.y + object1.height > object2.y)

I tried it and developed it with other codes and it works, it detects the collisions. But I have an issue with the collisions, it works with the condition in the left side but when the object1 goes to the top, bottom or right of the object2 it goes back to the object2's left side. In other words, if the object1 goes to the top/bottom or right it goes back to the left side. Any kind of help would be much appreciated.

function collide(object1, object2){

    //object1 player
    this.x = object1.x;
    this.y = object1.y;
    this.w = object1.w;
    this.h = object1.h;

    //object2 any object 
    this.x2 = object2.x;
    this.y2 = object2.y;
    this.w2 = object2.w;
    this.h2 = object2.h;

    //collisions 
    var isCorrect = false;
    var side = 0;

    if ((this.x < this.x2 + this.w2) && (this.x + this.w > this.x2) 
        && (this.y < this.y2 + this.h2) && (this.h + this.y > this.y2)){
        isCorrect = true;
    }

    if (this.x + this.w > this.x2){
        //left check
        side = 1;
    }else if (this.x < this.x2 + this.w2){
        //right check
        side = 2;
    }else if (this.y + this.h > this.y2){
        //bottom check
        side = 3;
    }else if (this.y < this.y2 + this.h2){
        //top check
        side = 4;
    }

    if (isCorrect){
        if ((this.x + this.w > this.x2) && side == 1){
            playerObj.x -= 5;
        }else if ((this.x < this.x2 + this.w2) && side == 2){
            playerObj.x += 5;
        }else if ((this.y + this.h > this.y2) && side == 3){
            playerObj.y += 5;
        }else if ((this.y < this.y2 + this.h2) && side == 4){
            playerObj.y -= 5;
        }
    }
}
Share Improve this question edited Apr 25, 2015 at 6:27 markE 105k11 gold badges170 silver badges183 bronze badges asked Apr 25, 2015 at 4:42 John SantosJohn Santos 511 silver badge3 bronze badges 2
  • you need to log the positions of your elements as they are being animated and find out where your if's don't catch the collision – nicholaswmin Commented Apr 25, 2015 at 4:44
  • What do you mean, sir? – John Santos Commented Apr 25, 2015 at 5:10
Add a ment  | 

1 Answer 1

Reset to default 18

This collision function will tell you which side of rect2 collided with rect1:

And of course, the opposite side of rect1 collided with rect2.

This function is a 2-pass test:

  • Test1: Check if the 2 rectangle's centers are close enough to be colliding

  • Test2: If yes, check the intersection depths to determine which side was most involved in the collision.

The collision function

function collide(r1,r2){
    var dx=(r1.x+r1.w/2)-(r2.x+r2.w/2);
    var dy=(r1.y+r1.h/2)-(r2.y+r2.h/2);
    var width=(r1.w+r2.w)/2;
    var height=(r1.h+r2.h)/2;
    var crossWidth=width*dy;
    var crossHeight=height*dx;
    var collision='none';
    //
    if(Math.abs(dx)<=width && Math.abs(dy)<=height){
        if(crossWidth>crossHeight){
            collision=(crossWidth>(-crossHeight))?'bottom':'left';
        }else{
            collision=(crossWidth>-(crossHeight))?'right':'top';
        }
    }
    return(collision);
}

Here's example code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

var rects=[];
var rect1={ x:100,y:100,w:85,h:85,fill:'red'}
var rect2={ x:10,y:10,w:40,h:60,fill:'gold'}

$("#canvas").mousemove(function(e){handleMouseMove(e);});

draw();

function collide(r1,r2){
  var dx=(r1.x+r1.w/2)-(r2.x+r2.w/2);
  var dy=(r1.y+r1.h/2)-(r2.y+r2.h/2);
  var width=(r1.w+r2.w)/2;
  var height=(r1.h+r2.h)/2;
  var crossWidth=width*dy;
  var crossHeight=height*dx;
  var collision='none';
  //
  if(Math.abs(dx)<=width && Math.abs(dy)<=height){
    if(crossWidth>crossHeight){
      collision=(crossWidth>(-crossHeight))?'bottom':'left';
    }else{
      collision=(crossWidth>-(crossHeight))?'right':'top';
    }
  }
  return(collision);
}

function draw(){
  ctx.clearRect(0,0,cw,ch);
  ctx.fillStyle=rect1.fill;
  ctx.fillRect(rect1.x,rect1.y,rect1.w,rect1.h);
  ctx.fillStyle=rect2.fill;
  ctx.fillRect(rect2.x,rect2.y,rect2.w,rect2.h);
  var side=collide(rect1,rect2);
  ctx.fillStyle='green'
  if(side=='top'){ ctx.fillRect(rect2.x,rect2.y,rect2.w,3); }
  if(side=='right'){ ctx.fillRect(rect2.x+rect2.w,rect2.y,3,rect2.h); }
  if(side=='bottom'){ ctx.fillRect(rect2.x,rect2.y+rect2.h,rect2.w,3); }
  if(side=='left'){ ctx.fillRect(rect2.x,rect2.y,3,rect2.h); }
}

function handleMouseMove(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  rect2.x=mouseX;
  rect2.y=mouseY;

  draw();

}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move the mouse to drag the gold rect<br>Any colliding side of gold rect will highlight</h4>
<canvas id="canvas" width=300 height=300></canvas>

发布评论

评论列表(0)

  1. 暂无评论