What is the best strategy to eliminate objects that pass a certain condition in an array?
in
Programming Questions
•
1 years ago
I have a canvas on which short phrases fade in and fade out in randomly generated changing x and y positions. I created functions called detectOverlap and overlapTest to check when there is an overlap between two phrases with the objective of NOT displaying those. This detection mechanism seems to work.
In reasoning how to address this, I was thinking that one of the overlapping object (hypothetically the one that is generated over the other) would be eliminated. Is this a good way to proceed and if so, how does one eliminate some objects but not others.
It is a bit complicated for me to figure out how to do this in the array they are in.
Ideally, I would also run a test to make sure that the same string (phrase) is not being displayed twice (since my array is not that big right now, this happens quite a bit). I would also proceed by eliminating the second iteration.
I apologize for my spaghetti code but I code like I make ceramic pots (in a very messy way).
TextField textbox;
WordCollage wc;
void setup() {
size (screen.width, screen.height);
background (225, 225, 255);
wc=new WordCollage (0, 0, width, height);
}
void draw() {
background (225, 225, 255);
frameRate(30);
if (wc.overlapTest()) {
wc.display();
}
textbox.display();
textbox.rollOver();
}
// mouse and keyboard events
void mousePressed () {
textbox.press(mouseX, mouseY);
}
void mouseDragged() {
textbox.drag (mouseX, mouseY);
}
void mouseReleased () {
textbox.release ();
}
void keyPressed () {
textbox.keyPressed();
}
/*--- THIS IS THE HIGHEST ABSTRACT CLASS FROM WHICH NO OBJECTS ARE INSTANTIATED ---*/
abstract class InteractiveBoxes {
int boxPosX, boxPosY, boxPosW, boxPosH;
int boxPosXOff, boxPosYOff;
boolean over = false;
boolean pressed = false;
InteractiveBoxes (int tempBoxPosX, int tempBoxPosY, int tempBoxWidth, int tempBoxHeight) {
boxPosX=tempBoxPosX;
boxPosY=tempBoxPosY;
boxPosW=tempBoxWidth;
boxPosH=tempBoxHeight;
}
// methods of the abstract InteractiveBoxes class
void rollOver () {
if ((mouseX>=boxPosX) && (mouseX <=boxPosX+boxPosW) && (mouseY>=boxPosY) && (mouseY<=boxPosY+boxPosH)) {
over=true;
}
else {
over=false;
}
} // end of the rollOver function
void click (int mX, int mY) {
boxPosX=mouseX;
boxPosY=mouseY;
boxPosW=mouseX-boxPosX;
boxPosH=mouseY-boxPosY;
} // end the click function
void press (int mX, int mY) {
if (over==true) {
pressed=true;
boxPosXOff=mX-boxPosX;
boxPosYOff=mY-boxPosY;
}
} // end of the press function
void drag (int mX, int mY) {
if (pressed==true) {
boxPosX=mX-boxPosXOff;
boxPosY=mY-boxPosYOff;
}
} // end of the drag function
void release () {
pressed=false;
} // end of release function
}
class TextField extends InteractiveBoxes {
PFont fontA;
String userInputText= ""; // declare and initialize the variable to store text while it is being typed
String captureText= ""; // declare and initialize the variable to save typed text when return key is hit
String[] fullComment;
int spacing;
int fontHeight;
color boxClr;
// constructor of the TextField class
TextField (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color tempBoxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
fontA = loadFont("ArialMT-48.vlw");
boxClr=tempBoxClr;
spacing = 5;
}
void appendStrings(String filename, String[] file) // This was a response from the processing forum on how to append text
{
try {
// Create file
FileWriter fstream = new FileWriter(sketchPath(filename), true); // boolean where true means append
PrintWriter out = new PrintWriter(fstream); // // Create a new file in the sketch directory
for (int i =0 ; i < file.length; ++i) { // go through String array
out.println(file[i]); // write each character in the String array in the text file
}
out.close(); //Close the output stream
}
catch (Exception e) { //Catch exception if any
println("Error: " + e.getMessage());
}
}
void display () {
// Display everything
fill (boxClr);
strokeWeight(4);
strokeJoin(ROUND);
rect (boxPosX, boxPosY, boxPosW, boxPosH);
fontHeight=16; // set the font size
textFont(fontA, fontHeight); // Set the font type and size at Arial 14 for text instructions
fill(240); // Set the fill for text instructions
text("Drag this box where you please. Type your graffiti in \na single phrase and hit return twice to add to wall:", boxPosX+spacing, boxPosY+fontHeight+spacing);
fontHeight=20; // reset the font size
fill (255); //set the fill for the user's input text
textFont(fontA, fontHeight); // Set the font type and size at Arial 20 for text instructions
text(userInputText, boxPosX+spacing, boxPosY+4*fontHeight+spacing);
text(captureText, boxPosX+spacing, boxPosY+4*fontHeight+spacing);
}
void keyPressed() {
fullComment = splitTokens(captureText, "/");
if (keyCode == BACKSPACE) {
userInputText = userInputText.substring(0, userInputText.length() - 1); // allow the backspace key to go back and erase characters
}
else
if (key != CODED) userInputText += key; // capture characters of any keys that are pressed except for the coded ones
// If the return key is pressed, save the String and clear it
if (key == RETURN || key == ENTER) {
captureText = userInputText;
appendStrings("userinput.txt", fullComment);
userInputText = ""; // Clear the String by setting it equal to ""
}
}
} // end of TextField class
class WordCollage extends InteractiveBoxes {
Graffiti[] thisGraffiti;
String [] retrieve;
PFont [] fonts;
String[] fontNames = {
"VinerHandITC-48", "SegoeScript-Bold-48", "RageItalic-48", "Mistral-48", "Vivaldii-48", "Pristina-Regular-48", "BradleyHandITC-48"
};
// constructor of the Graffiti Collage class
WordCollage (int boxPosX, int boxPosY, int boxPosW, int boxPosH) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
retrieve = loadStrings ("userinput.txt");
fonts=new PFont[fontNames.length];
for (int i = 0; i < fontNames.length; ++i) {
fonts[i] = loadFont(fontNames[i] + ".vlw");
}
thisGraffiti = new Graffiti[retrieve.length];
for (int i = 0; i < retrieve.length; ++i) {
thisGraffiti[i] = new Graffiti( retrieve[(int) random(retrieve.length)], fonts[(int) random(fonts.length)] );
}
} // end of the constructor
boolean overlapTest () {
for (int i=0; i<retrieve.length ; i++) { // create a for loop that will go through all the graffiti objects in the array
for (int j=0; j<retrieve.length ; j++) { // create another for loop that will go through all the graffiti objects in the array
if (j!=i && (thisGraffiti[i].detectOverlap(thisGraffiti[j]))) {
}
}
}
println("overlap");
return true;
}
void display () {
for (int n = 0; n < thisGraffiti.length; n ++ ) {
thisGraffiti[n].display();
}
}
}
/* Here I will need an array out of bound exception and also an exception for when the text file is empty*/
class Graffiti {
String graffitiText;
int graffitiX, graffitiY;
float opacity, randomOpacity, opacitySpeed;
int opacityDir;
color fClr;
PFont font;
Graffiti(String graffitiText, PFont font) { // constructor for the Graffiti class
this.graffitiText = graffitiText;
this.font = font;
graffitiX = int(random (screen.width));
graffitiX = constrain(graffitiX, 5, screen.width-27*graffitiText.length()); // constrain the x position so that the phrases are not cut off the screen
graffitiY = int(random (screen.height));
graffitiY = constrain(graffitiY, 50, screen.height-110); // constrain the y position so that the phrases are not cut off the screen
fClr = color(random (0, 175), random(0, 175), random(0, 175));
opacity = random(255);
randomOpacity = 1;
opacityDir= int (randomOpacity);
opacitySpeed=random(1, 3);
println("Added Graffiti: " + graffitiText + " " + graffitiX + "," + graffitiY + "," + opacity + "," + opacityDir);
} // end of the constructor for the Graffiti class
boolean detectOverlap (Graffiti checkOverlap) {
if ((graffitiX>=(checkOverlap.graffitiX+checkOverlap.graffitiText.length()*27)) || ((graffitiX+(27*graffitiText.length()))<= (checkOverlap.graffitiX)) || ((graffitiY)>=(checkOverlap.graffitiY+110)) || ((graffitiY+110) <= (checkOverlap.graffitiY)))
{ // conditional block (from the vehicle collision detection assignment) that states that if the left of a graffiti is equal or more than the right of another graffiti OR if the right of a graffiti is equal or less than the left of another graffiti OR if the top of a graffiti is equal or more than the bottom of another graffiti OR if the bottom of a graffiti is equal or less than the top of another graffiti, then...
return false; // ...return false if any of these conditions are met
} // end of the if block
else { // if none of these conditions are met...
return true; // return true
} // end of the else block
} // end of the detect Overlap function
void display() {
// Fade ins and fade outs by incrementing the opacity variable in function of the frameRate
opacity += opacityDir * opacitySpeed; // this is the speed of the fading effect
opacity = constrain(opacity, 0, 255); // constrain the range of the opacity from 0 to 255
if ( (opacity >= 255 && opacityDir == 1) || // When we hit maximum opacity...
(opacity <= 0 && opacityDir == -1)) { //... or when we are at minimum opacity...
opacityDir *= -1; //...change direction of the opacity fade
if (opacity <= 0) { // when graffiti is invisible...
graffitiX = int(random (screen.width)); //...choose new x
graffitiX = constrain(graffitiX, 5, screen.width-27*graffitiText.length()); // constrain the x position so that the phrases are not cut off the screen
graffitiY = int(random (screen.height)); //...choose new y
graffitiY = constrain(graffitiY, 50, screen.height-110); // constrain the y position so that the phrases are not cut off the screen
fClr = color(random (0, 175), random(0, 175), random(0, 175)); //...and choose new font color
} // end of the loop that deals with the graffiti once it has become invisible
} // end of the loop that deals with the fade ins and fade outs of opacity
textFont(font, 48); // display the graffiti with correct font/color
fill(fClr, opacity); // color the text randomly and fade in/out with the opacity variable
text(graffitiText, graffitiX, graffitiY); // write the graffiti in a random x and y position
} // end the display function
} // end the Graffiti class
In reasoning how to address this, I was thinking that one of the overlapping object (hypothetically the one that is generated over the other) would be eliminated. Is this a good way to proceed and if so, how does one eliminate some objects but not others.
It is a bit complicated for me to figure out how to do this in the array they are in.
Ideally, I would also run a test to make sure that the same string (phrase) is not being displayed twice (since my array is not that big right now, this happens quite a bit). I would also proceed by eliminating the second iteration.
I apologize for my spaghetti code but I code like I make ceramic pots (in a very messy way).
TextField textbox;
WordCollage wc;
void setup() {
size (screen.width, screen.height);
background (225, 225, 255);
wc=new WordCollage (0, 0, width, height);
}
void draw() {
background (225, 225, 255);
frameRate(30);
if (wc.overlapTest()) {
wc.display();
}
textbox.display();
textbox.rollOver();
}
// mouse and keyboard events
void mousePressed () {
textbox.press(mouseX, mouseY);
}
void mouseDragged() {
textbox.drag (mouseX, mouseY);
}
void mouseReleased () {
textbox.release ();
}
void keyPressed () {
textbox.keyPressed();
}
/*--- THIS IS THE HIGHEST ABSTRACT CLASS FROM WHICH NO OBJECTS ARE INSTANTIATED ---*/
abstract class InteractiveBoxes {
int boxPosX, boxPosY, boxPosW, boxPosH;
int boxPosXOff, boxPosYOff;
boolean over = false;
boolean pressed = false;
InteractiveBoxes (int tempBoxPosX, int tempBoxPosY, int tempBoxWidth, int tempBoxHeight) {
boxPosX=tempBoxPosX;
boxPosY=tempBoxPosY;
boxPosW=tempBoxWidth;
boxPosH=tempBoxHeight;
}
// methods of the abstract InteractiveBoxes class
void rollOver () {
if ((mouseX>=boxPosX) && (mouseX <=boxPosX+boxPosW) && (mouseY>=boxPosY) && (mouseY<=boxPosY+boxPosH)) {
over=true;
}
else {
over=false;
}
} // end of the rollOver function
void click (int mX, int mY) {
boxPosX=mouseX;
boxPosY=mouseY;
boxPosW=mouseX-boxPosX;
boxPosH=mouseY-boxPosY;
} // end the click function
void press (int mX, int mY) {
if (over==true) {
pressed=true;
boxPosXOff=mX-boxPosX;
boxPosYOff=mY-boxPosY;
}
} // end of the press function
void drag (int mX, int mY) {
if (pressed==true) {
boxPosX=mX-boxPosXOff;
boxPosY=mY-boxPosYOff;
}
} // end of the drag function
void release () {
pressed=false;
} // end of release function
}
class TextField extends InteractiveBoxes {
PFont fontA;
String userInputText= ""; // declare and initialize the variable to store text while it is being typed
String captureText= ""; // declare and initialize the variable to save typed text when return key is hit
String[] fullComment;
int spacing;
int fontHeight;
color boxClr;
// constructor of the TextField class
TextField (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color tempBoxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
fontA = loadFont("ArialMT-48.vlw");
boxClr=tempBoxClr;
spacing = 5;
}
void appendStrings(String filename, String[] file) // This was a response from the processing forum on how to append text
{
try {
// Create file
FileWriter fstream = new FileWriter(sketchPath(filename), true); // boolean where true means append
PrintWriter out = new PrintWriter(fstream); // // Create a new file in the sketch directory
for (int i =0 ; i < file.length; ++i) { // go through String array
out.println(file[i]); // write each character in the String array in the text file
}
out.close(); //Close the output stream
}
catch (Exception e) { //Catch exception if any
println("Error: " + e.getMessage());
}
}
void display () {
// Display everything
fill (boxClr);
strokeWeight(4);
strokeJoin(ROUND);
rect (boxPosX, boxPosY, boxPosW, boxPosH);
fontHeight=16; // set the font size
textFont(fontA, fontHeight); // Set the font type and size at Arial 14 for text instructions
fill(240); // Set the fill for text instructions
text("Drag this box where you please. Type your graffiti in \na single phrase and hit return twice to add to wall:", boxPosX+spacing, boxPosY+fontHeight+spacing);
fontHeight=20; // reset the font size
fill (255); //set the fill for the user's input text
textFont(fontA, fontHeight); // Set the font type and size at Arial 20 for text instructions
text(userInputText, boxPosX+spacing, boxPosY+4*fontHeight+spacing);
text(captureText, boxPosX+spacing, boxPosY+4*fontHeight+spacing);
}
void keyPressed() {
fullComment = splitTokens(captureText, "/");
if (keyCode == BACKSPACE) {
userInputText = userInputText.substring(0, userInputText.length() - 1); // allow the backspace key to go back and erase characters
}
else
if (key != CODED) userInputText += key; // capture characters of any keys that are pressed except for the coded ones
// If the return key is pressed, save the String and clear it
if (key == RETURN || key == ENTER) {
captureText = userInputText;
appendStrings("userinput.txt", fullComment);
userInputText = ""; // Clear the String by setting it equal to ""
}
}
} // end of TextField class
class WordCollage extends InteractiveBoxes {
Graffiti[] thisGraffiti;
String [] retrieve;
PFont [] fonts;
String[] fontNames = {
"VinerHandITC-48", "SegoeScript-Bold-48", "RageItalic-48", "Mistral-48", "Vivaldii-48", "Pristina-Regular-48", "BradleyHandITC-48"
};
// constructor of the Graffiti Collage class
WordCollage (int boxPosX, int boxPosY, int boxPosW, int boxPosH) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
retrieve = loadStrings ("userinput.txt");
fonts=new PFont[fontNames.length];
for (int i = 0; i < fontNames.length; ++i) {
fonts[i] = loadFont(fontNames[i] + ".vlw");
}
thisGraffiti = new Graffiti[retrieve.length];
for (int i = 0; i < retrieve.length; ++i) {
thisGraffiti[i] = new Graffiti( retrieve[(int) random(retrieve.length)], fonts[(int) random(fonts.length)] );
}
} // end of the constructor
boolean overlapTest () {
for (int i=0; i<retrieve.length ; i++) { // create a for loop that will go through all the graffiti objects in the array
for (int j=0; j<retrieve.length ; j++) { // create another for loop that will go through all the graffiti objects in the array
if (j!=i && (thisGraffiti[i].detectOverlap(thisGraffiti[j]))) {
}
}
}
println("overlap");
return true;
}
void display () {
for (int n = 0; n < thisGraffiti.length; n ++ ) {
thisGraffiti[n].display();
}
}
}
/* Here I will need an array out of bound exception and also an exception for when the text file is empty*/
class Graffiti {
String graffitiText;
int graffitiX, graffitiY;
float opacity, randomOpacity, opacitySpeed;
int opacityDir;
color fClr;
PFont font;
Graffiti(String graffitiText, PFont font) { // constructor for the Graffiti class
this.graffitiText = graffitiText;
this.font = font;
graffitiX = int(random (screen.width));
graffitiX = constrain(graffitiX, 5, screen.width-27*graffitiText.length()); // constrain the x position so that the phrases are not cut off the screen
graffitiY = int(random (screen.height));
graffitiY = constrain(graffitiY, 50, screen.height-110); // constrain the y position so that the phrases are not cut off the screen
fClr = color(random (0, 175), random(0, 175), random(0, 175));
opacity = random(255);
randomOpacity = 1;
opacityDir= int (randomOpacity);
opacitySpeed=random(1, 3);
println("Added Graffiti: " + graffitiText + " " + graffitiX + "," + graffitiY + "," + opacity + "," + opacityDir);
} // end of the constructor for the Graffiti class
boolean detectOverlap (Graffiti checkOverlap) {
if ((graffitiX>=(checkOverlap.graffitiX+checkOverlap.graffitiText.length()*27)) || ((graffitiX+(27*graffitiText.length()))<= (checkOverlap.graffitiX)) || ((graffitiY)>=(checkOverlap.graffitiY+110)) || ((graffitiY+110) <= (checkOverlap.graffitiY)))
{ // conditional block (from the vehicle collision detection assignment) that states that if the left of a graffiti is equal or more than the right of another graffiti OR if the right of a graffiti is equal or less than the left of another graffiti OR if the top of a graffiti is equal or more than the bottom of another graffiti OR if the bottom of a graffiti is equal or less than the top of another graffiti, then...
return false; // ...return false if any of these conditions are met
} // end of the if block
else { // if none of these conditions are met...
return true; // return true
} // end of the else block
} // end of the detect Overlap function
void display() {
// Fade ins and fade outs by incrementing the opacity variable in function of the frameRate
opacity += opacityDir * opacitySpeed; // this is the speed of the fading effect
opacity = constrain(opacity, 0, 255); // constrain the range of the opacity from 0 to 255
if ( (opacity >= 255 && opacityDir == 1) || // When we hit maximum opacity...
(opacity <= 0 && opacityDir == -1)) { //... or when we are at minimum opacity...
opacityDir *= -1; //...change direction of the opacity fade
if (opacity <= 0) { // when graffiti is invisible...
graffitiX = int(random (screen.width)); //...choose new x
graffitiX = constrain(graffitiX, 5, screen.width-27*graffitiText.length()); // constrain the x position so that the phrases are not cut off the screen
graffitiY = int(random (screen.height)); //...choose new y
graffitiY = constrain(graffitiY, 50, screen.height-110); // constrain the y position so that the phrases are not cut off the screen
fClr = color(random (0, 175), random(0, 175), random(0, 175)); //...and choose new font color
} // end of the loop that deals with the graffiti once it has become invisible
} // end of the loop that deals with the fade ins and fade outs of opacity
textFont(font, 48); // display the graffiti with correct font/color
fill(fClr, opacity); // color the text randomly and fade in/out with the opacity variable
text(graffitiText, graffitiX, graffitiY); // write the graffiti in a random x and y position
} // end the display function
} // end the Graffiti class
1