Collision Detection
Table of Contents

LINE/RECTANGLE

We've actually already covered how to check if a line has hit a rectangle: it's really just four Line/Line collisions, one for each side!

For example, the left edge of the square starts at (rx,ry) and extends down to ry+rh. We can treat that as a line, using the algorithm we made in the last section:

var left = lineLine(x1,y1,x2,y2, rx,ry, rx,ry+rh);

This can be more easily visualized like this:

Dividing a rectangle into four lines

We do the same for the other three sides:

var left =   lineLine(x1,y1,x2,y2, rx,ry,rx, ry+rh);
var right =  lineLine(x1,y1,x2,y2, rx+rw,ry, rx+rw,ry+rh);
var top =    lineLine(x1,y1,x2,y2, rx,ry, rx+rw,ry);
var bottom = lineLine(x1,y1,x2,y2, rx,ry+rh, rx+rw,ry+rh);

If any of the above statements are true, the line has hit the rectangle.

if (left || right || top || bottom) {
    return true;
}
return false;

A full example is below. Note that the red dots are drawn in the Line/Line function, showing where the line intersects the rectangle. You can delete them from the function if you don't want them in your finished project.

var x1 = 0;      // points for line (controlled by mouse)
var y1 = 0;
var x2 = 0;      // static point
var y2 = 0;
 
var sx = 200;    // square position
var sy = 100;
var sw = 200;    // and size
var sh = 200;
 
 
function setup() {
    var canvas = createCanvas(600, 400);
 
    strokeWeight(5);  // make the line easier to see
}
 
 
function draw() {
    background(255);
 
    // set end of line to mouse coordinates
    x1 = mouseX;
    y1 = mouseY;
 
    // check if line has hit the square
    // if so, change the fill color
    var hit = lineRect(x1,y1,x2,y2, sx,sy,sw,sh);
    if (hit) fill(255,150,0);
    else fill(0,150,255);
    noStroke();
    rect(sx, sy, sw, sh);
 
    // draw the line
    stroke(0, 150);
    line(x1, y1, x2, y2);
}
 
 
// LINE/RECTANGLE
function lineRect(x1,y1,x2,y2, rx,ry,rw,rh) {
 
    // check if the line has hit any of the rectangle's sides
    // uses the Line/Line function below
    var left =   lineLine(x1,y1,x2,y2, rx,ry,rx, ry+rh);
    var right =  lineLine(x1,y1,x2,y2, rx+rw,ry, rx+rw,ry+rh);
    var top =    lineLine(x1,y1,x2,y2, rx,ry, rx+rw,ry);
    var bottom = lineLine(x1,y1,x2,y2, rx,ry+rh, rx+rw,ry+rh);
 
    // if ANY of the above are true, the line
    // has hit the rectangle
    if (left || right || top || bottom) {
        return true;
    }
    return false;
}
 
 
// LINE/LINE
function lineLine(x1,y1,x2,y2, x3,y3,x4,y4) {
 
    // calculate the direction of the lines
    var uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
    var uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
 
    // if uA and uB are between 0-1, lines are colliding
    if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
 
        // optionally, draw a circle where the lines meet
        var intersectionX = x1 + (uA * (x2-x1));
        var intersectionY = y1 + (uA * (y2-y1));
        fill(255,0,0);
        noStroke();
        ellipse(intersectionX, intersectionY, 20, 20);
 
        return true;
    }
    return false;
}

This algorithm can also be used to test line-of-sight. Let's say you have two objects and a rectangular obstacle: if you draw a line between one object and another, then check if it has hit the rectangle, you can tell if the objects can "see" each other or if they are hidden behind the obstacle.

An example of line of sight

For an example of this in code, see the "Line Of Sight" example in my Processing teaching repository.