//***************************************************************************************** // Author: Professor Shieu-Hong Lin, MATH/CS Department, Biola University. 2018 // Permission is given to students/educators for adapting the code below. //***************************************************************************************** //************************************************************************************************ //Create four new fish objects centered at // (400, 400), (430, 450), (500, 520), and (50, 500)respectively //************************************************************************************************ RigidFish myFish1 = new RigidFish(400, 400); RigidFish myFish2 = new RigidFish(430, 450); RigidFish myFish3 = new RigidFish(500, 520); RigidFish myFish4 = new RigidFish(50, 500); //************************************************************************************************ //Create four movingItem objects centered at different locations //************************************************************************************************ MovingItem myBall1 = new MovingItem(70, 100); MovingItem myBall2 = new MovingItem(170, 300); MovingItem myBall3 = new MovingItem(370, 100); MovingItem myBall4 = new MovingItem(470, 400); //******************************************************************************************** //Define the setup function, which will be called once in the beginning // to set up some initial settings of the program //******************************************************************************************** void setup() { //Set the canvas size size(800, 800); //Set the background color of the canvas background(192, 64, 0); //Set the stroke color as white stroke(255, 255, 255); // make the balls Visible myBall1.setVisibility(true); myBall2.setVisibility(true); myBall3.setVisibility(true); myBall4.setVisibility(true); } //******************************************************************************************** //Define the draw function, which will be called repeatedly to draw pictures on the screen //******************************************************************************************** void draw() { //Clear the canvas background(192, 64, 0); //******************************************************************************************** //Draw the fish heading toward the corresponding balls. //******************************************************************************************** myFish1.drawFishHeadToward(myBall1); myFish2.drawFishHeadToward(myBall2); myFish3.drawFishHeadToward(myBall3); myFish4.drawFishHeadToward(myBall4); //******************************************************************************************** //Move the fishtoward the corresponding balls in different speed. //******************************************************************************************** //myFish1.keepDistanceFrom(mouseX, mouseY, 4); myFish1.moveToward(myBall1, 3); myFish2.moveToward(myBall2, 5); myFish3.moveToward(myBall3, 4); myFish4.moveToward(myBall4, 6); //******************************************************************************************** //Move the balls in different ways. //******************************************************************************************** myBall1.moveAsBouncingBall(); myBall2.moveUpDown(); myBall3.moveAsBouncingBall(); myBall4.moveAsBouncingBall(); } //***************************************************************************************** // The RigidFish class below defines the behavior of objects from the RigidFish class. //***************************************************************************************** class RigidFish { //******************************************************************************************** // For each object of the RigidFish class: // The following two data variables control the dynamics of the fins and the tail. //******************************************************************************************** float extentionScale; float increment; //***************************************************************************************** // For each object of the RigidFish class: // The following data variables model the shape of the fish //***************************************************************************************** // // float centerX: x coordinate of the center of the fish body // float centerY: y coordinate of the center of the fish body // float width: width of fish body // float fin: distance from head to the middle point of the tips of two fins // float tailLength: length of the fish tail // float tailWwidth: width of fish tail //***************************************************************************************** float centerX, centerY, length, width, fin, tailLength, tailWidth; //***************************************************************************************** // For each object of the RigidFish class: // The following data variables model the colorof the fish //***************************************************************************************** float R, G, B; //***************************************************************************************** // For each object of the RigidFish class: // The following constructor allows us to create a new object of the RigidFish class and // (i) set and propoerly set the center of the fish while // (ii) randmly set the values of the other control variables of the objects. //***************************************************************************************** RigidFish(float myCenterX, float myCenterY) { centerX = myCenterX; centerY = myCenterY; length = random(10, 80); width = random(10, 1.2*length); fin = random(5, 0.7*length); tailLength = random(10, 80); tailWidth = random(10, 80); extentionScale = 0.75 + random(0, 0.5); increment = 0.05 + random(0, 0.05); R = random(0,255); G = random(0,255); B = random(0,255); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to reset the center of the fish obejct. //***************************************************************************************** void setCenter(float myCenterX, float myCenterY) { centerX = myCenterX; centerY = myCenterY; } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to reset the shape of the fish obejct. //***************************************************************************************** void setShape(float myLength, float myWidth, float myFin, float myTailLength, float myTailWidth) { length = myLength; width = myWidth; fin = myFin; tailLength = myTailLength; tailWidth = myTailWidth; } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to reset the flapping parameters of the fish obejct. //***************************************************************************************** void setFlappingParameters(float myExtentionScale, float myIncrement) { extentionScale = myExtentionScale; increment = myIncrement; } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to reset the color of the fish obejct. //***************************************************************************************** void setFishColor(float myR, float myG, float myB) { R= myR; G = myG; B=myB; } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to draw the fish obejct with // fish body centered at (centerX, centerY) while heading toward (headX, headY) //***************************************************************************************** void drawFishHeadToward(float headX, float headY) { //********************************** //Set the fill color of the fish //********************************** fill(R, G, B); //********************************** //Determine the tail of the body //********************************** float tailX = centerX + (centerX - headX); float tailY = centerY + (centerY - headY); //********************************************************************* //Determine the orientation direction of the body: tail toward head //********************************************************************* float directionX = headX - tailX; float directionY = headY - tailY; //************************************************ //Determine the scaling factor of the body length //************************************************ float directionLength = sqrt(directionX*directionX + directionY*directionY); float lengthScale = (length / directionLength) *0.5; //********************************************************************* //Determine the orientation direction of the body: side to side //********************************************************************* float widthDirectionX = headY - tailY; float widthDirectionY = (-1)*(headX - tailX); //************************************************ //Determine the scaling factor of the body width //************************************************ float widthScale = (width / directionLength) *0.5; //************************************************ //Determine the fin location along of the body (on head to tail line) //************************************************ float finScale = (length / 2 - fin) / length; float finX = centerX + finScale*(2 * lengthScale)*directionX; float finY = centerY + finScale*(2 * lengthScale)*directionY; //************************* //Draw the body as a quad //************************* quad(centerX + lengthScale*directionX, centerY + lengthScale*directionY, finX + widthScale*widthDirectionX, finY + widthScale*widthDirectionY, centerX - lengthScale*directionX, centerY - lengthScale*directionY, finX - widthScale*widthDirectionX, finY - widthScale*widthDirectionY ); //********************************************************************* //Determine the extent of fin movement in a scale of 0.5 to 1.5 //********************************************************************* if (extentionScale> 1.25 || extentionScale< 0.75) increment *= -1; extentionScale += increment; //********************************************************************* //Determine the directions of the fin #1 //********************************************************************* float finDirectionX1 = (finX + widthScale*widthDirectionX) - (centerX + lengthScale*directionX); float finDirectionY1 = (finY + widthScale*widthDirectionY) - (centerY + lengthScale*directionY); //************************* //Draw fin #1 //************************* triangle( finX + widthScale*widthDirectionX, finY + widthScale*widthDirectionY, finX + extentionScale*widthScale*widthDirectionX + 0.5*finDirectionX1, finY + extentionScale*widthScale*widthDirectionY + 0.5*finDirectionY1, finX + (extentionScale - 0.15)*widthScale*widthDirectionX + 0.5*finDirectionX1, finY + (extentionScale - 0.15)*widthScale*widthDirectionY + 0.5*finDirectionY1 ); //********************************************************************* //Determine the directions of the fin #2 //********************************************************************* float finDirectionX2 = (finX - widthScale*widthDirectionX) - (centerX + lengthScale*directionX); float finDirectionY2 = (finY - widthScale*widthDirectionY) - (centerY + lengthScale*directionY); //************************* //Draw fin #2 //************************* triangle(finX - widthScale*widthDirectionX, finY - widthScale*widthDirectionY, finX - extentionScale*widthScale*widthDirectionX + 0.5*finDirectionX2, finY - extentionScale*widthScale*widthDirectionY + 0.5*finDirectionY2, finX - (extentionScale - 0.15)*widthScale*widthDirectionX + 0.5*finDirectionX2, finY - (extentionScale - 0.15)*widthScale*widthDirectionY + 0.5*finDirectionY2 ); //************************************************************ //Determine the scaling factors of the tail: length and width //************************************************************ float tailLengthScale = tailLength / directionLength; float tailWidthScale = (tailWidth / directionLength) * 0.5; //********************************** //Determine the tip of the tail //********************************** float tipX = centerX - lengthScale*directionX; float tipY = centerY - lengthScale*directionY; //************************************************ //Determine the bottom location along of the tail (on head to tail line) //************************************************ float endX = centerX - (lengthScale + tailLengthScale)*directionX; float endY = centerY - (lengthScale + tailLengthScale)*directionY; //************************* //Draw the tail as two triangled //************************* triangle(tipX, tipY, endX + 0.5* tailLengthScale*directionX, endY + 0.5* tailLengthScale*directionY, endX + (2 - extentionScale)*tailWidthScale * widthDirectionX, endY + (2 - extentionScale)*tailWidthScale * widthDirectionY ); triangle(tipX, tipY, endX + 0.5* tailLengthScale*directionX, endY + 0.5* tailLengthScale*directionY, endX - (2 - extentionScale)*tailWidthScale * widthDirectionX, endY - (2 - extentionScale)*tailWidthScale * widthDirectionY ); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to draw the fish obejct with // fish body centered at (centerX, centerY) while heading toward the center of another fish. //***************************************************************************************** void drawFishHeadToward(RigidFish anotherFish) { drawFishHeadToward(anotherFish.centerX, anotherFish.centerY); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to draw the fish obejct with // fish body centered at (centerX, centerY) while heading toward the center of a moving object. //***************************************************************************************** void drawFishHeadToward(MovingItem aMovingObject) { drawFishHeadToward(aMovingObject.centerX, aMovingObject.centerY); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to draw the fish obejct with // fish body centered at (centerX, centerY) while heading away from (awayX, awayY) //***************************************************************************************** void drawFishHeadAwawFrom(float awayX, float awayY) { float headX, headY; headX = centerX + (centerX - awayX); headY = centerY + (centerY - awayY); drawFishHeadToward(headX, headY); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to draw the fish obejct with // fish body centered at (centerX, centerY) while heading away from anotherFish //***************************************************************************************** void drawFishHeadAwawFrom(RigidFish anotherFish) { float headX, headY; headX = centerX + (centerX - anotherFish.centerX); headY = centerY + (centerY - anotherFish.centerY); drawFishHeadToward(headX, headY); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to draw the fish obejct with // fish body centered at (centerX, centerY) while heading away from aMovingObject //***************************************************************************************** void drawFishHeadAwawFrom(MovingItem aMovingObject) { float headX, headY; headX = centerX + (centerX - aMovingObject.centerX); headY = centerY + (centerY - aMovingObject.centerY); drawFishHeadToward(headX, headY); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct closer // toward a target point (targetX, targetY) with an approaching rate of speed. //***************************************************************************************** void moveToward(float targetX, float targetY, float approachingRate) { //******************************************************************************************** //Update the X and Y coordinates of the center to move it closer toward the target //******************************************************************************************** centerX = centerX + 0.01*approachingRate*(targetX - centerX); centerY = centerY + 0.01*approachingRate*(targetY - centerY); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct // toward the center of another fish. //***************************************************************************************** void moveToward(RigidFish anotherFish, float approachingRate) { moveToward(anotherFish.centerX, anotherFish.centerY, approachingRate); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct // toward the center of another fish. //***************************************************************************************** void moveToward(MovingItem aMovingObject, float approachingRate) { moveToward(aMovingObject.centerX, aMovingObject.centerY, approachingRate); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct to keep a distance // from a target point (targetX, targetY) with a rate of speed. //***************************************************************************************** void keepDistanceFrom(float targetX, float targetY, float apprachingRate) { float distance; //Calculate the Manhattann distance where distance = abs(targetX-centerX) + abs(targetY-centerY)+1; //******************************************************************************************** //Update the X and Y coordinates of the center to move it away from the target //******************************************************************************************** if (distance < 300) //Get away if it is too close { centerX = centerX - 9.95*apprachingRate*(targetX-centerX)/pow(distance, 1.4); centerY = centerY - 9.95*apprachingRate*(targetY-centerY)/pow(distance, 1.4); } else if (distance > 400) //Move closer if it is too far { centerX = centerX + 9.95*apprachingRate*(targetX-centerX)/pow(distance, 1.4); centerY = centerY + 9.95*apprachingRate*(targetY-centerY)/pow(distance, 1.4); } //******************************************************************************************** //Update the X and Y coordinates to make sure it is within the 800*800 frame //******************************************************************************************** if ( centerX > 800 ) centerX= 0; if ( centerY > 800 ) centerY= 0; if ( centerX < 0 ) centerX= 800; if ( centerY < 0 ) centerY= 800; } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct to keep a distance // from the center of another fish. //***************************************************************************************** void keepDistanceFrom(RigidFish anotherFish, float apprachingRate) { keepDistanceFrom(anotherFish.centerX, anotherFish.centerY, apprachingRate); } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct to keep a distance // from the center of another fish. //***************************************************************************************** void keepDistanceFrom(MovingItem anObject, float apprachingRate) { keepDistanceFrom(anObject.centerX, anObject.centerY, apprachingRate); } } //***************************************************************************************** // The MovingItem class below defines the behavior of moving objects from the MovingItem class //***************************************************************************************** class MovingItem { //***************************************************************************************** // For each object of the MovingItem class: // The following data variables model the center of the object //***************************************************************************************** // // float centerX: x coordinate of the center of the moving object // float centerY: y coordinate of the center of the moving object //***************************************************************************************** float centerX, centerY; //******************************************************************************************** // For each object of the MovingItem class: // The following two data variables control the speed of the moving object. //******************************************************************************************** float x_vel, y_vel; //******************************************************************************************** // For each object of the MovingItem class: // The following data variable control the visibility of the moving object. //******************************************************************************************** boolean visibility; //***************************************************************************************** // For each object of the MovingItem class: // The following constructor method sets the center of the moving object // and initializes it with a random speed. //***************************************************************************************** MovingItem(float x, float y) { centerX = x; centerY = y; x_vel = random(2, 9); y_vel = random(2, 9); visibility = false; } //***************************************************************************************** // For each object of the MovingItem class: // The following method allows us to set the visibility of the moving obejct. //***************************************************************************************** void setVisibility(boolean status) { visibility = status; } //***************************************************************************************** // For each object of the MovingItem class: // The following method allows us to set the velocity of the moving obejct along X and Y. //***************************************************************************************** void setVelocity(float myX_vel, float myY_vel) { x_vel = myX_vel; y_vel = myY_vel; } //***************************************************************************************** // For each object of the MovingItem class: // The following method allows us to move the obejct as a bouncing ball. //***************************************************************************************** void moveAsBouncingBall() { //************************************************************************** //Clear the canvas and Draw a ball in new position centered at (centerX, centerY): //Set the fill color to the red color, and then draw a circle with radius 20. //************************************************************************** if (visibility == true) { fill(255, 0, 255); ellipse(centerX, centerY-10, 20, 20); } //***************************************************************************************** // Update to the new position //***************************************************************************************** centerX += x_vel; centerY += y_vel; // Update the speed to show gravity //y_vel += 0.1; // Bounce off left & right wall if ((centerX<20) || (centerX> 800 -20)) { x_vel = x_vel* -1; } // Bounce off floor & ceiling if ((centerY<20) || (centerY> 800 -20)) { y_vel = y_vel * -1; } } //***************************************************************************************** // For each object of the MovingItem class: // The following method allows us to move the obejct as up and down in some . //***************************************************************************************** void moveUpDown() { //************************************************************************** //Clear the canvas and Draw a ball in new position centered at (centerX, centerY): //Set the fill color to the red color, and then draw a circle with radius 20. //************************************************************************** if (visibility == true) { fill(255, 0, 255); ellipse(centerX, centerY-10, 20, 20); } //***************************************************************************************** // Update y coordinate to the new position //***************************************************************************************** centerY += y_vel; // Bounce off floor, go up if ( (centerY> 800 -20) ) { y_vel = abs(y_vel) * -1; } // Bounce off ceiling, go down if ( centerY<20 ) { y_vel = y_vel * -1; } } //***************************************************************************************** // For each object of the MovingItem class: // The following method allows us to move the obejct right and left. //***************************************************************************************** void moveLeftRight() { //************************************************************************** //Clear the canvas and Draw a ball in new position centered at (centerX, centerY): //Set the fill color to the red color, and then draw a circle with radius 20. //************************************************************************** if (visibility == true) { fill(255, 0, 255); ellipse(centerX, centerY-10, 20, 20); } //***************************************************************************************** // Update x coordinate to the new position //***************************************************************************************** // Your code // Bounce off from the wall on the right, go left // Your code // Bounce off from the wall on the right, go right // Your code } }