//***************************************************************************************** // Author: Shieu-Hong Lin, MATH/CS Deprtment, Biola University. 2018 // Permission is given to students/educators for adapting the code below. //***************************************************************************************** //***************************************************************************************** // The RigidFish class below defines the behavior of objects from the RigidFish class // such that the fisj actively moves the fins and the tail: //***************************************************************************************** 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 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 farther away // from a target point (targetX, targetY) with a rate of speed. //***************************************************************************************** void moveAwayFrom(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 //******************************************************************************************** centerX= centerX - 0.95*apprachingRate*(targetX-centerX)/distance; centerY= centerY - 0.95*apprachingRate*(targetY-centerY)/distance; //******************************************************************************************** //Reappear in (400, 400) if it goes beyond the 800 by 800 frame //******************************************************************************************** if (centerX > 800 || centerY > 800 || centerX < 0 || centerY < 0) { centerX = 400; centerY = 400; } } //***************************************************************************************** // For each object of the RigidFish class: // The following method allows us to move the fish obejct farther away // from the center of another fish. //***************************************************************************************** void moveAwayFrom(RigidFish anotherFish, float apprachingRate) { moveAwayFrom(anotherFish.centerX, anotherFish.centerY, apprachingRate); } } //************************************************************************************************ //Create three new fish objects centered at (400, 400), (430, 450), and (500, 520) respectively //************************************************************************************************ RigidFish myFish1 = new RigidFish(400, 400); RigidFish myFish2 = new RigidFish(430, 450); RigidFish myFish3 = new RigidFish(500, 520); //******************************************************************************************** //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); } //******************************************************************************************** //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. //******************************************************************************************** myFish1.drawFishHeadToward(mouseX, mouseY); myFish2.drawFishHeadToward(myFish1); myFish3.drawFishHeadToward(myFish2); //******************************************************************************************** //Move the first fish toward the mouse cursor. //******************************************************************************************** //myFish1.moveAwayFrom(mouseX, mouseY, 4); myFish1.moveToward(mouseX, mouseY, 4); //******************************************************************************************** //Move the 2nd fish toward the first fish. //******************************************************************************************** myFish2.moveToward(myFish1, 4); //******************************************************************************************** //Move the 3rd fish toward the 2nd fish. //******************************************************************************************** myFish3.moveToward(myFish2, 4); }