Hello. I have been trying to find a way to get a box to push another box from any of its sides. This seems to almost work, but it keeps failing for some reason. Pushing from the top and right seem to work better than the left and bottom for some reason, but it has to be done very slowly.
I want to be able to use a box to push another box in a straight line left/right, up/down, and I also want to do it by a method that can be expanded so that the pushed box can push any reasonable number of other boxes in a row.
Whenever I find a method that pushes the box somewhat normally, moving the box around to a different side to push it in a different direction doesn’t work as expected, that’s why I was trying to use some way to choose how to constrain the move by which side the dragged box is on before it contacts the target box.
I was able to use a method that would push the box somewhat normally in one direction, but the dragged box would always overlap the pushed box if the mouse is moved quickly, I was hoping to avoid having that happen.
Am I on the right track with this, or is there a better approach?
Box pusher, target;
PVector m;
void setup() {
//size(screen.width, screen.height);
size(400, 500);
pusher = new Box(new PVector(100, 100), new PVector(110, 110), color(127, 192, 92, 40));
target = new Box(new PVector(width/2, height/2), new PVector(75, 75), color(0, 127, 255));
}
void draw() {
background(127);
m = new PVector(mouseX, mouseY);
pusher.move(m, new PVector(0, 0));
pusher.displayBox();
target.displayBox();
collisionTest();
target.displayLabel();
moveTarget();
}
void mousePressed() {
pusher.checkOver();
}
void mouseDragged() {
}
void mouseReleased() {
pusher.isLocked = false;
}
void moveTarget() {
println(target.pushSide, target.lastPushSide);
if (pusher.xyMax.y >= target.xyMin.y && target.lastPushSide == "N") {
target.isLocked = true;
target.move(new PVector(target.loc.x, pusher.xyMax.y), new PVector(0, target.dims.y/2));
}
if (pusher.xyMin.x <= target.xyMax.x && target.lastPushSide == "E") {
target.isLocked = true;
target.move(new PVector(pusher.xyMin.x, target.loc.y), new PVector(-target.dims.x/2, 0));
}
if (pusher.xyMin.y >= target.xyMax.y && target.lastPushSide == "S") {
target.isLocked = true;
target.move(new PVector(target.loc.x, pusher.xyMin.y), new PVector(0, -target.dims.y/2));
}
if (pusher.xyMax.x >= target.xyMin.x && target.lastPushSide == "W") {
target.isLocked = true;
target.move(new PVector(pusher.xyMax.x, target.loc.y), new PVector(target.dims.x/2, 0));
}
}
void collisionTest() {
// pusher is the box that is moving
// target is the box to be pushed
// north
if (pusher.xyMax.y <= target.xyMin.y && pusher.xyMin.x < target.xyMax.x && pusher.xyMax.x > target.xyMin.x) {
//target.highlightCollision(new PVector(target.xyMin.x, target.xyMin.y), new PVector(target.xyMax.x, target.xyMin.y));
target.pushSide = "N";
}
// east
else if (pusher.xyMin.x >= target.xyMax.x && pusher.xyMax.y > target.xyMin.y && pusher.xyMin.y < target.xyMax.y) {
//target.highlightCollision(new PVector(target.xyMax.x, target.xyMin.y), new PVector(target.xyMax.x, target.xyMax.y));
target.pushSide = "E";
}
// south
else if (pusher.xyMin.x <= target.xyMax.x && pusher.xyMin.y > target.xyMax.y && pusher.xyMax.x > target.xyMin.x) {
//target.highlightCollision(new PVector(target.xyMax.x, target.xyMax.y), new PVector(target.xyMin.x, target.xyMax.y));
target.pushSide = "S";
}
// west
else if (pusher.xyMin.y <= target.xyMax.y && pusher.xyMax.x < target.xyMin.x && pusher.xyMax.y > target.xyMin.y) {
//target.highlightCollision(new PVector(target.xyMin.x, target.xyMax.y), new PVector(target.xyMin.x, target.xyMin.y));
target.pushSide = "W";
} else {
target.isLocked = false;
target.lastPushSide = target.pushSide;
target.pushSide = "X";
}
}
class Box {
PVector loc, dims, xyMin, xyMax;
String pushSide, lastPushSide;
color c;
boolean isLocked;
Box(PVector loc, PVector dims, color c) {
this.loc = loc;
this.dims = dims;
this.c = c;
xyMin = PVector.sub(loc, PVector.div(dims, 2));
xyMax = PVector.add(xyMin, dims);
isLocked = false;
pushSide = "";
lastPushSide = "";
}
void displayBox() {
rectMode(CENTER);
fill(c);
strokeWeight(1);
stroke(255);
rect(loc.x, loc.y, dims.x, dims.y);
}
void displayLabel() {
textAlign(CENTER, CENTER);
textSize(18);
fill(255);
text(pushSide, loc.x, loc.y);
}
void update() {
xyMin = PVector.sub(loc, PVector.div(dims, 2));
xyMax = PVector.add(xyMin, dims);
}
void move(PVector newLoc, PVector offset) {
if (isLocked) {
loc = PVector.add(newLoc, offset);
update();
}
}
boolean mOver() {
if (m.x > xyMin.x - 1 && m.y > xyMin.y - 1 && m.x < xyMax.x && m.y < xyMax.y) {
return true;
} else {
return false;
}
}
void checkOver() {
if (mOver()) {
isLocked = true;
} else {
isLocked = false;
}
}
void highlightCollision(PVector a, PVector b) {
strokeWeight(5);
stroke(255, 0, 0);
line(a.x, a.y, b.x, b.y);
}
}