/** * Data class for a flock of birds * @author Thomas Bak **/ import java.util.Vector; import java.awt.*; class Flock { Vector vBirds; Flock() { vBirds = new Vector(5, 5); Bird bTemp; Color cTemp; // Create 40 new birds (35 bl, 5 r), random positions for (int iIndex = 0; iIndex < 40; iIndex++) { //if ( Math.random() * 50 < 45 ) if (iIndex < 35) cTemp = Color.blue; else cTemp = Color.red; bTemp = new Bird( (int) (Math.random() * 300), (int) (Math.random() * 300), (int) (Math.random() * 24) * 15, cTemp ); vBirds.addElement(bTemp); } } /** * Place a new bird into the flock * @param bird The bird to add **/ void addBird( Bird bird ) { vBirds.addElement( bird ); } /** * Remove a bird from the flock * @param col The feather colors of the bird that must go **/ void removeBird( Color col ) { Bird bTemp; // Find a bird of the right color for (int i = 0; i < vBirds.size(); i++) { bTemp = (Bird) vBirds.elementAt(i); if (bTemp.getFeathers() == col) { vBirds.removeElementAt(i); i = vBirds.size(); } } } /** * Move every bird in the flock **/ public void move() { // Move each bird Bird bTemp; for (int i = 0; i < vBirds.size(); i++) { bTemp = (Bird) vBirds.elementAt(i); bTemp.move( generalHeading(bTemp) ); } } /** * Calculate the general average heading of * the birds surrounding this bird. * @param b The bird in question * @return The average theta **/ private int generalHeading(Bird b) { Point pSplotch = new Point(0,0); // The amalgamation of the birds' headings int iNumBirds=0; // The number of birds that were included // Find all of the birds less than 50 distance away Bird bTemp; for (int i = 0; i < vBirds.size(); i++) { bTemp = (Bird) vBirds.elementAt(i); // If it's close enough, add it to the average aim position if ( b.getDistance(bTemp) < 50 ) { // Follow same birds, run away from different ones if ( b.getFeathers().equals(bTemp.getFeathers()) ) { pSplotch.x += bTemp.getAim().x; pSplotch.y += bTemp.getAim().y; } else { // Collision avoidance if ( b.getAim().x < bTemp.getAim().x ) pSplotch.x = 0; else pSplotch.x = 1000; if ( b.getAim().y < bTemp.getAim().y ) pSplotch.y = 0; else pSplotch.y = 1000; iNumBirds = 0; i = 1000; } iNumBirds++; // Too close & !comparing to itself if (b.getDistance(bTemp) < 10 && !b.equals(bTemp) ){//&& b.getFeathers().equals(bTemp.getFeathers()) ) { // Tell this bird that it's too close to the others b.isTooClose(); } } } // Calc the average heading relative position pSplotch.x /= iNumBirds; pSplotch.y /= iNumBirds; // Calculate the goal theta double gah = ( (double)(b.getY() - pSplotch.y) / (double)(pSplotch.x - b.getX() ) ); int iGoalTheta = (int) (Math.atan(gah) * (180 / Math.PI)); // Fix Q2 & Q3 bug if (pSplotch.x < b.getX() ) iGoalTheta = 180 + iGoalTheta; // Fix Q4 negative theta bug if (iGoalTheta < 0) iGoalTheta = 360 + iGoalTheta; return (int)(iGoalTheta / 15) * 15; } /** * Display the entire flock **/ public void display( Graphics g ) { // Draw each bird Bird bTemp; for (int i = 0; i < vBirds.size(); i++) { bTemp = (Bird) vBirds.elementAt(i); bTemp.display(g); } } }