Thanks for the assistance @Hyperion65, you’re amazing.
I got it working exactly for my purposes by modifying that example from Jeffrey Thompson.
It might not be pretty or well built, but it does what it needs to.
Thanks again for your assistance and patience.
My Solution:
//Jeffrey Thmpson
//http://jeffreythompson.org/collision-detection/matrix-transformations.php
ArrayList<Square> squares;
int w = 100;
int tmrStart;
void setup() {
size(400, 400);
init();
}
void init() {
// squares defined as PVector
// arrays around the origin
PVector[] sq = {
new PVector(-50, -50),
new PVector(50, -50),
new PVector(50, 50),
new PVector(-50, 50)
};
squares = new ArrayList<Square>();
boolean r = false;
tmrStart = millis();
for (int i = 0; i < 5; i++) {
if (random(2) > 1) r = false;
else r = true;
squares.add(new Square(int(random(25, width-25)), int(random(25, height-25)), r, i, sq));
if (i > 0) {
//check for collision
for (int j = 0; j < squares.size(); j++) {
if (i != j) {
boolean hit = polyPoly(squares.get(j).getSqScreen(), squares.get(i).getSqScreen());
if (hit) squares.get(i).newPos();
}
}
}
}
}
void recheck() {
for (int i = 0; i < squares.size(); i++) {
if (millis() - tmrStart > 1000) break;
if (i > 0) {
//check for collision
for (int j = 0; j < squares.size(); j++) {
if (i != j) {
boolean hit = polyPoly(squares.get(j).getSqScreen(), squares.get(i).getSqScreen());
if (hit) squares.get(i).newPos();
}
}
}
}
}
void mouseReleased() {
init();
}
void draw() {
background(255);
for (Square s : squares) {
s.draw();
}
}
// a function that returns the actual screen coordinates
// after matrix transformations (like translate and rotate)
// we could do this up above but easier to make it a function
// that can take any number of polygon points
PVector[] pointsToScreenCoords(PVector[] points) {
PVector[] screenPoints = new PVector[points.length]; // create output array
for (int i=0; i<points.length; i++) { // go through all the points
float x = screenX(points[i].x, points[i].y); // get the screen x coordinate
float y = screenY(points[i].x, points[i].y);
screenPoints[i] = new PVector(x, y);
}
return screenPoints;
}
// POLYGON/POLYGON
boolean polyPoly(PVector[] p1, PVector[] p2) {
// go through each of the vertices, plus the next vertex in the list
int next = 0;
for (int current=0; current<p1.length; current++) {
// get next vertex in list
// if we’ve hit the end, wrap around to 0
next = current+1;
if (next == p1.length) next = 0;
// get the PVectors at our current position
// this makes our if statement a little cleaner
PVector vc = p1[current]; // c for “current”
PVector vn = p1[next]; // n for “next”
// now we can use these two points (a line) to compare to the
// other polygon’s vertices using polyLine()
boolean collision = polyLine(p2, vc.x, vc.y, vn.x, vn.y);
if (collision) return true;
// optional: check if the 2nd polygon is INSIDE the first
collision = polyPoint(p1, p2[0].x, p2[0].y);
if (collision) return true;
}
return false;
}
// POLYGON/LINE
boolean polyLine(PVector[] vertices, float x1, float y1, float x2, float y2) {
// go through each of the vertices, plus the next vertex in the list
int next = 0;
for (int 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 PVectors at our current position
// extract X/Y coordinates from each
float x3 = vertices[current].x;
float y3 = vertices[current].y;
float x4 = vertices[next].x;
float y4 = vertices[next].y;
// do a Line/Line comparison
// if true, return ‘true’ immediately and stop testing (faster)
boolean hit = lineLine(x1, y1, x2, y2, x3, y3, x4, y4);
if (hit) {
return true;
}
}
// never got a hit
return false;
}
// LINE/LINE
boolean lineLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
// calculate the direction of the lines
float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
float 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) {
return true;
}
return false;
}
// POLYGON/POINT
// used only to check if the second polygon is INSIDE the first
boolean polyPoint(PVector[] vertices, float px, float py) {
boolean collision = false;
// go through each of the vertices, plus the next vertex in the list
int next = 0;
for (int 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 PVectors at our current position
// this makes our if statement a little cleaner
PVector vc = vertices[current]; // c for “current”
PVector 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;
}
class Square {
PVector[] arr;
PVector pos;
boolean rot;
color c = color(0, 150);
int id;
Square(int x, int y, boolean rot, int id, PVector[] arr) {
pos = new PVector(x, y);
this.rot = rot;
this.arr = arr;
this.id = id;
}
void draw() {
// move the origin to the position of the first square
pushMatrix();
translate(pos.x, pos.y);
if (rot) rotate(radians(45));
// and draw the square!
fill(c);
noStroke();
beginShape();
for (PVector pt : arr) {
vertex(pt.x, pt.y);
}
endShape(CLOSE);
fill(0);
text(id, 0, 0);
popMatrix();
}
PVector[] getSqScreen() {
pushMatrix();
translate(pos.x, pos.y);
if (rot) rotate(radians(45));
PVector[] square1Screen = pointsToScreenCoords(arr);
popMatrix();
return square1Screen;
}
void setFill(color c) {
this.c = c;
}
void newPos() {
pos.x = int(random(50, width-50));
pos.y = int(random(50, height-50));
recheck();
}
}