I am trying to append a string to an array of Strings. in my application, graffiti messages are displayed on a wall. When a user types his graffiti line in a box, it should appear also on the wall but currently it only appears AFTER I run the program again. I have already posted on this problem and was told to add a function called addNewString() which would append the new string to the array. I have tried all kinds of magic incantations of different syntax and nothing works. Referencing books, it seems like doing this should work
...but when I do this I get an "Illegal Argument Exception: Array Element Type Mismatch" error...
Here is my code for both input and output to the text file. The problem should be constrained to the WordCollage class or at worse, the TextField class. The rest is for reference:
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;
// constructor of the TextField class
TextField (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
}
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());
}
}
String getNewString () { // create a function that will return the string
if (key == RETURN || key == ENTER) { // If the return key is pressed...
return captureText; // return the string that the user just typed in
} // end the condition for when the return or enter key would be pressed after a user typed in their text
return null; // statement that must be put at the end of a method that returns a string in case there is nothing in that string at a given moment
} // end of the getNewString function
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 ""
}
}
void display () {
// Display everything
fill (boxClr);
strokeWeight(4);
strokeJoin(ROUND);
rect (boxPosX, boxPosY, boxPosW, boxPosH);
fill(240); // Set the fill for text instructions
fontHeight=16;
textFont(fontA, fontHeight); // Set the font type and size at Arial 16 for text instructions
fill (255); //set the fill for the user's input text
text("Drag this box where you please. Type your graffiti as \na single phrase and hit return twice to add to wall:", boxPosX+marginSpacing, boxPosY+fontHeight+marginSpacing);
fontHeight=20;
textFont(fontA, fontHeight); // Set the font type and size at Arial 20 for text instructions
text(userInputText, boxPosX+marginSpacing, boxPosY+4*fontHeight+marginSpacing);
text(captureText, boxPosX+marginSpacing, boxPosY+4*fontHeight+marginSpacing);
}
} // end of TextField class
WordCollage (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
retrieve = loadStrings ("userinput.txt");
fonts=new PFont[fontNames.length];
nbrAdded=0; // declare and initialize a variable that keeps track of the number of graffiti that have been added so far
for (int i = 0; i < fontNames.length; ++i) {
fonts[i] = loadFont(fontNames[i] + ".vlw");
}
try {
thisGraffiti = new Graffiti[retrieve.length];
for (int i = 0; i < retrieve.length; ++i) {
Graffiti candidate;
do {
candidate = new Graffiti( retrieve[(int) random(retrieve.length)], fonts[(int) random(fonts.length)] ); // create each graffiti by retrieving each string in the array one by one and giving it a random font
this.addNewString(); // append the string that the user just typed in or other strings that users will later type in to the thisGraffiti array
}
while (!isDesirable (candidate)); // create a loop that keeps trying new candidates by checking if each are desirable...
thisGraffiti[i] = candidate; // ...until it gets a candidate that is desirable
nbrAdded++; // increment by one the variable that keeps track of the number of graffiti that have been added so far
println ("This is the number added:" + nbrAdded);
}
}
catch (NullPointerException e) {
println("I can't find the text file that contains your array!");
}
} // end of the constructor
for (int i=0; i<nbrAdded ; i++) { // create a for loop that will go through all the graffiti objects in the array
if ((cand.detectOverlap(thisGraffiti[i])) || (cand.equals(thisGraffiti[i])))
{
// check if candidate passes all desirability checks and return false if it's good, and true if it's bad
return false;
}
println("duplication");
}
return true;
}
void display () {
try {
for (int n = 0; n < thisGraffiti.length; n ++ ) {
thisGraffiti[n].display();
}
}
catch (NullPointerException e) {
println("I can't find your array!");
}
}
}
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 (checkOverlap == null) {
println("checkOverlap is null!");
return false;
}
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 if there is an overlap
} // 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, 150), random(0, 150), random(0, 150), random(100, 255)); //...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
I am not posting my code because I think it's not a good idea...
...however my problem is probably a common mistake and I think it's easy to understand without code.
I am using copy (not copy()) or else image to copy an area of the canvas that has been selected with x and y parameters.
I am trying to paste in on permanently so that it is not erased. So I am copying it in the draw method of a layer with a background (0,0) and as far as I can tell, I am on that layer...
When I copy it with say, pressing a key or clicking the mouse, the image will copy for a second and then disappear. Or else when I fiddle with the conditional, it will copy it until I press another key.
In other words, the copying happens when there is a mouse or key event, and then it disappears when that event is stopped or when a new mouse or key event occurs.
It's behaving the same way whether I use "copy" or "image".
So my question is, can I implement "copy" and "image" as a result of key or mouse events and then make multiple iterations that "stick" to my top layer?
Okay, here is some code. It's a freakin' mess, especially the last class called ImageCollage which is supposed to use parameters from the rectangular selection tool to copy part of a photograph that is in a movable box. Currently my main problem is that when the copySelection method of the ImageCollage class is working (and it works sometimes but not always), it copies a rectangular selection of the image but the x and y parameters are wrong. The width and height of the box seem to be the same though. It seems to be related to the values that I assign when I instantiate the object but I cannot figure out why.
I also left a bunch of code in the imageCollage class that is irrelevant right now but it is actually how I would prefer copying the selection: rather than use copy, I would like to use loadPixels() but I don't know how to make it work and it's just a bunch of code I copied from the Shiffman book which I can't get to work so I just left it there in the constructor for now...I am open to suggestions...
if (keyPressed && key == CODED && keyCode == KeyEvent.VK_CONTROL) {
selectToolStatus=true; // when CONTROL key is pressed, status of the select tools is true
}
else {
selectToolStatus=false; // when CONTROL key is not pressed, status of the select tools is false
}
if (mousePressed && keyPressed && key == CODED && keyCode == KeyEvent.VK_CONTROL) {
if (toggle == 1) {
selectEllipse.select();
}
else if (toggle==2) {
selectRectangle.select();
}
}
if (toggle == 1) {
selectEllipse.drawSelection();
}
else if (toggle==2) {
selectRectangle.drawSelection();
}
void mouseReleased () {
artWorks.release();
if (toggle==1) {
selectEllipse.release(); // calculate the ellipse shape if toggle is 1
}
else if (toggle==2) { // calculate the rectangle shape if toggle is 2
selectRectangle.release ();
}
}
abstract class InteractiveBoxes {
int boxPosX, boxPosY, boxPosW, boxPosH;
PFont fontA; // declare a variable that refers to the default font for all the subclasses
int fontHeight;
int marginSpacing;
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;
fontA = loadFont("ArialMT-48.vlw"); // Load the default font that the subclasses will be able to use
fontHeight=48; // set a default value for the font height (determined by the font size limit)
marginSpacing=5;
}
// 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
abstract void display();
}
class PictureGallery extends InteractiveBoxes {
PImage[] images=new PImage[15];
int imageIndex;
color boxClr;
// constructor of the Picture Gallery class
PictureGallery (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color tempBoxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
boxClr=tempBoxClr;
imageIndex=0;
for (int i = 0; i < images.length; i ++ ) {
images[i] = loadImage( "picture" + i + ".jpg" );
}
} // end of the constructor
// methods of the PictureGallery class
int getArtworksX () {
return (boxPosX);
}
int getArtworksY () {
return (boxPosY);
}
int getArtworksW () {
return (boxPosW);
}
int getArtworksH () {
return (boxPosH);
}
int getIconY () {
return (boxPosY+boxPosH);
}
PImage getImage () {
return images[imageIndex];
}
void flipThrough() {
if (key == CODED) {
if (keyCode == KeyEvent.VK_F1)
{
imageIndex++;
println("imageindeix is:" + imageIndex);
if (imageIndex>images.length-1)
{
imageIndex=0;
}
}
}
}
void display () {
try {
for (int i = 0; i < images.length; i ++ ) {
strokeWeight(4);
strokeJoin(ROUND);
fill (boxClr);
rect (boxPosX-2, boxPosY, boxPosW+4, boxPosH+100);
fill(240); // Set the fill for text instructions
fontHeight=16;
textFont(fontA, fontHeight); // Set the font type and size at Arial 16 for text instructions
text("Drag this box where you please. Press F1 key \nto flip through images in this picture gallery.", boxPosX+marginSpacing, ((boxPosY+boxPosH)+fontHeight+marginSpacing));
text("Click on selection tool then CTRL \nkey to select. Press ALT to paste", boxPosX+marginSpacing+97, ((boxPosY+boxPosH)+3*fontHeight+4*marginSpacing));
rect (boxPosX-2, boxPosY-2, boxPosW+4, boxPosH+4);
image (images[imageIndex], boxPosX, boxPosY, boxPosW, boxPosH);
}
}
catch (ArrayIndexOutOfBoundsException e) {
println ("Hey, that’s not a valid index!");
}
catch (NullPointerException e) {
println( "I can't find this array! ");
}
} // end of the display function
} // end of the Picture Gallery class
abstract class SelectionTool extends InteractiveBoxes {
PImage icon;
int iconXPos, iconYPos, iconW, iconH;
color boxClr;
int selectX, selectY, selectW, selectH;
boolean inside;
// constructor of the abstract SelectionTool class
SelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color tempBoxClr, int tempIconW, int tempIconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
boxClr=tempBoxClr;
iconW=tempIconW;
iconH=tempIconH;
inside=false;
iconXPos=artWorks.getArtworksX();
iconYPos=iconH+artWorks.getIconY();
} // end of the constructor
// methods of the abstract SelectionTool class
boolean insidePictureGallery () {
if (mousePressed && (mouseX>=artWorks.getArtworksX())&&(mouseX <=(artWorks.getArtworksX()+artWorks.getArtworksW()))&&(mouseY>=artWorks.getArtworksY())&& (mouseY<=(artWorks.getArtworksY()+artWorks.getArtworksH())))
{
inside=true;
}
else {
inside=false;
}
return inside;
} // end of the inside function
void click (int mX, int mY) {
if (over==true) {
}
else {
boxPosX=mouseX;
boxPosY=mouseY;
boxPosW=mouseX-boxPosX;
boxPosH=mouseY-boxPosY;
}
} // end the click function
int getSelectionX () {
return (selectX);
}
int getSelectionY () {
return (selectY);
}
int getSelectionW () {
return (selectW);
}
int getSelectionH () {
return (selectH);
}
void release () {
pressed=false;
selectX=boxPosX;
selectY=boxPosY;
selectW=mouseX-boxPosX;
selectH=mouseY-boxPosY;
} // end of release function
abstract void select ();
abstract void display ();
} // end of the SelectionTool class
class RectSelectionTool extends SelectionTool {
// constructor of the RectSelectionTool class
RectSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr, iconW, iconH);
icon=loadImage("rectangularmarquee.jpg");
} // end of the constructor
// methods of the RectSelectionTool class
void select () {
if (inside==true && mouseX<=(artWorks.getArtworksX()+artWorks.getArtworksW()) && mouseY<=(artWorks.getArtworksY()+artWorks.getArtworksH()))
{
strokeWeight(1);
stroke(boxClr);
fill (0, 0, 0, 0);
if (mousePressed) {
rect (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
stroke(0);
}
}
}
void drawSelection () {
if (inside==true && selectX+selectW<=(artWorks.getArtworksX()+artWorks.getArtworksW()) && selectY+selectH<=(artWorks.getArtworksY()+artWorks.getArtworksH()))
{
strokeWeight(1);
stroke(boxClr);
fill (0, 0, 0, 0);
rect (selectX, selectY, selectW, selectH);
stroke(0);
}
}
void display () {
iconXPos=artWorks.getArtworksX();
iconYPos=iconH+artWorks.getIconY();
image (icon, iconXPos+iconW, iconYPos);
} // end of the display function
} // end of the RectSelectionTool class
class EllipseSelectionTool extends SelectionTool {
// constructor of the EllipseSelectionTool class
EllipseSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr, iconW, iconH);
icon=loadImage ("ellipticalmarquee.jpg");
} // end of the constructor
void display () {
iconXPos=artWorks.getArtworksX();
iconYPos=iconH+artWorks.getIconY();
image (icon, iconXPos, iconYPos);
} // end of the display function
} // end of the EllipseSelectionTool class
class ImageCollage extends InteractiveBoxes {
PImage destination;
int collageX, collageY;
// constructor of the ImageCollage class
ImageCollage (int boxPosX, int boxPosY, int boxPosW, int boxPosH) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
for (int x = selectRectangle.getSelectionX(); x < selectRectangle.getSelectionX()+selectRectangle.getSelectionW(); x++ ) {
for (int y = selectRectangle.getSelectionY(); y < selectRectangle.getSelectionY()+selectRectangle.getSelectionH(); y++ ) {
int loc = x + y*artWorks.getImage().width;
float r = red(artWorks.getImage().pixels [loc]);
float g = green(artWorks.getImage().pixels[loc]);
float b = blue(artWorks.getImage().pixels[loc]);
// Set the display pixel to the image pixel
destination.pixels[loc] = color (r, g, b);
}
}
destination.updatePixels();
} // end of the constructor
I have a text file that is a string array that appends a string everytime the user types some words and hits return twice.
The strings in that array are displayed on the canvas.
However, when an user makes a new contribution it can only be displayed if I rerun the application.
What I would like is that once the user types return twice, this new string is not only appended but also displayed.
I think the problem is with loadStrings but since it is in the constructor of a class, I am assuming that it is updated everytime draw is called. Perhaps I am assuming wrong?
int boxPosX, boxPosY, boxPosW, boxPosH;
PFont fontA; // declare a variable that refers to the default font for all the subclasses
int fontHeight;
int marginSpacing;
InteractiveBoxes (int tempBoxPosX, int tempBoxPosY, int tempBoxWidth, int tempBoxHeight) {
boxPosX=tempBoxPosX;
boxPosY=tempBoxPosY;
boxPosW=tempBoxWidth;
boxPosH=tempBoxHeight;
fontA = loadFont("ArialMT-48.vlw"); // Load the default font that the subclasses will be able to use
fontHeight=48; // set a default value for the font height (determined by the font size limit)
marginSpacing=5;
}
// methods of the abstract InteractiveBoxes class
abstract void display();
}
class TextField extends InteractiveBoxes {
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;
color boxClr;
// constructor of the TextField class
TextField (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color tempBoxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
boxClr=tempBoxClr;
}
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 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 ""
}
}
void display () {
// Display everything
fill (boxClr);
strokeWeight(4);
strokeJoin(ROUND);
rect (boxPosX, boxPosY, boxPosW, boxPosH);
fill(240); // Set the fill for text instructions
fontHeight=16;
textFont(fontA, fontHeight); // Set the font type and size at Arial 16 for text instructions
fill (255); //set the fill for the user's input text
text("Drag this box where you please. Type your graffiti as \na single phrase and hit return twice to add to wall:", boxPosX+marginSpacing, boxPosY+fontHeight+marginSpacing);
fontHeight=20;
textFont(fontA, fontHeight); // Set the font type and size at Arial 20 for text instructions
text(userInputText, boxPosX+marginSpacing, boxPosY+4*fontHeight+marginSpacing);
text(captureText, boxPosX+marginSpacing, boxPosY+4*fontHeight+marginSpacing);
}
} // end of TextField class
WordCollage (int boxPosX, int boxPosY, int boxPosW, int boxPosH) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
retrieve = loadStrings ("userinput.txt");
fonts=new PFont[fontNames.length];
nbrAdded=0; // declare and initialize a variable that keeps track of the number of graffiti that have been added so far
for (int i = 0; i < fontNames.length; ++i) {
fonts[i] = loadFont(fontNames[i] + ".vlw");
}
try {
thisGraffiti = new Graffiti[retrieve.length];
for (int i = 0; i < retrieve.length; ++i) {
Graffiti candidate;
do {
candidate = new Graffiti( retrieve[(int) random(retrieve.length)], fonts[(int) random(fonts.length)] ); // create each graffiti by retrieving each string in the array one by one and giving it a random font
}
while (!isDesirable (candidate)); // create a loop that keeps trying new candidates by checking if each are desirable...
thisGraffiti[i] = candidate; // ...until it gets a candidate that is desirable
nbrAdded++; // increment by one the variable that keeps track of the number of graffiti that have been added so far
println ("This is the number added:" + nbrAdded);
}
}
catch (NullPointerException e) {
println("I can't find the text file that contains your array!");
}
} // end of the constructor
for (int i=0; i<nbrAdded ; i++) { // create a for loop that will go through all the graffiti objects in the array
if ((cand.detectOverlap(thisGraffiti[i])) || (cand.equals(thisGraffiti[i])))
{
// check if candidate passes all desirability checks and return false if it's good, and true if it's bad
return false;
}
println("duplication");
}
return true;
}
void display () {
try {
for (int n = 0; n < thisGraffiti.length; n ++ ) {
thisGraffiti[n].display();
}
}
catch (NullPointerException e) {
println("I can't find your array!");
}
}
}
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 (checkOverlap == null) {
println("checkOverlap is null!");
return false;
}
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 if there is an overlap
} // 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, 150), random(0, 150), random(0, 150), random(100, 255)); //...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
I created a box that can be dragged anywhere on the canvas when the mouse is on it and is pressed and dragged. It is an object called "artworks" which extends this movability from the functions of the abstract Interactivve Boxes class. When I press F1, I can flip through an array of images in that box, one at a time.
I also created a selection tool with rectangular and/or elliptical marquee. From draw, I activate it by pressing the CONTROL KEY and mousePressed.
My problem is that when I try to use the selection tool over the images, the drag function activates at the same time as the selection tool.
Is there a way I can tell the program to NOT drag (i.e. move) the box when the CONTROL KEY is pressed (and therefore, when I am using the selection tool)? (In other words, when I use the selection tool, the drag function cannot be used).
I would also like to copy-paste from the "artworks" with my selection tool. Is the best strategy to do this to use the loadPixels() and updatePixels()? I am aware that a circular selection will probably not work.
if (toggle==1) {
selectEllipse.release();
}
else if (toggle==2) {
selectRectangle.release ();
}
}
void keyPressed () {
artWorks.flipThrough();
}
abstract class InteractiveBoxes {
int boxPosX, boxPosY, boxPosW, boxPosH;
color boxClr;
PFont fontA; // declare a variable that refers to the default font for all the subclasses
int fontHeight;
int marginSpacing;
int boxPosXOff, boxPosYOff;
boolean over = false;
boolean pressed = false;
InteractiveBoxes (int tempBoxPosX, int tempBoxPosY, int tempBoxWidth, int tempBoxHeight, color tempboxClr) {
boxPosX=tempBoxPosX;
boxPosY=tempBoxPosY;
boxPosW=tempBoxWidth;
boxPosH=tempBoxHeight;
boxClr=tempboxClr;
fontA = loadFont("ArialMT-48.vlw"); // Load the default font that the subclasses will be able to use
fontHeight=48; // set a default value for the font height (determined by the font size limit)
marginSpacing=5;
}
// 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
abstract void display();
}
class PictureGallery extends InteractiveBoxes {
PImage[] images=new PImage[10];
int imageIndex;
// constructor of the Picture Gallery class
PictureGallery (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
imageIndex=0;
for (int i = 0; i < images.length; i ++ ) {
images[i] = loadImage( "picture" + i + ".jpg" );
}
} // end of the constructor
// methods of the PictureGallery class
int getIconX () {
return boxPosX;
}
int getIconY () {
return (boxPosY+boxPosH);
}
PImage getImage () {
return images[imageIndex];
}
void flipThrough() {
if (key == CODED) {
if (keyCode == KeyEvent.VK_F1)
{
imageIndex++;
if (imageIndex>images.length-1)
{
imageIndex=0;
}
}
}
}
void display () {
try {
for (int i = 0; i < images.length; i ++ ) {
strokeWeight(4);
strokeJoin(ROUND);
fill (boxClr);
rect (boxPosX-2, boxPosY, boxPosW+4, boxPosH+100);
fill(240); // Set the fill for text instructions
fontHeight=16;
textFont(fontA, fontHeight); // Set the font type and size at Arial 16 for text instructions
text("Drag this box where you please. Press F1 key \nto flip through images in this picture gallery.", boxPosX+marginSpacing, ((boxPosY+boxPosH)+fontHeight+marginSpacing));
text("Click on selection tool and CTRL \nkey to select. Press P to paste.", boxPosX+marginSpacing+100, ((boxPosY+boxPosH)+3*fontHeight+4*marginSpacing));
rect (boxPosX-2, boxPosY-2, boxPosW+4, boxPosH+4);
image (images[imageIndex], boxPosX, boxPosY, boxPosW, boxPosH);
}
}
catch (ArrayIndexOutOfBoundsException e) {
println ("Hey, that’s not a valid index!");
}
catch (NullPointerException e) {
println( "I can't find this array! ");
}
} // end of the display function
} // end of the Picture Gallery class
abstract class SelectionTool extends InteractiveBoxes {
PImage icon;
int iconXPos, iconYPos, iconW, iconH;
int SelectX, SelectY, SelectW, SelectH;
// constructor of the abstract SelectionTool class
SelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int tempIconW, int tempIconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
iconW=tempIconW;
iconH=tempIconH;
iconXPos=artWorks.getIconX();
iconYPos=iconH+artWorks.getIconY();
} // end of the constructor
// methods of the abstract SelectionTool class
boolean rollOver (boolean over) {
if (mousePressed && (mouseX>=iconXPos) && (mouseX <=iconXPos+iconW) && (mouseY>=iconYPos) && (mouseY<=iconYPos+iconH))
{
over=true;
}
else {
over=false;
}
return over;
} // end of the rollOver function
void click (int mX, int mY) {
if (over==true) {
}
else {
boxPosX=mouseX;
boxPosY=mouseY;
boxPosW=mouseX-boxPosX;
boxPosH=mouseY-boxPosY;
}
} // end the click function
void release () {
pressed=false;
SelectX=boxPosX;
SelectY=boxPosY;
SelectW=mouseX-boxPosX;
SelectH=mouseY-boxPosY;
} // end of release function
abstract void select ();
abstract void display ();
} // end of the SelectionTool class
class RectSelectionTool extends SelectionTool {
// constructor of the RectSelectionTool class
RectSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr, iconW, iconH);
icon=loadImage("rectangularmarquee.jpg");
} // end of the constructor
// methods of the RectSelectionTool class
void select () {
strokeWeight(1);
stroke(boxClr);
fill (0, 0, 0, 0);
if (mousePressed) {
rect (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
}
else {
rect (SelectX, SelectY, SelectW, SelectH);
}
stroke(0);
}
void release () {
pressed=false;
SelectX=boxPosX;
SelectY=boxPosY;
SelectW=mouseX-boxPosX;
SelectH=mouseY-boxPosY;
fill(0, 0, 0, 0);
stroke(boxClr);
rect (SelectX, SelectY, SelectW, SelectH);
stroke(0);
} // end of release function
void display () {
iconXPos=artWorks.getIconX();
iconYPos=iconH+artWorks.getIconY();
image (icon, iconXPos+iconW, iconYPos);
} // end of the display function
} // end of the RectSelectionTool class
class EllipseSelectionTool extends SelectionTool {
// constructor of the EllipseSelectionTool class
EllipseSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr, iconW, iconH);
icon=loadImage ("ellipticalmarquee.jpg");
} // end of the constructor
void release () {
pressed=false;
SelectX=boxPosX;
SelectY=boxPosY;
SelectW=mouseX-boxPosX;
SelectH=mouseY-boxPosY;
fill(0, 0, 0, 0);
stroke(boxClr);
ellipseMode(CORNER);
ellipse (SelectX, SelectY, SelectW, SelectH);
stroke(0);
} // end of release function
void display () {
iconXPos=artWorks.getIconX();
iconYPos=iconH+artWorks.getIconY();
image (icon, iconXPos, iconYPos);
} // end of the display function
} // end of the EllipseSelectionTool class
Currently, I have an applet where users can type something which is saved to a "userinput" text file when they press return twice after typing. Meanwhile, another class comes into this text file which stores the different user inputs as an array of strings, retrieves them randomly and displays them onto the canvas one after another with fades.
However, whatever someone types when the program is executing will not appear on the canvas until I rerun the canvas.
Is it possible to do this? Here is my code below (only the textual sections which are relevant):
int boxPosX, boxPosY, boxPosW, boxPosH;
color boxClr;
PFont fontA; // declare a variable that refers to the default font for all the subclasses
int fontHeight;
int marginSpacing;
int boxPosXOff, boxPosYOff;
boolean over = false;
boolean pressed = false;
InteractiveBoxes (int tempBoxPosX, int tempBoxPosY, int tempBoxWidth, int tempBoxHeight, color tempboxClr) {
boxPosX=tempBoxPosX;
boxPosY=tempBoxPosY;
boxPosW=tempBoxWidth;
boxPosH=tempBoxHeight;
boxClr=tempboxClr;
fontA = loadFont("ArialMT-48.vlw"); // Load the default font that the subclasses will be able to use
fontHeight=48; // set a default value for the font height (determined by the font size limit)
marginSpacing=5;
}
// 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
abstract void display();
}
class TextField extends InteractiveBoxes { //
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;
// constructor of the TextField class
TextField (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
}
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 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 ""
}
}
void display () {
// Display everything
fill (boxClr);
strokeWeight(4);
strokeJoin(ROUND);
rect (boxPosX, boxPosY, boxPosW, boxPosH);
fill(240); // Set the fill for text instructions
fontHeight=16;
textFont(fontA, fontHeight); // Set the font type and size at Arial 16 for text instructions
fill (255); //set the fill for the user's input text
text("Drag this box where you please. Type your graffiti as \na single phrase and hit return twice to add to wall:", boxPosX+marginSpacing, boxPosY+fontHeight+marginSpacing);
fontHeight=20;
textFont(fontA, fontHeight); // Set the font type and size at Arial 20 for text instructions
text(userInputText, boxPosX+marginSpacing, boxPosY+4*fontHeight+marginSpacing);
text(captureText, boxPosX+marginSpacing, boxPosY+4*fontHeight+marginSpacing);
}
} // end of TextField class
WordCollage (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
retrieve = loadStrings ("userinput.txt");
fonts=new PFont[fontNames.length];
nbrAdded=0; // declare and initialize a variable that keeps track of the number of graffiti that have been added so far
for (int i = 0; i < fontNames.length; ++i) {
fonts[i] = loadFont(fontNames[i] + ".vlw");
}
try {
thisGraffiti = new Graffiti[retrieve.length];
for (int i = 0; i < retrieve.length; ++i) {
Graffiti candidate;
do {
candidate = new Graffiti( retrieve[(int) random(retrieve.length)], fonts[(int) random(fonts.length)] ); // create each graffiti by retrieving each string in the array one by one and giving it a random font
}
while (!isDesirable (candidate)); // create a loop that keeps trying new candidates by checking if each are desirable...
thisGraffiti[i] = candidate; // ...until it gets a candidate that is desirable
nbrAdded++; // increment by one the variable that keeps track of the number of graffiti that have been added so far
println ("This is the number added:" + nbrAdded);
}
}
catch (NullPointerException e) {
println("I can't find the text file that contains your array!");
}
} // end of the constructor
boolean isDesirable (Graffiti cand)
{
for (int i=0; i<nbrAdded ; i++) { // create a for loop that will go through all the graffiti objects in the array
if ((cand.detectOverlap(thisGraffiti[i])) || (cand.equals(thisGraffiti[i])))
{
// check if candidate passes all desirability checks and return false if it's good, and true if it's bad
return false;
}
println("duplication");
}
return true;
}
void display () {
try {
for (int n = 0; n < thisGraffiti.length; n ++ ) {
thisGraffiti[n].display();
}
}
catch (NullPointerException e) {
println("I can't find your array!");
}
}
}
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 (checkOverlap == null) {
println("checkOverlap is null!");
return false;
}
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 if there is an overlap
} // 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, 150), random(0, 150), random(0, 150), random(100, 255)); //...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
After a week of wrestling, I am still trying to toggle a selection tool from rectangular marquee to elliptical marquee by clicking on their respective small icon BEFORE I begin my selection. Both these selection tools are classes inherited from an abstract class, itself inherited from an abstract class.
On the advice of a forum respondent, I am trying to use a toggle in the form of a variable called shapeSel whereby it is worth 1 for the ellipticalTool and 2 for the rectangular one. I assume that the problem is in my syntax but also how I lay it out in the main part of my program. I left the PictureGallery class in the following code but it is not directly related to the problem.
if (key == CODED) {
if (keyCode == KeyEvent.VK_CONTROL && mousePressed)
{
selectRectangle.select();
selectRectangle.release ();
}
}
if (key == CODED) {
if (keyCode == KeyEvent.VK_CONTROL && mousePressed)
{
selectEllipse.select();
selectEllipse.release();
}
}
}
abstract class InteractiveBoxes {
int boxPosX, boxPosY, boxPosW, boxPosH;
color boxClr;
PFont fontA; // declare a variable that refers to the default font for all the subclasses
int fontHeight;
int marginSpacing;
int boxPosXOff, boxPosYOff;
boolean over = false;
boolean pressed = false;
InteractiveBoxes (int tempBoxPosX, int tempBoxPosY, int tempBoxWidth, int tempBoxHeight, color tempboxClr) {
boxPosX=tempBoxPosX;
boxPosY=tempBoxPosY;
boxPosW=tempBoxWidth;
boxPosH=tempBoxHeight;
boxClr=tempboxClr;
fontA = loadFont("ArialMT-48.vlw"); // Load the default font that the subclasses will be able to use
fontHeight=48; // set a default value for the font height (determined by the font size limit)
marginSpacing=5;
}
// 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
abstract void display();
}
class PictureGallery extends InteractiveBoxes {
// ArrayList pictures;
PImage[] images=new PImage[10];
int imageIndex;
// constructor of the Picture Gallery class
PictureGallery (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
imageIndex=0;
for (int i = 0; i < images.length; i ++ ) {
images[i] = loadImage( "picture" + i + ".jpg" );
}
} // end of the constructor
// methods of the PictureGallery class
int getIconX () {
return boxPosX;
}
int getIconY () {
return (boxPosY+boxPosH);
}
PImage getImage () {
return images[imageIndex];
}
void flipThrough() {
if (key == CODED) {
if (keyCode == KeyEvent.VK_F1)
{
imageIndex++;
if (imageIndex>images.length-1) {
imageIndex=0;
}
}
}
}
}
abstract class SelectionTool extends InteractiveBoxes {
PImage icon;
int iconXPos, iconYPos, iconW, iconH;
int SelectX, SelectY, SelectW, SelectH;
int shapeSel;
// constructor of the abstract SelectionTool class
SelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int tempIconW, int tempIconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr);
iconW=tempIconW;
iconH=tempIconH;
shapeSel=0;
} // end of the constructor
// methods of the abstract SelectionTool class
boolean rollOver (boolean over) {
if (mousePressed && (mouseX>=iconXPos) && (mouseX <=iconXPos+iconW) && (mouseY>=iconYPos) && (mouseY<=iconYPos+iconH))
{
over=true;
}
else {
over=false;
}
return over;
} // end of the rollOver function
void click (int mX, int mY) {
if (over==true) {
}
else {
boxPosX=mouseX;
boxPosY=mouseY;
boxPosW=mouseX-boxPosX;
boxPosH=mouseY-boxPosY;
}
} // end the click function
void release () {
pressed=false;
SelectX=boxPosX;
SelectY=boxPosY;
SelectW=mouseX-boxPosX;
SelectH=mouseY-boxPosY;
} // end of release function
abstract void select ();
abstract void display ();
} // end of the SelectionTool class
class RectSelectionTool extends SelectionTool {
// constructor of the RectSelectionTool class
RectSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr, iconW, iconH);
icon=loadImage("rectangularmarquee.jpg");
} // end of the constructor
// methods of the RectSelectionTool class
void select () {
strokeWeight(1);
stroke(boxClr);
fill (0, 0, 0, 0);
rect (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
stroke(0);
}
int setToggle (int shapeSel) {
shapeSel=2;
return shapeSel;
}
void display () {
iconXPos=artWorks.getIconX();
iconYPos=iconH+artWorks.getIconY();
image (icon, iconXPos+iconW, iconYPos);
} // end of the display function
} // end of the RectSelectionTool class
class EllipseSelectionTool extends SelectionTool {
// constructor of the EllipseSelectionTool class
EllipseSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, color boxClr, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, boxClr, iconW, iconH);
icon=loadImage ("ellipticalmarquee.jpg");
} // end of the constructor
void display () {
iconXPos=artWorks.getIconX();
iconYPos=iconH+artWorks.getIconY();
image (icon, iconXPos, iconYPos);
} // end of the display function
} // end of the EllipseSelectionTool class
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).
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);
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
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
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
I am trying to fade in and fade out each String of an array on its own. I have a simple way to do the fade outs but I need a simple way to switch to fade in mode when the opacity reaches 0. There must be a simple way to do this with conditionals but I am a bit lost right now. I can't see the forest for the trees... I am using two variables to control this: fOpacity and transparency
for (int n = 0; n < numberOfGraffiti; n ++ ) {
if (transparency > 0) {
transparency += 0.25;
}
else if (transparency == 0) {
transparency = 255;
}
textFont(fontA, 48); // Set the font type and size at 48 and random types
fill(fClr[n], fOpacity[n]-transparency);
for (int i = 0; i < retrieve.length; i ++ ) {
text (retrieve[n], wordsPosX[n], wordsPosY[n]);
}
}
I am trying to load an array of fonts so that I can work with them with the variable PFont font[j].
I am sure if the syntax is different with PFont arrays (or if we can do such a thing).
This is the syntax I am using (I'll be adding more fonts when I get it right). FYI, currently, I am getting a "maybe a missing semicolon?" error but if I take out the curly braces, I get a the method loadFont(String) is not applicatble for the arguments (String, String, String) error
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
}
abstract class SelectionTool extends InteractiveBoxes {
PImage icon;
int iconXPos, iconYPos, iconW, iconH;
int SelectX, SelectY, SelectW, SelectH;
boolean activate = false;
// constructor of the abstract SelectionTool class
SelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, int tempIconXPos, int tempIconYPos, int tempIconW, int tempIconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
iconXPos=tempIconXPos;
iconYPos=tempIconYPos;
iconW=tempIconW;
iconH=tempIconH;
} // end of the constructor
// methods of the abstract SelectionTool class
void rollOver (boolean over) {
if (mousePressed && (mouseX>=iconXPos) && (mouseX <=iconXPos+iconW) && (mouseY>=iconYPos) && (mouseY<=iconYPos+iconH))
{
over=true;
}
else {
over=false;
}
} // end of the rollOver function
void release () {
pressed=false;
SelectX=boxPosX;
SelectY=boxPosY;
SelectW=mouseX-boxPosX;
SelectH=mouseY-boxPosY;
} // end of release function
abstract void select ();
void display () {
image (icon, iconXPos, iconYPos);
} // end of the display function
} // end of the SelectionTool class
class RectSelectionTool extends SelectionTool {
// constructor of the RectSelectionTool class
RectSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, int iconXPos, int iconYPos, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, iconXPos, iconYPos, iconW, iconH);
icon=loadImage("rectangularmarquee.jpg");
} // end of the constructor
// methods of the RectSelectionTool class
void select () {
strokeWeight(1);
stroke(0, 0, 255);
fill (0, 0, 0, 0);
ellipseMode(CORNER);
if (mousePressed)
{
rect (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
}
else {
rect (SelectX, SelectY, SelectW, SelectH);
}
stroke(0);
}
} // end of the RectSelectionTool class
class EllipseSelectionTool extends SelectionTool {
// constructor of the EllipseSelectionTool class
EllipseSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, int iconXPos, int iconYPos, int iconW, int iconH) {
super (boxPosX, boxPosY, boxPosW, boxPosH, iconXPos, iconYPos, iconW, iconH);
icon=loadImage ("ellipticalmarquee.jpg");
} // end of the constructor
// methods of the EllipseSelectionTool class
void select () {
strokeWeight(1);
stroke(0, 0, 255);
fill (0, 0, 0, 0);
if (mousePressed) {
ellipseMode(CORNER);
ellipse (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
}
else {
ellipseMode(CORNER);
ellipse (SelectX, SelectY, SelectW, SelectH);
}
stroke(0);
}
} // end of the EllipseSelectionTool class
I am trying to toggle a selection tool from rectangular marquee to elliptical marquee by clicking on their respective small icon BEFORE I begin my selection. Both these selection tools are classes inherited from an abstract class, itself inherited from an abstract class.
My strategy has been to try to use an "activateSelectionTool" function in the middle class called SelectionTool but I cannot seem to make the toggle this way.
What would be an intelligence way of approaching this problem?
void release () {
pressed=false;
SelectX=boxPosX;
SelectY=boxPosY;
SelectW=mouseX-boxPosX;
SelectH=mouseY-boxPosY;
} // end of release function
abstract void select ();
void display () {
image (icon, iconXPos, iconYPos);
} // end of the display function
} // end of the SelectionTool class
class RectSelectionTool extends SelectionTool {
// constructor of the RectSelectionTool class
RectSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, int iconXPos, int iconYPos) {
super (boxPosX, boxPosY, boxPosW, boxPosH, iconXPos, iconYPos);
icon=loadImage("rectangularmarquee.jpg");
} // end of the constructor
// methods of the RectSelectionTool class
void select () {
strokeWeight(1);
stroke(0, 0, 255);
fill (0, 0, 0, 0);
ellipseMode(CORNER);
if (activate==true && mousePressed)
{
rect (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
}
else {
rect (SelectX, SelectY, SelectW, SelectH);
}
stroke(0);
}
} // end of the RectSelectionTool class
class EllipseSelectionTool extends SelectionTool {
// constructor of the EllipseSelectionTool class
EllipseSelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, int iconXPos, int iconYPos) {
super (boxPosX, boxPosY, boxPosW, boxPosH, iconXPos, iconYPos);
icon=loadImage ("ellipticalmarquee.jpg");
} // end of the constructor
// methods of the EllipseSelectionTool class
void select () {
strokeWeight(1);
stroke(0, 0, 255);
fill (0, 0, 0, 0);
if (activate==true && mousePressed) {
ellipseMode(CORNER);
ellipse (boxPosX, boxPosY, mouseX-boxPosX, mouseY-boxPosY);
}
else {
ellipseMode(CORNER);
ellipse (SelectX, SelectY, SelectW, SelectH);
}
stroke(0);
}
} // end of the EllipseSelectionTool class
I am making an app in which I have a selectionTool class from which I can make different shape selectionTool objects which each are related to a small photoshop-like icon displayed on the screen that represents this object's shape.
Currently, in my constructor, I have a String variable which I want to use to either have a rectangular selection tool (in which case the object would be instantiated with "rect") or else an elliptical selection tool (in which case the object would be instantiated with "ellipse").
The variable is called shapeMarquee but it does not work. However, if I substitute that variable (it's in two places right below each other) for either rect or ellipse, I get the selection tool to work fine.
It's probably a syntax problem but I can't see how to make it work. Here is my code:
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 SelectionTool extends InteractiveBoxes {
String shapeMarquee;
PImage icon;
int iconXPos, iconYPos;
int SelectX, SelectY, SelectW, SelectH;
// constructor of the SelectionTool class
SelectionTool (int boxPosX, int boxPosY, int boxPosW, int boxPosH, String selectShapeMarquee, PImage iconS, int tempIconXPos, int tempIconYPos) {
super (boxPosX, boxPosY, boxPosW, boxPosH);
Can someone recommend a good library that is up to date that would allow the user of my program to type words or phrases in a box which can then be both stored, as well as pasted freely (like poetry) on the main canvas?
The idea is to make a "cadavre exquis" with multiple users (community built poetry). I will design the interface but was wondering if there is a user friendly element for capturing each users poetry. Otherwise, a simple reference to a book or program would be helpful.
I am trying to create a rectangular selection tool that draws the upper left corner of the rectangle when the mouse is first clicked and then the bottom right corner of the rectangle when the mouse is next released. I've got this so far but the top left corner is always reading as (0, 0) for some reason.
This animation contains a glitch which is like an itch that I can't scratch (or find).
When the fish changes position, there is a brief flash of its ghost that appears at 180 degrees.
I can't find why. Slowing down the framerate does not help.
/* Undersea race*/
// declare the object variables for this program
Raceline drawStartLine; // Declare a reference variable for the start line object inherited from the Raceline class
Raceline drawFinishLine; // Declare a reference variable for the finish line object inherited from the Raceline class
Starfish steadyStarfish; // Declare a reference variable for the steady starfish object inherited from the Starfish class
Turtle slowTurtle; // Declare a reference variable for the slow turtle object inherited from the Turtle class
Fish indecisiveFish; // Declare reference variable for the indecisive fish object inherited from the Fish class
FishReverse indecisiveFishReverse; // Declare reference variable for the reverse indecisive fish object inherited from the FishReverse class
// declare the object variables related to the text in this program (to write "Start Line" and "Finish Line")
PFont startFinishLine; // Declare a variable that is of the Font class type
String startLine; // Declare a variable that is of the String class type to store a sequence of characters that will textually describe the "Start Line"
String finishLine; // Declare a variable that is of the String class type to store a sequence of characters that will textually describe the "Finish Line"
float fishAngle; // declare the variable that will control the position of the cos and sin wave for the fish
// define the initial environment properties for this program in the setup function that will be called only once
void setup () { // define initial environment properties such as screen size and background color by calling the setup method
size (screen.width*3/4, screen.height*5/6); // set the canvas size so that it fills up a large part of the screen
background (0, 170, 250); // set the color of the background to a watery shade of blue
// initialize the font object variables for the text in this program (to write "Start Line" and "Finish Line")
startFinishLine =loadFont ("CourierNewPS-BoldItalicMT-16.vlw"); // construct a new font for the text in this program by loading this font used in a data file attached to this file
textFont (startFinishLine); // make the loaded font active in the startFinishLine variable that is of the Font class type
startLine = "Start Line"; // initialize the startLine string type variable with a sequence of characters that spells "Start Line"
finishLine = "Finish Line"; // initialize the finishLine string type variable with a sequence of characters that spells "Finish Line"
fishAngle=245.0; // initialize the angle of the fish so that it emerges from the top left of the canvas
// declare and initialize the race lines and the three different elements of this animation as objects
drawStartLine=new Raceline (color (162, 20, 148), color (162, 20, 148), 2, 40); // declare and initialize the startline object and pass in the parameters that define it
drawFinishLine=new Raceline (color (162, 20, 148), color (162, 20, 148), 2, width-40); // declare and initialize the finishline object and pass in the parameters that define it
steadyStarfish=new Starfish (color (216, 20, 125), 0, 0); // declare and initialize the steadyStarfish object and pass in the parameters that define it
slowTurtle=new Turtle (color (114, 188, 19), 0, 0); // declare and initialize the slowTurtle object and pass in the parameters that define it
indecisiveFish=new Fish (color (255, 40, 10), 0, 0); // declare and initialize the indecisiveFish object and pass in the parameters that define it
indecisiveFishReverse=new FishReverse (color (255, 40, 10), 0, 0); // declare and initialize the reverse indecisiveFish object and pass in the parameters that define it
} // end the setup method
void draw() { // start the draw method
background (0, 170, 250); // set the color of the background to a watery shade of blue
// write the phrases "start line" and "finish line" on the canvas
fill (111, 4, 100); // determine the color of the text as purple
text (startLine, 56, 26); // display the "Start Line" on the top left of the canvas
text (finishLine, width-170, height-20); // display the "Finish Line" on the bottom right of the canvas
drawStartLine.display(); // call the method to display to the screen the startline object inherited from the Raceline class
drawFinishLine.display(); // call the method to display to the screen the finishline object inherited from the Raceline class
// execute the race by displaying and moving each element across the screen
steadyStarfish.move(); // call the method to move the steadyStarfish to the screen
steadyStarfish.display(); // call the method to display the steadyStarfish to the screen
slowTurtle.move(); // call the method to move the slowTurtle to the screen
slowTurtle.display(); // call the method to display the slowTurtle to the screen
float angleCondition=fishAngle/180; // declare and create a variable that calculates the division of the angle of the cos and sin movement by 180 to determine the condition when the fish changes direction
int angleConditionConvertedtoInteger = int (angleCondition); // convert this variable from a float type to an integer type
if (angleConditionConvertedtoInteger%2==0) { // create a condition that uses the remainder of the division of this variable to determine the direction of the fish so that if the remainder is an even number, the fish swims back
indecisiveFishReverse.move (); // move the reverse indecisive fish so that it swims back towards the start line
indecisiveFishReverse.display (); // draw the reverse indecisive fish so that it swims back towards the start line
}
else { // create a condition that uses the remainder of the division of this variable to determine the direction of the fish so that if the remainder is an odd number, the fish swims forward
indecisiveFish.move(); // move the indecisive fish in its forward direction so that it swims towards the finish line
indecisiveFish.display(); // draw the indecisive fish in its forward direction so that it swims towards the finish line
}
} // end the draw method
// Race line class
class Raceline {
color clrLine;
color strokeClr;
int dotSize;
int raceLineX;
Raceline (color clrLinetemp, color strokeClrtemp, int dotSizetemp, int raceLineXtemp) {
clrLine=clrLinetemp;
strokeClr=strokeClrtemp;
dotSize=dotSizetemp;
raceLineX=raceLineXtemp;
}
void display() {
for (int i=0; i<height; i+=8) { // loop that will use a counter that will draw a shape every 8 pixels for the whole height of the canvas
stroke (strokeClr); // determine the color of the stroke of the ellipses that form the dotted line as purple
fill (clrLine); // fill with purple the ellipses that form the dotted lines
ellipse (raceLineX, i, dotSize, dotSize); // draw little ellipses every 8 pixels from top to bottom on the left of the canvas to make up the dotted line
} // end the for loop
} // end display
}// end class
// StarFish class
class Starfish { // create a class called Starfish
// all of the fields for the class called Starfish
float starFishX;
float starFishY;
color clrStarFish; // declare the variable that controls the color parameter of the pentagon class
float starFishAngle; // declare the variable that will control the position of the cos and sin wave for the starfish
float starFishAngleSpeed; // declare the variable that will allow for the incrementation of the angle for the starfish undulatory movements
float starFishCenterX; // declare the variable that will determine the X position from which the cos motion occurs for the starfish
float starFishCenterY; // declare the variable that will determine the Y position from which the sin motion occurs for the starfish
float sizeArcStarFishMoveX; // declare the variable that will determine the radius of the cos motion for the starfish so the breadth of the circular movement
float sizeArcStarFishMoveY; // declare the variable that will determine the radius of the sin motion for the starfish so the breadth of the circular movement
float starFishLocX; // declare the variable that determines the X location of the starfish in the animation
float starFishLocY; // declare the variable that determines the Y location of the starfish in the animation
float speedXstarFish; // declare the variable that determines the speed applied to the location of the starfish in the animation (in this case only the X location)
// constructor for the class called Starfish
Starfish (color clrStarFishtemp, float starFishXtemp, float starFishYtemp) { // create the constructor for the Starfish class and declare its temporary variables
starFishX=starFishXtemp;
starFishY=starFishYtemp;
starFishAngle=255.0; // initialize the angle of the starFish so that it emerges from the upper left of the canvas
clrStarFish=clrStarFishtemp; // initialize the variable that controls the color parameter of the starfish class
starFishCenterX=0.0; // assign a value of 0 to the variable that will determine the X position from which the cos motion occurs for the starfish
starFishCenterY=height/3; // assign a value of a third of the height of the canvas to the variable that will determine the Y position from which the sin motion occurs for the starfish
sizeArcStarFishMoveX=width/6; // assign a value to the variable that will determine the radius of the cos motion for the starfish so the breadth of the circular movement
sizeArcStarFishMoveY=height/4; // assign a value to the variable that will determine the radius of the sin motion for the starfish so the breadth of the circular movement
} // end the block of code of the constructor for the class called Starfish
// method to move the Starfish
void move () {
starFishX=starFishLocX+speedXstarFish;
starFishY=starFishLocY;
starFishAngleSpeed=(random(-0.4, 0.1)); // assign a random value between -0.4 and 0.1 to the change of angle used in the undulatory movement of the starfish to make it a bit jittery
starFishLocX=starFishCenterX+sizeArcStarFishMoveX*cos(radians(starFishAngle)); // assign a cos wave movement to the variable that determines the X location of the starfish in the animation
starFishLocY=starFishCenterY+sizeArcStarFishMoveY*sin(radians(starFishAngle)); // assign a sin wave movement to the variable that determines the Y location of the starfish in the animation
starFishAngle+=starFishAngleSpeed; // increment the angle of the starfish cos and sin wave movements the random speed assigned to the starfish speed variable
speedXstarFish+=0.5+(random(-0.8, 0.8)); // assign a value that is a random value added to a constant to move the starfish horizontally across the screen
}
// method to display the Starfish
void display () { /// create a variable that will refer to the function used to display the starfish
strokeJoin(ROUND);
strokeWeight (4);
stroke(1);
fill(clrStarFish);
beginShape();
vertex(starFishX, starFishY+24);
vertex(starFishX+20, starFishY+32);
vertex(starFishX+27, starFishY);
vertex(starFishX+34, starFishY+32);
vertex(starFishX+54, starFishY+24);
vertex(starFishX+42, starFishY+54);
vertex(starFishX+50, starFishY+96);
vertex(starFishX+27, starFishY+72);
vertex(starFishX+4, starFishY+96);
vertex(starFishX+12, starFishY+54);
endShape(CLOSE); // end the recording of the vertices for the Starfish class and closes the shape
} // end the block of code of the display method for the class called Starfish
} // end the block for the class called Starfish
// Turtle class
class Turtle { // create a class called Turtle
// all of the fields for the class called Turtle
float turtleX;
float turtleY;
color clrTurtle;
float angle; // declare the variable that will control the position of the sin wave for the turtle
float turtleMiddleYPos; // declare the variable that will determine the Y position from which the sin motion occurs for the turtle
float turtleYRangeOfMotion; // declare the variable that will determine the radius of the sin motion for the turtle
float speedOfSinWaveMovement; // declare the variable that will impart a change in the angle that controls the sin wave for the turtle
float turtleLocX; // declare the variable that determines the X location of the turtle in the animation
float turtleLocY; // declare the variable that determines the Y location of the turtle in the animation
float speedXTurtle; // declare the variable that determines the speed of the turtle's horizontal movement
// constructor for the class called Turtle
Turtle (color clrTurtletemp, float turtleXtemp, float turtleYtemp) { // create the constructor for the Turtle class and declare its temporary variables
turtleX=turtleXtemp;
turtleY=turtleYtemp;
clrTurtle=clrTurtletemp; // initialize the variable that controls the color parameter of the turtle class
turtleLocX=0.0-140; // initialize the content of global variable for the X location of the turtle
angle=0.0; // initialize the value of the angle of the sin wave that has a zero value
turtleMiddleYPos=height/2-58; // initialize that determines the Y position from which the sin motion occurs so that it is in the center taking into account the height of the turtle divided by 2 (116%2=58)
turtleYRangeOfMotion=height/2.6; // initialize a value for the range of Y movement of the turtle on the sin wave that makes it cover most of the height but stays inside the window
speedOfSinWaveMovement=0.005; // initialize a value for the speed of the change of angle of the sin wave that is relatively slow
} // end the block of code of the constructor for the class called Turtle
// method to move the Turtle
void move () {
turtleX=turtleLocX+speedXTurtle;
turtleY=turtleLocY;
turtleLocY=turtleMiddleYPos+sin(angle)*turtleYRangeOfMotion; // calculates the Y location of the turtle on the sin wave movement
angle+=speedOfSinWaveMovement; // increment the angle of the sin wave by the speed factor every time the draw () method is called
speedXTurtle+=0.5; //increment the speed of the turtle's horizontal movement
}
// method to display the Turtle
void display () { /// create a variable that will refer to the function used to display the starfish
// assign parameters for the color and stroke of the solid turtle figure
fill(clrTurtle);
; // set color of solid figure to a turtle-like green
stroke(0); // set color of stroke to black for the solid figure outlines
smooth(); // set anti-aliased edges for the solid turtle figure
strokeWeight (3); // set the thickness of the stroke that delineated the solid turtle figure
// draw the top flapper underneath the body and head
beginShape();
curveVertex (turtleX+122, turtleY+25);
curveVertex (turtleX+122, turtleY+25);
curveVertex (turtleX+128, turtleY+21);
curveVertex (turtleX+138, turtleY-8);
curveVertex (turtleX+115, turtleY-30);
curveVertex (turtleX+125, turtleY-15);
curveVertex (turtleX+113, turtleY+7);
curveVertex (turtleX+113, turtleY+7);
endShape(CLOSE); // end the recording of the vertices for the top flapper of the Turtle class and closes the shape
// draw the bottom flapper underneath the body and head
beginShape();
curveVertex (turtleX+131, turtleY+23);
curveVertex (turtleX+131, turtleY+23);
curveVertex (turtleX+136, turtleY+27);
curveVertex (turtleX+138, turtleY+42);
curveVertex (turtleX+130, turtleY+60);
curveVertex (turtleX+118, turtleY+85);
curveVertex (turtleX+119, turtleY+86);
curveVertex (turtleX+115, turtleY+78);
curveVertex (turtleX+124, turtleY+25);
curveVertex (turtleX+124, turtleY+25);
endShape(CLOSE); // end the recording of the vertices for the bottom flapper of the Turtle class and closes the shape
// draw the body of the turtle with 11 curveVertices points
curveVertex (turtleX+12, turtleY+25);
curveVertex (turtleX+12, turtleY+25);
endShape(CLOSE); // end the recording of the vertices for the body of the Turtle class and closes the shape
// draw the eye and the smile of the turtle
fill(232, 221, 7); // make eye color brown
ellipse (turtleX+158, turtleY+14, 2, 2); // draw small eye
noStroke(); // eliminate stroke for the mouth
fill(93, 9, 0); // make mouth pinky red
arc(turtleX+156, turtleY+24, 6, 6, QUARTER_PI, PI+QUARTER_PI); //draw arc of mouth
} // end the block of code of the display method for the class called Turtle
} // end the block for the class called Turtle
// Fish class
class Fish { // create a class called Fish
// all of the fields for the class called Turtle
float fishX;
float fishY;
color clrFish;
float fishAngleSpeed; // declare the variable that will allow for the incrementation of the angle for the fish circular movements
float fishCenterX; // declare the variable that will determine the X position from which the cos motion occurs for the fish
float fishCenterY; // declare the variable that will determine the Y position from which the sin motion occurs for the fish
float sizeArcFishMoveX; // declare the variable that will determine the radius of the cos motion for the fish swimming back and forth in circles
float sizeArcFishMoveY; // declare the variable that will determine the radius of the sin motion for the fish swimming back and forth in circles
float fishLocX; // declare the variable that determines the X location of the fish in the animation
float fishLocY; // declare the variable that determines the Y location of the fish in the animation
float speedXFish; // declare the variable that determines the speed applied to the location of the fish in the animation (in this case only the X location)
// constructor for the class called Fish
Fish (color clrFishtemp, float fishXtemp, float fishYtemp) { // create the constructor for the Turtle class and declare its temporary variables
fishX=fishXtemp;
fishY=fishYtemp;
clrFish=clrFishtemp; // initialize the variable that controls the color parameter of the turtle class
fishAngleSpeed=0.4; // assign a value of 0.4 to the change of angle used in the cos and sign wave movement of the fish
fishCenterX=0.0; // assign a value of 0 to the variable that will determine the X position from which the cos motion occurs for the fish
fishCenterY=height/2; // assign a value of half the height of the canvas to the variable that will determine the Y position from which the sin motion occurs for the fish
sizeArcFishMoveX=width/3; // assign a value of a third of the width of the canvas to the variable that will determine the radius of the cos wave motion of the fish
sizeArcFishMoveY=height/3; // assign a value of a third of the height of the canvas to the variable that will determine the radius of the sin wave motion of the fish
} // end the block of code of the constructor for the class called Fish
// method to move the Fish
void move () {
fishX=fishLocX+speedXFish;
fishY=fishLocY;
fishLocX=fishCenterX+sizeArcFishMoveX*cos(radians(fishAngle)); // assign a cos wave movement to the variable that determines the X location of the fish in the animation
fishLocY=fishCenterY+sizeArcFishMoveY*sin(radians(fishAngle)); // assign a sin wave movement to the variable that determines the Y location of the fish in the animation
fishAngle+=fishAngleSpeed; // increment the angle of the fish cos and sin wave movements by 0.4
speedXFish+=(random(0.1, 0.8)); // assign a value that is a random value to move the starfish horizontally across the screen
}
// method to display the Fish
void display () { /// create a variable that will refer to the function used to display the Fish
fill(clrFish);
stroke(1);
strokeWeight (3);
beginShape();
vertex(fishX, fishY);
vertex(fishX+50, fishY+40);
vertex(fishX+105, fishY+20);
vertex(fishX+150, fishY+50);
vertex(fishX+90, fishY+80);
vertex(fishX+55, fishY+70);
vertex(fishX+30, fishY+90);
endShape(CLOSE);
arc (fishX+116, fishY+42, 10, 15, 0, PI);
} // end the block of code of the display method for the class called Fish
} // end the block for the class called Fish
// Reverse Fish class
class FishReverse { // create a class called ReverseFish to show the fish in reverse
// all of the fields for the class called FishReverse
float fishXR;
float fishYR;
color clrFishR;
float fishAngleSpeedR; // declare the variable that will allow for the incrementation of the angle for the fish circular movements
float fishCenterXR; // declare the variable that will determine the X position from which the cos motion occurs for the fish
float fishCenterYR; // declare the variable that will determine the Y position from which the sin motion occurs for the fish
float sizeArcFishMoveXR; // declare the variable that will determine the radius of the cos motion for the fish swimming back and forth in circles
float sizeArcFishMoveYR; // declare the variable that will determine the radius of the sin motion for the fish swimming back and forth in circles
float fishLocXR; // declare the variable that determines the X location of the fish in the animation
float fishLocYR; // declare the variable that determines the Y location of the fish in the animation
float speedXFishR; // declare the variable that determines the speed applied to the location of the fish in the animation (in this case only the X location)
// constructor for the class called Reverse Fish
FishReverse (color clrFishtempR, float fishXtempR, float fishYtempR) { // create the constructor for the Turtle class and declare its temporary variables
fishXR=fishXtempR;
fishYR=fishYtempR;
clrFishR=clrFishtempR; // initialize the variable that controls the color parameter of the turtle class
fishAngleSpeedR=0.4; // assign a value of 0.4 to the change of angle used in the cos and sign wave movement of the fish
fishCenterXR=0.0; // assign a value of 0 to the variable that will determine the X position from which the cos motion occurs for the fish
fishCenterYR=height/2; // assign a value of half the height of the canvas to the variable that will determine the Y position from which the sin motion occurs for the fish
sizeArcFishMoveXR=width/3; // assign a value of a third of the width of the canvas to the variable that will determine the radius of the cos wave motion of the fish
sizeArcFishMoveYR=height/3; // assign a value of a third of the height of the canvas to the variable that will determine the radius of the sin wave motion of the fish
} // end the block of code of the constructor for the class called Fish
// method to move the Fish
void move () {
fishXR=fishLocXR+speedXFishR;
fishYR=fishLocYR;
fishLocXR=fishCenterXR+sizeArcFishMoveXR*cos(radians(fishAngle)); // assign a cos wave movement to the variable that determines the X location of the fish in the animation
fishLocYR=fishCenterYR+sizeArcFishMoveYR*sin(radians(fishAngle)); // assign a sin wave movement to the variable that determines the Y location of the fish in the animation
fishAngle+=fishAngleSpeedR; // increment the angle of the fish cos and sin wave movements by 0.4
speedXFishR+=(random(0.1, 0.8)); // assign a value that is a random value to move the starfish horizontally across the screen
}
I am looking for an elegant solution to programming the following animation with the one fish swimming forward until its orbital trajectory reaches 180, and then flipping to the other side for the other part of its orbital trajectory before it comes back again in its first direction and so on.
Right now, I have superposed the two fish swimming in the full orbit, but it should be one or the other.
I would like to simplify my code. Either by simply flipping the fish horizontally or else by finding a clean solution to conditions. Here are the conditions I had prepared but they don't work in the draw method because the angle can't be read. Beneath those conditions is the full code of the animation which should work fine.
// BEGINNING OF TEST CODE FOR CONDITION
float angleCondition=fishAngle/180; // declare and create a variable that calculates the division of the angle of the cos and sin movement by 180 to determine the condition when the fish changes direction
int angleConditionConvertedtoInteger = int (angleCondition); // convert this variable from a float type to an integer type
if (angleConditionConvertedtoInteger%2==0) { // create a condition that uses the remainder of the division of this variable to determine the direction of the fish so that if the remainder is an even number, the fish swims back
indecisiveFishR.move (); // move the reverse indecisive fish so that it swims back towards the start line
indecisiveFishR.display (); // draw the reverse indecisive fish so that it swims back towards the start line
}
else { // create a condition that uses the remainder of the division of this variable to determine the direction of the fish so that if the remainder is an odd number, the fish swims forward
indecisiveFish.move(); // move the indecisive fish in its forward direction so that it swims towards the finish line
indecisiveFish.display(); // draw the indecisive fish in its forward direction so that it swims towards the finish line
}
// END OF TEST CODE FOR CONDITION
// BELOW IS ALL THE CODE FOR FULL ANIMATION
/* Race between a fish, turtle and starfish with an unpredictable outcome*/
// declare the object variables for this program
Raceline drawStartLine; // Declare a reference variable for the start line object inherited from the Raceline class
Raceline drawFinishLine; // Declare a reference variable for the finish line object inherited from the Raceline class
Starfish steadyStarfish; // Declare a reference variable for the steady starfish object inherited from the Starfish class
Turtle slowTurtle; // Declare a reference variable for the slow turtle object inherited from the Turtle class
Fish indecisiveFish; // Declare reference variable for the indecisive fish object inherited from the Fish class
FishReverse indecisiveFishReverse; // Declare reference variable for the reverse indecisive fish object inherited from the FishReverse class
// declare the object variables related to the text in this program (to write "Start Line" and "Finish Line")
PFont startFinishLine; // Declare a variable that is of the Font class type
String startLine; // Declare a variable that is of the String class type to store a sequence of characters that will textually describe the "Start Line"
String finishLine; // Declare a variable that is of the String class type to store a sequence of characters that will textually describe the "Finish Line"
// define the initial environment properties for this program in the setup function that will be called only once
void setup () { // define initial enviroment properties such as screen size and background color
size (screen.width*3/4, screen.height*5/6); // set the canvas size so that it fills up a large part of the screen
background (0, 170, 250); // set the color of the background to a watery shade of blue
// initialize the font object variables for the text in this program (to write "Start Line" and "Finish Line")
startFinishLine =loadFont ("CourierNewPS-BoldItalicMT-16.vlw"); // construct a new font for the text in this program by loading this font used in a data file attached to this file
textFont (startFinishLine); // make the loaded font active in the startFinishLine variable that is of the Font class type
startLine = "Start Line"; // initialize the startLine string type variable with a sequence of characters that spell "Start Line"
finishLine = "Finish Line"; // initialize the finishLine string type variable with a sequence of characters that spell "Finish Line"
// declare and initialize the race lines and the three different elements of this animation as objects
drawStartLine=new Raceline (color (162, 20, 148), color (162, 20, 148), 2, 40);
drawFinishLine=new Raceline (color (162, 20, 148), color (162, 20, 148), 2, width-40);
steadyStarfish=new Starfish (color (216, 20, 125), 0, 0); // declare and initialize the steadyStarfish object and pass in the parameters that define it
slowTurtle=new Turtle (color (114, 188, 19), 0, 0); // declare and initialize the slowTurtle object and pass in the parameters that define it
indecisiveFish=new Fish (color (255, 40, 10), 0, 0); // declare and initialize the indecisiveFish object and pass in the parameters that define it
indecisiveFishReverse=new FishReverse (color (255, 40, 10), 0, 0);
} // end the setup function
void draw() {
background (0, 170, 250); // set the color of the background to a watery shade of blue
// write the phrases "start line" and "finish line" on the canvas
fill (111, 4, 100); // determine the color of the text as purple
text (startLine, 56, 26); // display the "Start Line" on the top left of the canvas
text (finishLine, width-170, height-20); // display the "Finish Line" on the bottom right of the canvas
steadyStarfish.move(); // call the method to move the steadyStarfish to the screen
steadyStarfish.display(); // call the method to display the steadyStarfish to the screen
slowTurtle.move(); // call the method to move the slowTurtle to the screen
slowTurtle.display(); // call the method to display the slowTurtle to the screen
indecisiveFish.move(); // move the indecisive fish in its forward direction so that it swims towards the finish line
indecisiveFish.display(); // draw the indecisive fish in its forward direction so that it swims towards the finish line
indecisiveFishReverse.move(); // move the indecisive fish in its reverse direction so that it swims towards the finish line
indecisiveFishReverse.display(); // draw the indecisive fish in its reverse direction so that it swims towards the finish line
} // end the draw method
// Race line class
class Raceline {
color clrLine;
color strokeClr;
int dotSize;
int raceLineX;
Raceline (color clrLinetemp, color strokeClrtemp, int dotSizetemp, int raceLineXtemp) {
clrLine=clrLinetemp;
strokeClr=strokeClrtemp;
dotSize=dotSizetemp;
raceLineX=raceLineXtemp;
}
void display() {
for (int i=0; i<height; i+=8) { // loop that will use a counter that will draw a shape every 8 pixels for the whole height of the canvas
stroke (strokeClr); // determine the color of the stroke of the ellipses that form the dotted line as purple
fill (clrLine); // fill with purple the ellipses that form the dotted lines
ellipse (raceLineX, i, dotSize, dotSize); // draw little ellipses every 8 pixels from top to bottom on the left of the canvas to make up the dotted line
} // end the for loop
} // end display
}// end class
// StarFish class
class Starfish { // create a class called Starfish
// all of the fields for the class called Starfish
float starFishX;
float starFishY;
color clrStarFish; // declare the variable that controls the color parameter of the pentagon class
float starFishAngle; // declare the variable that will control the position of the cos and sin wave for the starfish
float starFishAngleSpeed; // declare the variable that will allow for the incrementation of the angle for the starfish undulatory movements
float starFishCenterX; // declare the variable that will determine the X position from which the cos motion occurs for the starfish
float starFishCenterY; // declare the variable that will determine the Y position from which the sin motion occurs for the starfish
float sizeArcStarFishMoveX; // declare the variable that will determine the radius of the cos motion for the starfish so the breadth of the circular movement
float sizeArcStarFishMoveY; // declare the variable that will determine the radius of the sin motion for the starfish so the breadth of the circular movement
float starFishLocX; // declare the variable that determines the X location of the starfish in the animation
float starFishLocY; // declare the variable that determines the Y location of the starfish in the animation
float speedXstarFish; // declare the variable that determines the speed applied to the location of the starfish in the animation (in this case only the X location)
// constructor for the class called Starfish
Starfish (color clrStarFishtemp, float starFishXtemp, float starFishYtemp) { // create the constructor for the Starfish class and declare its temporary variables
starFishX=starFishXtemp;
starFishY=starFishYtemp;
starFishAngle=255.0; // initialize the angle of the starFish so that it emerges from the upper left of the canvas
clrStarFish=clrStarFishtemp; // initialize the variable that controls the color parameter of the starfish class
starFishCenterX=0.0; // assign a value of 0 to the variable that will determine the X position from which the cos motion occurs for the starfish
starFishCenterY=height/3; // assign a value of a third of the height of the canvas to the variable that will determine the Y position from which the sin motion occurs for the starfish
sizeArcStarFishMoveX=width/6; // assign a value to the variable that will determine the radius of the cos motion for the starfish so the breadth of the circular movement
sizeArcStarFishMoveY=height/4; // assign a value to the variable that will determine the radius of the sin motion for the starfish so the breadth of the circular movement
} // end the block of code of the constructor for the class called Starfish
// method to move the Starfish
void move () {
starFishX=starFishLocX+speedXstarFish;
starFishY=starFishLocY;
starFishAngleSpeed=(random(-0.4, 0.1)); // assign a random value between -0.4 and 0.1 to the change of angle used in the undulatory movement of the starfish to make it a bit jittery
starFishLocX=starFishCenterX+sizeArcStarFishMoveX*cos(radians(starFishAngle)); // assign a cos wave movement to the variable that determines the X location of the starfish in the animation
starFishLocY=starFishCenterY+sizeArcStarFishMoveY*sin(radians(starFishAngle)); // assign a sin wave movement to the variable that determines the Y location of the starfish in the animation
starFishAngle+=starFishAngleSpeed; // increment the angle of the starfish cos and sin wave movements the random speed assigned to the starfish speed variable
speedXstarFish+=0.5+(random(-0.8, 0.8)); // assign a value that is a random value added to a constant to move the starfish horizontally across the screen
}
// method to display the Starfish
void display () { /// create a variable that will refer to the function used to display the starfish
strokeJoin(ROUND);
strokeWeight (4);
stroke(1);
fill(clrStarFish);
beginShape();
vertex(starFishX, starFishY+24);
vertex(starFishX+20, starFishY+32);
vertex(starFishX+27, starFishY);
vertex(starFishX+34, starFishY+32);
vertex(starFishX+54, starFishY+24);
vertex(starFishX+42, starFishY+54);
vertex(starFishX+50, starFishY+96);
vertex(starFishX+27, starFishY+72);
vertex(starFishX+4, starFishY+96);
vertex(starFishX+12, starFishY+54);
endShape(CLOSE); // end the recording of the vertices for the Starfish class and closes the shape
} // end the block of code of the display method for the class called Starfish
} // end the block for the class called Starfish
// Turtle class
class Turtle { // create a class called Turtle
// all of the fields for the class called Turtle
float turtleX;
float turtleY;
color clrTurtle;
float angle; // declare the variable that will control the position of the sin wave for the turtle
float turtleMiddleYPos; // declare the variable that will determine the Y position from which the sin motion occurs for the turtle
float turtleYRangeOfMotion; // declare the variable that will determine the radius of the sin motion for the turtle
float speedOfSinWaveMovement; // declare the variable that will impart a change in the angle that controls the sin wave for the turtle
float turtleLocX; // declare the variable that determines the X location of the turtle in the animation
float turtleLocY; // declare the variable that determines the Y location of the turtle in the animation
float speedXTurtle; // declare the variable that determines the speed of the turtle's horizontal movement
// constructor for the class called Turtle
Turtle (color clrTurtletemp, float turtleXtemp, float turtleYtemp) { // create the constructor for the Turtle class and declare its temporary variables
turtleX=turtleXtemp;
turtleY=turtleYtemp;
clrTurtle=clrTurtletemp; // initialize the variable that controls the color parameter of the turtle class
turtleLocX=0.0-140; // initialize the content of global variable for the X location of the turtle
angle=0.0; // initialize the value of the angle of the sin wave that has a zero value
turtleMiddleYPos=height/2-58; // initialize that determines the Y position from which the sin motion occurs so that it is in the center taking into account the height of the turtle divided by 2 (116%2=58)
turtleYRangeOfMotion=height/2.6; // initialize a value for the range of Y movement of the turtle on the sin wave that makes it cover most of the height but stays inside the window
speedOfSinWaveMovement=0.005; // initialize a value for the speed of the change of angle of the sin wave that is relatively slow
} // end the block of code of the constructor for the class called Turtle
// method to move the Turtle
void move () {
turtleX=turtleLocX+speedXTurtle;
turtleY=turtleLocY;
turtleLocY=turtleMiddleYPos+sin(angle)*turtleYRangeOfMotion; // calculates the Y location of the turtle on the sin wave movement
angle+=speedOfSinWaveMovement; // increment the angle of the sin wave by the speed factor every time the draw () method is called
speedXTurtle+=0.5; //increment the speed of the turtle's horizontal movement
}
// method to display the Turtle
void display () { /// create a variable that will refer to the function used to display the starfish
// assign parameters for the color and stroke of the solid turtle figure
fill(clrTurtle);
; // set color of solid figure to a turtle-like green
stroke(0); // set color of stroke to black for the solid figure outlines
smooth(); // set anti-aliased edges for the solid turtle figure
strokeWeight (3); // set the thickness of the stroke that delineated the solid turtle figure
// draw the top flapper underneath the body and head
beginShape();
curveVertex (turtleX+122, turtleY+25);
curveVertex (turtleX+122, turtleY+25);
curveVertex (turtleX+128, turtleY+21);
curveVertex (turtleX+138, turtleY-8);
curveVertex (turtleX+115, turtleY-30);
curveVertex (turtleX+125, turtleY-15);
curveVertex (turtleX+113, turtleY+7);
curveVertex (turtleX+113, turtleY+7);
endShape(CLOSE); // end the recording of the vertices for the top flapper of the Turtle class and closes the shape
// draw the bottom flapper underneath the body and head
beginShape();
curveVertex (turtleX+131, turtleY+23);
curveVertex (turtleX+131, turtleY+23);
curveVertex (turtleX+136, turtleY+27);
curveVertex (turtleX+138, turtleY+42);
curveVertex (turtleX+130, turtleY+60);
curveVertex (turtleX+118, turtleY+85);
curveVertex (turtleX+119, turtleY+86);
curveVertex (turtleX+115, turtleY+78);
curveVertex (turtleX+124, turtleY+25);
curveVertex (turtleX+124, turtleY+25);
endShape(CLOSE); // end the recording of the vertices for the bottom flapper of the Turtle class and closes the shape
// draw the body of the turtle with 11 curveVertices points
curveVertex (turtleX+12, turtleY+25);
curveVertex (turtleX+12, turtleY+25);
endShape(CLOSE); // end the recording of the vertices for the body of the Turtle class and closes the shape
// draw the eye and the smile of the turtle
fill(232, 221, 7); // make eye color brown
ellipse (turtleX+158, turtleY+14, 2, 2); // draw small eye
noStroke(); // eliminate stroke for the mouth
fill(93, 9, 0); // make mouth pinky red
arc(turtleX+156, turtleY+24, 6, 6, QUARTER_PI, PI+QUARTER_PI); //draw arc of mouth
} // end the block of code of the display method for the class called Turtle
} // end the block for the class called Turtle
// Fish class
class Fish { // create a class called Fish
// all of the fields for the class called Turtle
float fishX;
float fishY;
color clrFish;
float fishAngle; // declare the variable that will control the position of the cos and sin wave for the fish
float fishAngleSpeed; // declare the variable that will allow for the incrementation of the angle for the fish circular movements
float fishCenterX; // declare the variable that will determine the X position from which the cos motion occurs for the fish
float fishCenterY; // declare the variable that will determine the Y position from which the sin motion occurs for the fish
float sizeArcFishMoveX; // declare the variable that will determine the radius of the cos motion for the fish swimming back and forth in circles
float sizeArcFishMoveY; // declare the variable that will determine the radius of the sin motion for the fish swimming back and forth in circles
float fishLocX; // declare the variable that determines the X location of the fish in the animation
float fishLocY; // declare the variable that determines the Y location of the fish in the animation
float speedXFish; // declare the variable that determines the speed applied to the location of the fish in the animation (in this case only the X location)
// constructor for the class called Fish
Fish (color clrFishtemp, float fishXtemp, float fishYtemp) { // create the constructor for the Turtle class and declare its temporary variables
fishX=fishXtemp;
fishY=fishYtemp;
clrFish=clrFishtemp; // initialize the variable that controls the color parameter of the turtle class
fishAngle=245.0; // initialize the angle of the fish so that it emerges from the top left of the canvas
fishAngleSpeed=0.4; // assign a value of 0.4 to the change of angle used in the cos and sign wave movement of the fish
fishCenterX=0.0; // assign a value of 0 to the variable that will determine the X position from which the cos motion occurs for the fish
fishCenterY=height/2; // assign a value of half the height of the canvas to the variable that will determine the Y position from which the sin motion occurs for the fish
sizeArcFishMoveX=width/3; // assign a value of a third of the width of the canvas to the variable that will determine the radius of the cos wave motion of the fish
sizeArcFishMoveY=height/3; // assign a value of a third of the height of the canvas to the variable that will determine the radius of the sin wave motion of the fish
} // end the block of code of the constructor for the class called Fish
// method to move the Fish
void move () {
fishX=fishLocX+speedXFish;
fishY=fishLocY;
fishLocX=fishCenterX+sizeArcFishMoveX*cos(radians(fishAngle)); // assign a cos wave movement to the variable that determines the X location of the fish in the animation
fishLocY=fishCenterY+sizeArcFishMoveY*sin(radians(fishAngle)); // assign a sin wave movement to the variable that determines the Y location of the fish in the animation
fishAngle+=fishAngleSpeed; // increment the angle of the fish cos and sin wave movements by 0.4
speedXFish+=(random(0.1, 0.8)); // assign a value that is a random value to move the starfish horizontally across the screen
}
// method to display the Fish
void display () { /// create a variable that will refer to the function used to display the Fish
fill(clrFish);
stroke(1);
strokeWeight (3);
beginShape();
vertex(fishX, fishY);
vertex(fishX+50, fishY+40);
vertex(fishX+105, fishY+20);
vertex(fishX+150, fishY+50);
vertex(fishX+90, fishY+80);
vertex(fishX+55, fishY+70);
vertex(fishX+30, fishY+90);
endShape(CLOSE);
arc (fishX+116, fishY+42, 10, 15, 0, PI);
} // end the block of code of the display method for the class called Fish
} // end the block for the class called Fish
// Reverse Fish class
class FishReverse { // create a class called ReverseFish to show the fish in reverse
// all of the fields for the class called FishReverse
float fishXR;
float fishYR;
color clrFishR;
float fishAngleR; // declare the variable that will control the position of the cos and sin wave for the fish
float fishAngleSpeedR; // declare the variable that will allow for the incrementation of the angle for the fish circular movements
float fishCenterXR; // declare the variable that will determine the X position from which the cos motion occurs for the fish
float fishCenterYR; // declare the variable that will determine the Y position from which the sin motion occurs for the fish
float sizeArcFishMoveXR; // declare the variable that will determine the radius of the cos motion for the fish swimming back and forth in circles
float sizeArcFishMoveYR; // declare the variable that will determine the radius of the sin motion for the fish swimming back and forth in circles
float fishLocXR; // declare the variable that determines the X location of the fish in the animation
float fishLocYR; // declare the variable that determines the Y location of the fish in the animation
float speedXFishR; // declare the variable that determines the speed applied to the location of the fish in the animation (in this case only the X location)
// constructor for the class called Reverse Fish
FishReverse (color clrFishtempR, float fishXtempR, float fishYtempR) { // create the constructor for the Turtle class and declare its temporary variables
fishXR=fishXtempR;
fishYR=fishYtempR;
clrFishR=clrFishtempR; // initialize the variable that controls the color parameter of the turtle class
fishAngleR=245.0; // initialize the angle of the fish so that it emerges from the top left of the canvas
fishAngleSpeedR=0.4; // assign a value of 0.4 to the change of angle used in the cos and sign wave movement of the fish
fishCenterXR=0.0; // assign a value of 0 to the variable that will determine the X position from which the cos motion occurs for the fish
fishCenterYR=height/2; // assign a value of half the height of the canvas to the variable that will determine the Y position from which the sin motion occurs for the fish
sizeArcFishMoveXR=width/3; // assign a value of a third of the width of the canvas to the variable that will determine the radius of the cos wave motion of the fish
sizeArcFishMoveYR=height/3; // assign a value of a third of the height of the canvas to the variable that will determine the radius of the sin wave motion of the fish
} // end the block of code of the constructor for the class called Fish
// method to move the Fish
void move () {
fishXR=fishLocXR+speedXFishR;
fishYR=fishLocYR;
fishLocXR=fishCenterXR+sizeArcFishMoveXR*cos(radians(fishAngleR)); // assign a cos wave movement to the variable that determines the X location of the fish in the animation
fishLocYR=fishCenterYR+sizeArcFishMoveYR*sin(radians(fishAngleR)); // assign a sin wave movement to the variable that determines the Y location of the fish in the animation
fishAngleR+=fishAngleSpeedR; // increment the angle of the fish cos and sin wave movements by 0.4
speedXFishR+=(random(0.1, 0.8)); // assign a value that is a random value to move the starfish horizontally across the screen
}
I am seeking better motion strategies to represent the characters of this animation scene. In the case of the dog, I need to find a way to fix the speed so that its attempt to break away from its leash is more realistic and in the case of the cat, I would like to find a way to have it jump around near the mouse and stay there for a few seconds.
Any ideas?
/* This animation is an interactive game that consists in trying to keep the mouse hidden underneath the moving turtle so that it can try to hide from the cat.
// declare global variables used in this program for the creatures taken from online available clip art
PImage mouseClipArt; // declare a variable to store the mouse image
PImage gingerCatClipArt; // declare a variable to store the cat image
PImage dogOnLeashClipArt; // declare a variable to store the dog image
// declare global variables used in this program for the cat positions and movements
float catRandomX; // declare a variable that will impart some randomness to the cat's horizontal position and thus movements
float catRandomY; // declare a variable that will impart some randomness to the cat's vertical position and thus movements
// declare global variables used in this program for the dog positions and movements
float dogLocX; // declare the variable that determines the X location of the dog in the animation
float dogLocY; // declare the variable that determines the Y location of the dog in the animation
float dogRelativeYPos; // declare a variable that will ensure that the dog's bobbing is related to the Y movement of the mouse
float dogYRangeOfMotion; // declare the variable that will determine the radius of the sin motion to limit the range of the dog's bobbing
float angleDog; // declare the variable that will control the position of the sin wave in the dog's movement
float speedOfDogUpAndDown; // declare a variable that will determine the speed of the dog's bobbing
// declare global variables used in this program for the turtle
float turtleLocX; // declare the variable that determines the X location of the turtle in the animation
float turtleLocY; // declare the variable that determines the Y location of the turtle in the animation
float angleX; // declare the variable that will control the position of the cos wave
float angleY; // declare the variable that will control the position of the sin wave
float turtleMiddleXPos; // declare the variable that will determine the X position from which the cos motion occurs
float turtleXRangeOfMotion; // declare the variable that will determine the radius of the cos motion
float turtleMiddleYPos; // declare the variable that will determine the Y position from which the sin motion occurs
float turtleYRangeOfMotion; // declare the variable that will determine the radius of the sin motion
float speedOfCosWaveMovement; // declare the variable that will impart a change in the angle that controls the cos wave
float speedOfSinWaveMovement; // declare the variable that will impart a change in the angle that controls the sin wave
void setup() {
size(1200, 800); // set the canvas size at 1200 pixels by 800 pixels
background(0, 170, 250); // set background color to the watery shade of blue of A2_01
// initialization of mouse (clip art) variable(s)
mouseClipArt =loadImage ("cf_mouse_clipart.png"); // load the mouse image into its variable
gingerCatClipArt =loadImage ("cf_gingercat_clipart.png"); // load the cat image into its variable
dogOnLeashClipArt =loadImage ("cf_dogonleash_clipart.png"); // load the dog image into its variable
// initialization of dog variables
angleDog=0.0; // initialize the value of the angle for the dog's sin wave movement that has a zero value
dogLocX=1.0; // initialize the value of the angle for the dog X position sot that it starts at zero
dogYRangeOfMotion=height/15-250; // initialize a value for the range of the Y movement of the dog on the sin wave that makes it bob up and down taking its own height into account (=250 pixels)
speedOfDogUpAndDown=0.18; // assign a speed of motion to the dog's up and down movement so that it is bobbing furiously yet also able to follow the Y position of the mouse
// initialization of turtle variables
angleX=0.0; // initialize the value of the angle of the cos wave that has a zero value
angleY=0.0; // initialize the value of the angle of the sin wave that has a zero value
turtleMiddleXPos=width/2-83; // initialize that determines the X position from which the cos motion occurs so that it is roughly near the center calculating the width of the turtle divided by 2 (166%2=83)
turtleXRangeOfMotion=width/4; // initialize a value for the range of X movement of the turtle on the cos wave that makes it cover most of the height but stays inside the window
turtleMiddleYPos=height/2-58; // initialize that determines the Y position from which the sin motion occurs so that it is in the center taking into account the height of the turtle divided by 2 (116%2=58)
turtleYRangeOfMotion=height/3; // initialize a value for the range of Y movement of the turtle on the sin wave that makes it cover most of the height but stays inside the window
speedOfCosWaveMovement=0.011; // initialize a value for the speed of the change of angle of the cos wave that is relatively slow
speedOfSinWaveMovement=0.008; // initialize a value for the speed of the change of angle of the sin wave that is slightly slower than the change of angle for the cos wave movement
}
// animation method block of code
void draw() {
background(0, 170, 250); // recall the background color in setup during draw
// mouse (from clip art) movements in the draw function
image(mouseClipArt, mouseX-30, mouseY-22, 50, 50); // draw the mouse and position it so that cursor is smack in the middle of it and so that it is small enough to hide underneath the turtle
catRandomX=mouseX*random (-0.0058, 0.0058); // impart a jittery random speed to the cat's X movement that is multiplied by the the movement of mouseX as a decimal value
catRandomY=random (-3, 3); // impart a small random speed to the cat's Y movement to add to the movement of mouseY
image (gingerCatClipArt, (mouseX+135)+catRandomX, (mouseY-150)+catRandomY, 75, 150); // draw the cat and position it so that it is always away from the mouse
// dog movements in the draw method
dogLocX= random(-50, 4); // imparts a random horizontal range of movement to the dog to show it is trying to break off from its leash
dogRelativeYPos=mouseY; // ensures that the dog's up and down movement is relative to the movement of the mouse and the cat
dogLocY=dogRelativeYPos+sin(angleDog)*dogYRangeOfMotion; // calculates the Y location of the dog on the sin wave movement
image (dogOnLeashClipArt, dogLocX, dogLocY, 200, 200); // draw the dog and position it so that it is trying to break its leash while it is stuck in the corner and male it a size that is both proportionate and threatening
angleDog+=speedOfDogUpAndDown; // increment the angle of the sin wave by the speed factor every time the draw () method is called
// turtle movements in the draw method
turtleLocX=turtleMiddleXPos+cos(angleX)*turtleXRangeOfMotion; // calculates the X location of the turtle during its animated movement on the cos wave
turtleLocY=turtleMiddleYPos+sin(angleY)*turtleYRangeOfMotion; // calculates the Y location of the turtle during its animated movement on the sin wave
turtle (turtleLocX, turtleLocY); // draw the turtle from A2_01
angleX+=speedOfCosWaveMovement; // increment the angle of the cos wave by the cos speed factor every time the draw () method is called
angleY+=speedOfSinWaveMovement; // increment the angle of the sin wave by the sin speed factor every time the draw () method is called
}
// assign parameters for the color and stroke of the solid turtle figure
fill (114, 188, 19); // set color of solid figure to a turtle-like green
stroke(0); // set color of stroke to black for the solid figure outlines
smooth(); // set anti-aliased edges for the solid turtle figure
strokeWeight (3); // set the thickness of the stroke that delineated the solid turtle figure
I have drawn a turtle in procedural processing in this first bit of code (see code #1) but when I try to draw that turtle in the draw () function by calling it as a method, the stroke disappears around it (see code #2). What is the most efficient way to address this problem? I cannot do OOP for this right now, so I need to remain in procedural programming.
CODE #1:
// define the size and color of the program and call the turtle method
void setup () {
size(400, 400); // set canvas size
background(0, 170, 250); // set background color to a watery shade of blue
turtle (width/4, height/2); // call the turtle method and give it arguments that position
// it so that it seems roughly near the middle of the canvas
}
// Define the turtle procedure as a method in its own section
// assign parameters for the color and stroke of the solid turtle figure
fill (114, 188, 19); // set color of solid figure to a turtle-like green
smooth(); // set anti-aliased edges for the solid turtle figure
strokeWeight (3); // set the thickness of the stroke that delineated the solid turtle figure
// assign parameters for the color and stroke of the solid turtle figure
fill (114, 188, 19); // set color of solid figure to a turtle-like green
smooth(); // set anti-aliased edges for the solid turtle figure
strokeWeight (3); // set the thickness of the stroke that delineated the solid turtle figure
I am working on a small animation. After having inserted this block in it, I noticed that the first second or two when I run it, I get a blank screen as if something is destabilizing the execution. I was curious to know why this particular block would do that? This is the problem block and I have included the whole code in another section below that.
// loop to draw the twelve lines on the sand that mark the hours
int lineNumber =0;
while (lineNumber<13) {
int spaceBetween =(lineNumber-1)*10;
int hourCounter=lineNumber+1;
float hourLineY = (seaLevelLow+2)+spaceBetween;
float inverseHourLineY = height-spaceBetween-3;
stroke(232, 221, 7);
strokeWeight(1);
line (40, hourLineY, width-40, hourLineY);
fill(209,199,6);
text(hourCounter, 20, inverseHourLineY);
text(hourCounter+12, width-30, hourLineY-5);
lineNumber++; }
// declare global variables for internal clock time functions
int hr; // will return the hour according to internal clock
int mnt; // will return the minutes according to internal clock
int sec; //returns the seconds according to internal clock
int dy; //returns the day of the month according to internal clock
int mth; //returns the month according to internal clock
int yr; //returns the four digit year according to internal clock
float milliseconds; //returns the number of milliseconds since start of app according to internal clock
// declare global variables for sky lines and sun and moon animation
float centerX;
float centerY;
float horizonLineY;
float arcSpaceX;
float arcSpaceY;
float arcSpaceAngleX;
float arcSpaceAngleY;
float x;
float y;
int sunSize=90;
float angle;
float sizeArcX;
float sizeArcY;
float sunSpeed;
float seaLevelLow;
float seaLevelY;
float hourLineY;
// declare global variables for Spring fish animation
float FishYLocation;
float maleFishXLocation=1500;
float femaleFishXLocation=1200;
float fishSpeed=2;
float maleFishAcceleration=2;
float fishReproductionSpeed=3;
float babyX;
float babyY;
int time1 = 8000;
// prepare the size and framerate of the application
void setup() {
size(1400, 800);
frameRate (30);
// initialize content of the global variables for internal clock time
int hr= hour(); // hour will range from 0 to 23
int mnt=minute(); // minutes will range from 0 to 59
int sec=second(); // seconds will range from 0 to 59
int dy=day(); // days will range from 1 to 31
int mth=month(); // mth will range from 1 to 12
int yr=year(); // yr will range from this year on
float milliseconds =millis(); // milliseconds will start when app starts
// initialize content of the global variables for rotation of sun
// and static purple lines that function as a 5 sec. time reference
centerX=width/2;
centerY=height/2;
horizonLineY=height-height*3/5;
seaLevelLow=height-120;
angle=0.0;
sizeArcX=width/2;
sizeArcY=height/2.1;
}
void draw() {
background(120, 70, 230);
// initialize content of the local variables
sunSpeed=second();
angle=180+3*sunSpeed;
// loop to draw purple lines in the sky spaced apart in a regular fashion
// where the space between each line represents a span of 5 seconds.
void draw() {
int fishMotion =millis ();
float FishYLocation=height*5/7;
background (230);
// Condition for seduction preceding spawning
if (femaleFishXLocation<maleFishXLocation) {
//Female fish appearing followed by a male fish
if (fishMotion < time1) {
maleFishXLocation-=fishSpeed;
femaleFishXLocation-=fishSpeed;
}
// Male fish showing interest in female fish
else {
maleFishAcceleration*=1.007;
maleFishXLocation-=maleFishAcceleration;
femaleFishXLocation-=fishSpeed;
}
fill(255,40,10);
drawFish (femaleFishXLocation, FishYLocation);
fill(245, 245, 0);
drawFish (maleFishXLocation, FishYLocation);
}
// Fish spawning as they swim off the screen together
else {
femaleFishXLocation-=fishSpeed;
fill(255,40,10);
drawFish (femaleFishXLocation, FishYLocation);
fill(245, 245, 0);
drawFish (femaleFishXLocation-1, FishYLocation);
// Baby fish following behind
fill(255, 180, 0);
scale(0.5);
//draw and move sun incrementally everytime the loop is called
for (float angle=0; angle<180; angle+=3) {
float speed=second();
background(120, 50, 230);
fill(255, 255, 0);
noStroke();
float x=width/2+scalar*sin(radians(angle)-speed);
float y=height/2+scalar*cos(radians(angle)-speed);
ellipse(x, y, 100, 100);
}
}