This simple example demonstrates collisions detection between two rectangular objects. Note that this method will only work when both rectangles are axis-aligned, and only with rectangles!
However, it's possible to use this approach with invisible bounding boxes around more complex shapes. In many cases, as in old arcade games, the user may not even notice the collisions are based purely on rectangles.
var rctl1X; // rectangle One x position var rctl1Y; // rectangle One y position var rctl1W = 40; // rectangle One Width var rctl1H = 70; // rectangle One Height // var rctl2X; // rectangle One x position var rctl2Y; // rectangle One y position var rctl2W = 100; // rectangle Two Width var rctl2H = 100; // rectangle Two Height function setup() { createCanvas(800, 600); noStroke(); rectMode(CENTER); rctl2X = width/2; rctl2Y = height/2; } function draw() { background(255); rctl1X = mouseX; rctl1Y = mouseY; var collision = checkCollision(rctl1X, rctl1Y, rctl1W, rctl1H, rctl2X, rctl2Y, rctl2W, rctl2H); if (collision) { fill(255, 0, 0); } else { fill(0, 255, 0); } rect(rctl1X, rctl1Y, rctl1W, rctl1H); rect(rctl2X, rctl2Y, rctl2W, rctl2H); } // this method uses the center of the rectangles function checkCollision(r1x, r1y, r1w, r1h, r2x, r2y, r2w,r2h) { // store the locations of each rectangles outer borders var top1 = r1y-r1h/2; var bottom1 = r1y+r1h/2; var right1 = r1x+r1w/2; var left1 = r1x-r1w/2; var top2 = r2y-r2h/2; var bottom2 = r2y+r2h/2; var right2 = r2x+r2w/2; var left2 = r2x-r2w/2; if (top1>bottom2 || bottom1<top2 || right1<left2 || left1>right2) { return false; } else { return true; } }
This method uses the top left original of the rectangle and width and height to calculate the collision.
function checkRectangle( var r1x, var r1y, var r1w, var r1h, var r2x, var r2y, var r2w, var r2h) { return (r1x < r2x + r2w && r1x + r1w > r2x && r1y < r2y + r2h && r1y + r1h > r2y); }
The following example demonstrates a simple method for checking collisions between round objects. As in the above example, it can be used to create invisible bounding boxes for more complex shapes.
let ballList = [] ; let mouseBall; let centerBall; function setup() { createCanvas(600, 800); for (var j = 0; j< 10; j++) { centerBall = new Ball(width/2+j, height/2+j, 40); ballList.push(centerBall); } mouseBall = new Ball(mouseX, mouseY, 20); } function draw() { background(255); mouseBall.update(mouseX, mouseY); for (var i = 0; i< ballList.length; i++) { ballList[i].drawBall(); mouseBall.checkCollision(ballList.get(i)._position, ballList.get(i)._radius); } mouseBall.drawBall(); } class Ball { constructor (x, y, r) { this._position = createVector(x,y,0); this._radius = r; this.colour = 250; } update(x, y) { this._position.add(x, y, 0); } drawBall() { pushMatrix(); fill(this.colour, 0, 0); noStroke(); translate(this._position.x, this._position.y); ellipse(0, 0, this._radius* 2, this._radius*2); popMatrix(); } checkCollision(position,radius) { var distance = p5.Vector.dist(this._position, position); if (this.distance <= radius +this._radius) { println("hit"); this.colour = 60; } else { this.colour = 255; } } }
Sometimes it is only necessary to check if one specific points is inside a very complex shape. This complex shape can even be convex, which means that the edges of the polygon do not only point to the outside, but maybe also to the inside.
But there is a simple solution to check, if a point is located inside or outside this complex shape. W. Randolph Franklin created this method to check, if a point is located inside an Array of points.
const polyPoints = [{ x: 445, y: 240 }, { x: 350, y: 410 }, { x: 150, y: 410 }, { x: 45, y: 240 }, { x: 150, y: 60 }, { x: 240, y: 225 } ]; function setup() { createCanvas(500, 500); } function draw() { background('#f8f8f8'); drawCustomShape(); drawCollidingShape(); (hit()) ? fill('#131721'): noFill(); } //is colliding shape in custom shape function hit() { return polyPoint(polyPoints, mouseX, mouseY); } //shape being collided with function drawCustomShape() { beginShape(); strokeJoin(ROUND); strokeWeight(10) for (let i = 0; i < Object.keys(polyPoints).length; i++) { vertex(polyPoints[i].x, polyPoints[i].y); } endShape(CLOSE); } //colliding shape function drawCollidingShape() { push(); fill('#f8f8f8'); ellipse(mouseX, mouseY, 10, 10); pop(); } // POLYGON/POINT function polyPoint(vertices, px, py) { let collision = false; // go through each of the vertices, plus // the next vertex in the list let next = 0; for (let current = 0; current < vertices.length; current++) { // get next vertex in list // if we've hit the end, wrap around to 0 next = current + 1; if (next == vertices.length) next = 0; // get the Vectors at our current position // this makes our if statement a little cleaner let vc = vertices[current]; // c for "current" let vn = vertices[next]; // n for "next" // compare position, flip 'collision' variable // back and forth if (((vc.y >= py && vn.y < py) || (vc.y < py && vn.y >= py)) && (px < (vn.x - vc.x) * (py - vc.y) / (vn.y - vc.y) + vc.x)) { collision = !collision; } } return collision; }
For complex shapes, it's possible to create a reference bitmap to indicate hit areas. This reference can be black and white images, which correlates exactly to an image or shape that will be displayed on the screen. This method works well for game maps, and in situations where you are testing a simple shape against a complex one.
Out background image:
Our collision reference:
In the example, we just test one pixel directly under the mouse. This could be improved by testing at multiple points on the edge of the object we are testing.