During my girlfriend's prom, I found it interesting how quickly everyone in a crowd of people could align to all face the same direction when a certain song came on where everyone danced in unison (like the Macerena). I figured each individual had some field of view in front of them and they were turning toward the average vector of all of the people in front of them, so I tried modeling it. My code gets some alignment, but then some strange wave pattern sweeps through the crowd and I'm not sure why.

#### dancer.java

```
```import java.awt.Polygon;
import java.awt.Rectangle;
import java.lang.reflect.Array;

public class dancer  {

double orientation;
int xposition;
int yposition;
int xBounds;
int yBounds;
int size;
Polygon fieldOfView;

public dancer(int i, int j, double orientation,int size,int xBounds, int yBounds){
this.xposition=i;
this.yposition=j;
this.orientation=orientation;
this.yBounds=yBounds;
this.xBounds=xBounds;
this.fieldOfView = new Polygon();
this.updateFieldOfView();
this.size = size;

//if statements that find points for polygon
}

public void updateFieldOfView(){
if(this.orientation>=2*Math.PI){
this.orientation-=2*Math.PI;
}

double leftSideAngle = this.orientation+Math.PI/2;
double rightSideAngle = this.orientation-Math.PI/2;
double maxAdd = 1.5*Math.sqrt((this.xBounds*this.xBounds)+(this.yBounds*this.yBounds));

int xpoints[] = new int;
int ypoints[] = new int;
//Rectangle boundsOfBox = new Rectangle(0,0,xBounds,yBounds);

double leftxPoint = this.xposition +(int)this.size/2 + maxAdd*Math.cos(leftSideAngle);
double leftyPoint = this.yposition + (int)this.size/2 +maxAdd*Math.sin(leftSideAngle);

double rightxPoint = this.xposition +(int)this.size/2 + maxAdd*Math.cos(rightSideAngle);
double rightyPoint = this.yposition +(int)this.size/2 + maxAdd*Math.sin(rightSideAngle);

double vertexx = this.xposition +(int)this.size/2 + maxAdd*Math.cos(this.orientation);
double vertexy = this.yposition +(int)this.size/2 + maxAdd*Math.sin(this.orientation);

xpoints=(int)leftxPoint;
xpoints=(int)rightxPoint;
xpoints=(int)vertexx;
ypoints=(int)leftyPoint;
ypoints=(int)rightyPoint;
ypoints=(int)vertexy;

this.fieldOfView=new Polygon(xpoints,ypoints,3);

}

public double getOrientation() {
return orientation;
}

public void setOrientation(double orientation) {
this.orientation = orientation;
}

public int getXposition() {
return xposition;
}

public void setXposition(int xposition) {
this.xposition = xposition;
}

public int getYposition() {
return yposition;
}

public void setYposition(int yposition) {
this.yposition = yposition;
}
}
```
```

#### dancers.java

```
```import java.util.Random;

//Perhaps a proximity factor could be introduced. Weight of p1's orientation on p2's orientation is inversely proportional to the distance between them.
//Or inverse square

public class dancers {
boolean drawn = false;
int numberOfDancers;
int size;
int xBounds;
int yBounds;
int speedOfTurn = 5; //higher is slower
dancer dancers[];
Random ran = new Random();
public dancers(int numberOfDancers, int size, int xBounds, int yBounds) {

this.numberOfDancers = numberOfDancers;
this.size = size;
this.dancers = new dancer[numberOfDancers];
this.xBounds = xBounds;
this.yBounds= yBounds;

for (int i = 0; i < numberOfDancers; i++) {
int xPosition = ran.nextInt(xBounds);
int yPosition = ran.nextInt(yBounds);
double orientation = 2*Math.PI*ran.nextDouble();
dancers[i] = new dancer(xPosition,yPosition,orientation,size,xBounds,yBounds);
}

}
public void spin(){
for (int i = 0; i < numberOfDancers; i++) {
dancers[i].orientation+=.1;
if(dancers[i].orientation>2*Math.PI){
dancers[i].orientation-=2*Math.PI;
}
//dancers[i].updateFieldOfView();
//System.out.println(dancers);
}
}

public void updateFieldOfView(){
for (int i = 0; i < numberOfDancers; i++) {
dancers[i].updateFieldOfView();
}
}

public void tryToAlignIncorrectButCool(){

for (int i = 0; i < numberOfDancers; i++) {

double sumOfAngles=0;
int numberOfPeopleSeen = 0;
for (int j = 0; j < numberOfDancers; j++) {
if(dancers[i].fieldOfView.contains(dancers[j].xposition, dancers[j].yposition)){
sumOfAngles+=dancers[j].orientation;
numberOfPeopleSeen++;
}
}
double angleToTendTo=(sumOfAngles)/(numberOfPeopleSeen);

if(angleToTendTo>dancers[i].orientation){
double distanceNeededToGo=angleToTendTo-dancers[i].orientation;
dancers[i].orientation+=(distanceNeededToGo/this.speedOfTurn);
}
if(angleToTendTo<dancers[i].orientation){
double distanceNeededToGo=dancers[i].orientation-angleToTendTo;
dancers[i].orientation+=(distanceNeededToGo/this.speedOfTurn);
}

}
}

public void tryToAlign() {

double orientationToChangeTo[] = new double [dancers.length];

for (int i = 0; i < numberOfDancers; i++) {

double sumOfAngles = 0;
int numberOfPeopleSeen = 0;
for (int j = 0; j < numberOfDancers; j++) {
if (dancers[i].fieldOfView.contains(dancers[j].xposition,
dancers[j].yposition)) {
sumOfAngles += dancers[j].orientation;
numberOfPeopleSeen++;
}
}
double angleToTendTo = (sumOfAngles) / (numberOfPeopleSeen);

if (angleToTendTo > dancers[i].orientation) {
double distanceNeededToGo = angleToTendTo- dancers[i].orientation;
orientationToChangeTo[i] = dancers[i].orientation + (distanceNeededToGo / this.speedOfTurn);
}
if (angleToTendTo < dancers[i].orientation) {
double distanceNeededToGo = dancers[i].orientation - angleToTendTo;
orientationToChangeTo[i] = dancers[i].orientation + (distanceNeededToGo / this.speedOfTurn);
}

}

for (int i = 0; i < numberOfDancers; i++) {
dancers[i].orientation=orientationToChangeTo[i];
}
}

}
```
```

#### player.java

```
```import java.awt.Color;
import java.awt.Graphics;

public class player extends java.applet.Applet implements Runnable {

int frame;
int delay;
int wait=100;
int increment = 1;
int displacement = 20;
int arrowLength = 13;
int halfOfArrowWidth=5;
dancers dancers = new dancers(500,10, 1000,1000);

/**
* Initialize the applet and compute the delay between frames.
*/
public void init() {

String str = getParameter("fps");
int fps = (str != null) ? Integer.parseInt(str) : 100;
delay = (fps > 0) ? (1000 / fps) : 100;
if (!dancers.drawn) {

dancers.drawn = true;
this.setSize(dancers.xBounds,dancers.yBounds);

}
}

/**
* This method is called when the applet becomes visible on the screen.
* Create a thread and start it.
*/
public void start() {
animator = new Thread(this);
animator.start();

}

/**
* This method is called by the thread that was created in the start method.
* It does the main animation.
*/
public void run() {

// Display the next frame of animation.

// Delay for a while
try {
} catch (InterruptedException e) {
break;
}

// Advance the frame
increment++;
repaint();
frame++;

}
}

/**
* This method is called when the applet is no longer visible. Set the
* animator variable to null so that the thread will exit before displaying
* the next frame.
*/
public void stop() {
animator = null;
}

/**
* Paint a frame of animation.
*/

int constantincrementor = 0;

public void paint(Graphics g) {

try {
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

//dancers.spin();
dancers.updateFieldOfView();
dancers.tryToAlign();
//dancers.tryToAlignIncorrectButCool();

//g.drawPolygon(dancers.dancers.fieldOfView);
//g.setColor(Color.yellow);
//g.drawString("Here", dancers.dancers.xposition, dancers.dancers.yposition);

if(dancers.drawn){

int a = 1;
int b = 1;
int c = 1;
int d = 1;

for (int i = 0; i < dancers.numberOfDancers; i++) {
g.fillOval(dancers.dancers[i].xposition, dancers.dancers[i].yposition, dancers.size, dancers.size);

if(dancers.dancers[i].orientation<=Math.PI/2&&dancers.dancers[i].orientation>=0){
a=-1;
b=1;
c=-1;
d=1;
}
if((dancers.dancers[i].orientation>=Math.PI/2&&dancers.dancers[i].orientation<=Math.PI)){
a=-1;
b=1;
c=-1;
d=1;
}
if((dancers.dancers[i].orientation>=Math.PI&&dancers.dancers[i].orientation<=(3*Math.PI)/2)){
a=1;
b=-1;
c=1;
d=-1;
}
if((dancers.dancers[i].orientation>=(3*Math.PI/2)&&dancers.dancers[i].orientation<=2*Math.PI)){
a=1;
b=-1;
c=1;
d=-1;
}

int[] xPoints = {(int)dancers.size/2+dancers.dancers[i].xposition+(int)(arrowLength*Math.cos(dancers.dancers[i].orientation))+(a)*(int)(halfOfArrowWidth*Math.cos(dancers.dancers[i].orientation+(Math.PI/2))),(int)dancers.size/2+dancers.dancers[i].xposition+(int)(arrowLength*Math.cos(dancers.dancers[i].orientation))+(b)*(int)(halfOfArrowWidth*Math.cos(dancers.dancers[i].orientation+(Math.PI/2))),(int)dancers.size/2+dancers.dancers[i].xposition+(int)(arrowLength*Math.cos(dancers.dancers[i].orientation))+(int)(halfOfArrowWidth*Math.cos(dancers.dancers[i].orientation))};
int[] yPoints = {(int)dancers.size/2+dancers.dancers[i].yposition+(int)(arrowLength*Math.sin(dancers.dancers[i].orientation))+(c)*(int)(halfOfArrowWidth*Math.sin(dancers.dancers[i].orientation+(Math.PI/2))),(int)dancers.size/2+dancers.dancers[i].yposition+(int)(arrowLength*Math.sin(dancers.dancers[i].orientation))+(d)*(int)(halfOfArrowWidth*Math.sin(dancers.dancers[i].orientation+(Math.PI/2))),(int)dancers.size/2+dancers.dancers[i].yposition+(int)(arrowLength*Math.sin(dancers.dancers[i].orientation))+(int)(halfOfArrowWidth*Math.sin(dancers.dancers[i].orientation))};

g.fillPolygon(xPoints, yPoints, 3);

g.drawLine(dancers.dancers[i].xposition+(int)dancers.size/2, dancers.dancers[i].yposition+(int)dancers.size/2, (int)dancers.size/2+dancers.dancers[i].xposition+(int)(arrowLength*Math.cos(dancers.dancers[i].orientation)), (int)dancers.size/2+dancers.dancers[i].yposition+(int)(arrowLength*Math.sin(dancers.dancers[i].orientation)));
}

}
}
}
```
```
```
```