...
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.
Code Block | ||
---|---|---|
| ||
intvar rctl1X; // rectangle One x position intvar rctl1Y; // rectangle One y position intvar rctl1W = 40; // rectangle One Width intvar rctl1H = 70; // rectangle One Height // intvar rctl2X; // rectangle One x position intvar rctl2Y; // rectangle One y position intvar rctl2W = 100; // rectangle 2Two Width intvar rctl2H = 100; // rectangle 2Two Height voidfunction setup() { sizecreateCanvas(800, 600); noStroke(); rectMode(CENTER); rctl2X = width/2; rctl2Y = height/2; } voidfunction draw() { background(255); rctl1X = mouseX; rctl1Y = mouseY; booleanvar collision = checkCollision(rctl1X, rctl1Y, rctl1W, rctl1H, rctl2X, rctl2Y, rctl2W, rctl2H); if (collision) { fill(70255, 0, 0); } else { fill(2550, 0255, 0); } rect(rctl1X, rctl1Y, rctl1W, rctl1H); rect(rctl2X, rctl2Y, rctl2W, rctl2H); } // this method uses the center of the rectangles booleanfunction checkCollision(int r1x, int r1y, int r1w, int r1h, int r2x, int r2y, int r2w, int r2h) { // store the locations of each rectangles outer borders intvar top1 = r1y-r1h/2; intvar bottom1 = r1y+r1h/2; intvar right1 = r1x+r1w/2; intvar left1 = r1x-r1w/2; intvar top2 = r2y-r2h/2; intvar bottom2 = r2y+r2h/2; intvar right2 = r2x+r2w/2; intvar 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.
Code Block | ||
---|---|---|
| ||
booleanfunction checkRectangle( floatvar r1x, floatvar r1y, floatvar r1w, floatvar r1h, floatvar r2x, floatvar r2y, floatvar r2w, floatvar 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.
Code Block | ||
---|---|---|
| ||
let ballList = new[] ArrayList<Ball>(); Balllet mouseBall; voidlet centerBall; function setup() { sizecreateCanvas(600, 800); ballList.add( 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); } void function draw() { background(255); mouseBall.update(mouseX, mouseY); for (intvar i = 0; i<ballList.size()i< ballList.length; i++) { ballList.get([i)].drawBall(); mouseBall.checkCollision(ballList.get(i)._position, ballList.get(i)._radius); } mouseBall.drawBall(); } class Ball { PVector _position = new PVector(); int _radius; int colour = 250; public Ball(int constructor (x, int y, int r) { this._position.set = createVector(x, y, 0); this._radius = r; this.colour = 250; } void update(int x, int y) { this._position.setadd(x, y, 0); } void 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(); } void checkCollision(PVector position, int radius) { floatvar distance = PVectorp5.Vector.dist(this._position, position); if (this.distance <= radius +this._radius) { println("hit"); this.colour = 60; } else { this.colour = 255; } } } |
Point and Polygon
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. This is an adapted version for processing.
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| boolean pnpoly(PVector[] vertices, float testx, float testy
| |||||||
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++) { int vertex(polyPoints[i, j; boolean c].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 (ilet current = 0,; jcurrent =< vertices.length-1; i < vertices.length; j = i++) { if ( ((vertices[i].y>testy) != (vertices[j].y>testy)) && (testx < (vertices[j].x-vertices[i]; 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) * (testy-vertices[i]py - vc.y) / (vertices[j]vn.y-vertices[i] - vc.y) + vertices[i]vc.x)) ){ ccollision = !ccollision; } } return ccollision; } |
Bitmap 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.
...