Jump to content

Collision Detect


pdiddles03
 Share

Recommended Posts

I need to determin which side was hit when collision is performed.  I for some reason never can figure it out.  It only returns two sides regardless of where it hits. please help! I have been stuck on this forever!

 

function collision(obj1, obj2){
  if(
    obj1.x + (obj1.width/2) > obj2.x - (obj2.width/2) &&
    obj1.x - (obj1.width/2) < obj2.x + (obj2.width/2) &&
    obj1.y + (obj1.height/2) > obj2.y - (obj2.height/2) &&
    obj1.y - (obj1.height/2) < obj2.y + (obj2.height/2)
  ){
    if(
      obj1.prev_y + (obj1.height/2) >= obj2.y - (obj2.height/2) &&
      obj1.x + (obj1.width/2) > obj2.x - (obj2.width/2) &&
      obj1.x - (obj1.width/2) < obj2.x + (obj2.width/2)
    ){
      return 'bottom';
    }
    else if(
      obj1.prev_y - (obj1.height/2)  <= obj2.y + (obj2.height/2) &&
      obj1.x + (obj1.width/2) > obj2.x - (obj2.width/2) &&
      obj1.x - (obj1.width/2) < obj2.x + (obj2.width/2)
    ){
      return 'top';
    }
    else if(
      obj1.prev_x + (obj1.width/2) > obj2.x - (obj2.width/2) &&
      obj1.y + (obj1.height/2) > obj2.y - (obj2.height/2) &&
      obj1.y - (obj1.height/2) < obj2.y + (obj2.height/2)
    ){
      return 'right';
    }
    else if(
      obj1.prev_x - (obj1.width/2) < obj2.x + (obj2.width/2) &&
      obj1.y + (obj1.height/2) > obj2.y - (obj2.height/2) &&
      obj1.y - (obj1.height/2) < obj2.y + (obj2.height/2)
    ){
      return 'left';
    }

  }
}

 

Link to comment
Share on other sites

Here's something I whipped up. I haven't tested it, so I don't know for certain if it works. Might also malfunction if the objects move at high speeds.

 

function collision(obj1, obj2)
{
	if(
	obj1.x + (obj1.width/2) > obj2.x - (obj2.width/2) &&
	obj1.x - (obj1.width/2) < obj2.x + (obj2.width/2) &&
	obj1.y + (obj1.height/2) > obj2.y - (obj2.height/2) &&
	obj1.y - (obj1.height/2) < obj2.y + (obj2.height/2)
	)
	{
		//I haven't tested this.
		//I forget if positive y is up or down. I might have gotten that backwards.
		
		//Get the horizontal and vertical distance between the objects.
		//You'll have to do some funny math with this if you want it to work with objects that are taller or wider.
		var xDistance = Math.abs(obj1.x-obj2.x)
		var yDistance = Math.abs(obj1.y-obj2.y)
		
		
		if(xDistance > yDistance)
		{
			if(obj1.x < obj2.x)
			{
				return "right"
			}
			else
			{
				return "left"
			}
		}
		else if(yDistance > xDistance)
		{
			if(obj1.y < obj2.y)
			{
				return "bottom"
			}
			else
			{
				return "top"
			}
		}
		else//if it is in a perfectly diagonal direction or at the same spot as the first object...do what?
		{
			return "insanity"
		}

	}
}

 

Link to comment
Share on other sites

  • 3 weeks later...

I thought: Better late than never. Inky cricket's solution works well for square elements. Here is a solution for rectangles of any shape. The corner collision is not 100% perfect at extreme cases that way; the correct/best solution would be to step back time and advance in smaller steps until the corner collision is solved by one of the two unseparated cases, but it works. Again, depending on your axis orientation you might want to swap 'top' and 'bottom'.

The solution uses the separation axis theorem (which is a fancy way of looking at the borders, at least for rectangles) to check for simple collisions: if two axes were separated before the collision but are no longer separated after collision, then movement among them caused the collision.

For collision around corners (both axes were separated before collision) the simple detection might not be enough, so the objects' relative velocity is compared to their distance before the collision, to see if the collision was caused by the objects' x- or y-movement.

 

function unseparated(x1, d1, x2, d2) { // test for normal axis separation
    return (x1 <= x2 && x2 <= x1 + d1) || (x2 <= x1 && x1 <= x2 + d2);
};

function collision(a, b) {
    if (unseparated(a.x, a.width, b.x, b.width) &&
        unseparated(a.y, a.height, b.y, b.height)) { // collision
      vx = (b.x - b.prev_x) - (a.x - a.prev_x); // relative x-velocity
      vy = (b.y - b.prev_y) - (a.y - a.prev_y); // relative y-velocity
      if (unseparated(a.prev_x, a.width, b.prev_x, b.width)) { // x-dir overlapped before -> collision in y-direction
        return (vy > 0) ? 'top' : 'bottom';
      } else if (unseparated(a.prev_y, a.height, b.prev_y, b.height)) { // y overlapped before -> collision in 
        return (vy > 0) ? 'left' : 'right';
      }
      else {  // diagonal-ish collision near corners
        dx = b.prev_x - a.prev_x;  // x-distance before collision
        dy = b.prev_y - a.prev_y;  // y-distance before collision
        if (Math.abs(vx) >= Math.abs(dx) && // x-speed was enough to collide
            dx * dy > 0){                   // x-velocity was in x-direction 
          return (vx > 0) ? 'right' : 'left';
        }
        else {                             // x-speed was not enough to collide => y-collision
          return (vy > 0) ? 'top' : 'bottom';
        }
      }
    }
};

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...