Can't figure out logic for overlapping squares when clicked

I’m having trouble figuring out how to emulate this with p5.js. My code is below. I’m able to get each box to move individually, even if they’re overlapping… But the moment I try to change the order of the boxes array they pop in front of each other and behind each other when I click overlapping boxes.

``````var boxW = 75;
var boxH = 75;
var xOffset = 0.0;
var yOffset = 0.0;
var boxCount = 3;
var boxes = [];

function setup() {
createCanvas(600, 400);
for (i = 0; i < boxCount; i++) {
boxes[i] = new Box(
width / 2 - boxW + i * boxW - 50 * i,
height / 2 - boxH + i * boxH - 50 * i,
boxW,
boxH,
color(128, random(255), 255)
);
}
}

function draw() {
background(25);
for (var i = 0; i < boxes.length; i++) {
boxes[i].contains(mouseX, mouseY);
boxes[i].display();

for (var j = 0; j < boxes.length; j++) {
if (i > j && boxes[i].overlaps(boxes[j])) {
if (boxes[i].overlaps(boxes[j])) {
boxes[i].overlapsResolution();
boxes[j].overlapsResolution();
}
}
}
}
}
// TESTING
// function mousePressed() {
//   for (var i = boxes.length - 1; i >= 0; i--) {
//     if (boxes[i].clicked(mouseX, mouseY)) {
//       //console.log("i: " + i);
//       for (var j = boxes.length - 1; j >= 0; j--) {
//         if (boxes[j].clicked(mouseX, mouseY)) {
//           //console.log("j: " + j);
//           if (i == j) {
//             boxes.push(boxes.splice(j, 1)[0]);
//             boxes[i].grabbed = true;
//           } else if (i > j) {
//             // boxes.push(boxes.splice(j, 1)[0]);
//             boxes[i].grabbed = false;
//           } else if (i < j) {
//             boxes[i].grabbed = false;
//           }
//         }
//       }
//     }
//   }
// }

// WORKING
function mousePressed() {
for (var i = 0; i < boxes.length; i++) {
if (boxes[i].clicked(mouseX, mouseY)) {
for (var j = 0; j < boxes.length; j++) {
if (boxes[j].clicked(mouseX, mouseY)) {
if (j > i) {
boxes[i].grabbed = false;
} else if (j == i) {
boxes.push(boxes.splice(j, 1)[0]);
boxes[i].grabbed = true;
}
}
}
}
}
}

function mouseDragged() {
for (var i = 0; i < boxes.length; i++) {
boxes[i].dragged(mouseX, mouseY, boxes, i);
}
}
function mouseReleased() {
for (var i = 0; i < boxes.length; i++) {
boxes[i].released();
}
}

function changePos(arr, from, to) {
arr.splice(to, 0, arr.splice(from, 0)[arr.length]);
return arr;
}

function Box(x, y, w, h, col) {
this.x = x; // x
this.y = y; // y
this.w = w; // width
this.h = h; // height

this.cx = this.x + this.w / 2; // center x
this.cy = this.y + this.h / 2; // center y

this.col = col; // box fill color
this.stroke = color(0, 128, 255); // box stroke color
this.strokeWeight = 0;

this.overlap = false;

// Mouse Variables
this.grabbed = false; // whether grabbed
this.xOffset = 0.0; // x offset when grabbed
this.yOffset = 0.0; // y offset when grabbed
this.selected = false; // whether selected
this.hovered = false; // whether hovered

// Mouse Functions
this.contains = function (mX, mY) {
if (
mX > this.x &&
mX < this.x + this.w &&
mY > this.y &&
mY < this.y + this.h
) {
return true;
} else {
// this.hovered = false;
return false;
}
};

this.clicked = function (mX, mY) {
if (this.contains(mX, mY)) {
this.xOffset = mX - this.x;
this.yOffset = mY - this.y;
return true;
} else {
return false;
}
};

this.dragged = function (mX, mY) {
if (this.grabbed) {
this.x = mX - this.xOffset;
this.y = mY - this.yOffset;
}
};

this.released = function () {
this.grabbed = false;
};

// Box Interactions
this.overlaps = function (other) {
if (
this.x <= other.x + other.w &&
this.y <= other.y + other.h &&
this.x + this.w >= other.x &&
this.y + this.h >= other.y
) {
this.overlap = true;
} else {
this.overlap = false;
}
};

this.overlapsResolution = function () {};

this.changeColor = function () {};

this.display = function () {
this.changeColor();
strokeWeight(this.strokeWeight);
stroke(this.stroke);
fill(this.col);
rect(this.x, this.y, this.w, this.h);
};

this.move = function () {
if (!this.grabbed) {
this.x = this.x + random(-2, 2);
this.y = this.y + random(-2, 2);
}
};
}
``````

I would recommend that your box array be sorted from back to front. When you click the mouse, test the boxes in order from front to back to see if the mouse is in that box. As soon as you are in a box, that is the one selected, so remove it from its position in the list and move it to the front of the list. When you drag, the box you are moving should already be at the front of the list since you placed it there when clicking, so you should only move the first box in the list. If your mouse click is not inside any of the boxes, you’ll need some global flag to remember that so that your drag doesn’t try to move the top box when it hadn’t been selected.

Thank you! This helped. This is what I came up with for function mousePressed().

``````function mousePressed() {
for (var i = boxes.length - 1; i >= 0; i--) {
if (boxes[i].clicked(mouseX, mouseY)) {
console.log("i: " + i);
boxes[i].grabbed = true;
boxes.push(boxes.splice(i, 1)[0]);
return
}
}
}
``````

Working Code:

``````var boxW = 75;
var boxH = 75;
var xOffset = 0.0;
var yOffset = 0.0;
var boxCount = 3;
var boxes = [];

function setup() {
createCanvas(600, 400);
for (i = 0; i < boxCount; i++) {
boxes[i] = new Box(
width / 2 - boxW + i * boxW - 50 * i,
height / 2 - boxH + i * boxH - 50 * i,
boxW,
boxH,
color(128, i * 85, 255)
);
}
}

function draw() {
background(25);
for (var i = 0; i < boxes.length; i++) {
boxes[i].contains(mouseX, mouseY);
boxes[i].display();

for (var j = 0; j < boxes.length; j++) {
if (i > j && boxes[i].overlaps(boxes[j])) {
if (boxes[i].overlaps(boxes[j])) {
boxes[i].overlapsResolution();
boxes[j].overlapsResolution();
}
}
}
}
}
// TESTING
function mousePressed() {
for (var i = boxes.length - 1; i >= 0; i--) {
if (boxes[i].clicked(mouseX, mouseY)) {
console.log("i: " + i);
boxes[i].grabbed = true;
boxes.push(boxes.splice(i, 1)[0]);
return
}
}
}

function mouseDragged() {
for (var i = 0; i < boxes.length; i++) {
boxes[i].dragged(mouseX, mouseY, boxes, i);
}
}
function mouseReleased() {
for (var i = 0; i < boxes.length; i++) {
boxes[i].released();
}
}

function changePos(arr, from, to) {
arr.splice(to, 0, arr.splice(from, 0)[arr.length]);
return arr;
}

function Box(x, y, w, h, col) {
this.x = x; // x
this.y = y; // y
this.w = w; // width
this.h = h; // height

this.cx = this.x + this.w / 2; // center x
this.cy = this.y + this.h / 2; // center y

this.col = col; // box fill color
this.stroke = color(0, 128, 255); // box stroke color
this.strokeWeight = 0;

this.overlap = false;

// Mouse Variables
this.grabbed = false; // whether grabbed
this.xOffset = 0.0; // x offset when grabbed
this.yOffset = 0.0; // y offset when grabbed
this.selected = false; // whether selected
this.hovered = false; // whether hovered

// Mouse Functions
this.contains = function (mX, mY) {
if (
mX > this.x &&
mX < this.x + this.w &&
mY > this.y &&
mY < this.y + this.h
) {
return true;
} else {
// this.hovered = false;
return false;
}
};

this.clicked = function (mX, mY) {
if (this.contains(mX, mY)) {
this.xOffset = mX - this.x;
this.yOffset = mY - this.y;
return true;
} else {
return false;
}
};

this.dragged = function (mX, mY) {
if (this.grabbed) {
this.x = mX - this.xOffset;
this.y = mY - this.yOffset;
}
};

this.released = function () {
this.grabbed = false;
};

// Box Interactions
this.overlaps = function (other) {
if (
this.x <= other.x + other.w &&
this.y <= other.y + other.h &&
this.x + this.w >= other.x &&
this.y + this.h >= other.y
) {
this.overlap = true;
} else {
this.overlap = false;
}
};

this.overlapsResolution = function () {};

this.changeColor = function () {};

this.display = function () {
this.changeColor();
strokeWeight(this.strokeWeight);
stroke(this.stroke);
fill(this.col);
rect(this.x, this.y, this.w, this.h);
};

this.move = function () {
if (!this.grabbed) {
this.x = this.x + random(-2, 2);
this.y = this.y + random(-2, 2);
}
};
}

``````