|
|
A crowd wandering around the "Hohe Markt" in Vienna. All they are missing is a aim! Hold "ALT" and drag the mouse to zoom. Hold "SHIFT" and drag the mouse to pan. The two classes "UMWELT" and "VIEW2D" are part of the template provided on this page "UMWELT" is based upon Aaron Steeds ai_path library. Only the main part and the class "MENSCH" will be described here. Templet has changed! Class Umwelt is now called "Nolli". a few changes where made to the class; please rever to the javadoc included with the templet. |
Built with Processing
/**
* a_collision_surrounding is a quick simulation of a mass of humans running around,
* including collision detection with other MENSCHen and an surrounding
* this sketch is based upon the provided template
* @author: Processing Workshop @ IKA 09 ika/akbild.ac.at
* @version: 1.0 web
*/
import ai.pathfinder.*;
import javax.swing.*;
Umwelt MyUmwelt;
View2D MyView;
ArrayList ArrM;
void setup() { // setup define the basic layout of your sketch
size(400,400); // set Size of the Window to 400/400
frameRate(25); // frameRate try's to call draw function 25 times / second
MyView = new View2D();
MyUmwelt = new Umwelt();
LOAD(); // in the template this function will enable you load different files
// for the web version this is replaced by a fixed path
// SCRIPT AFTER HERE // SCRIPT AFTER HERE // SCRIPT AFTER HERE // SCRIPT AFTER HERE
ArrM = new ArrayList(); // initialize the variable ArrM as ArrayList();
for (int i = 0; i < 100;i++) { // loop a 100 times
ArrM.add( new MENSCH(MyUmwelt) ); // and add 100 MENSCHen into the ArrM ArrayList();
}
}
void draw() {
background(255); // set the background to white
// WIRTE YOUR CODE HERE TO RENDER TO SCREEN // WIRTE YOUR CODE HERE TO RENDER TO SCREEN
MyView.TRANSFORM_VIEW();
MyUmwelt.RENDER();
// WRITE YOUR CODE HERE TO RENDER TO MODEL // WRITE YOUR CODE HERE TO RENDER TO MODEL
MENSCH M; // Define a variable M of the class MENSCH
for (int i =0; i < ArrM.size();i++){ // cycle through all MENSCHen stored in the ArrayList arrM
M = (MENSCH) ArrM.get(i); // get the i'th MENSCH an cast it into the variable M
M.Update(ArrM,MyUmwelt); // call the Update(ArrayList,Umwelt) Method of the Class MENSCH
M.Render(); // call the Render() Method of the Class MENSCH
}
MyView.RENDER();
}
public void mouseDragged() {
MyView.UPDATE();
}
public void keyReleased() {
MyView.STOP();
}
public void keyPressed() {
MyView.SET();
}
public void LOAD() {
XMLElement tempXML = new XMLElement(this,"Wien_neuerMarkt.xml");
MyUmwelt = new Umwelt(tempXML,35);
MyView.RESCALE (MyUmwelt.BBmax,MyUmwelt.BBmin);
}
/**
* MENSCH is a class for www.processing.org
* MENSCH will simulate a human running around
* @author: Processing Workshop @ IKA 09 ika/akbild.ac.at
* @version: 1.2
*/
class MENSCH {
PVector PVPos, PVDir; // PVPos = current Position, PVDir = current Motion
float Size; // Size = personal space of each Human
final float MaxSpeed = 0.3; // MaxSpeed = 0.3 m/s
final float View = 4.0; // View = 4.0 m; View defines the influence area of the solid void collision
MENSCH(Umwelt TempU) {
this.Size = random(.5,1); // define a personal space between
// .5 and 1 Meters
this.PVPos = new PVector( random(TempU.BBmin[0],TempU.BBmax[0]),random(TempU.BBmin[1],TempU.BBmax[1]) ); // position MENSCH somewhere into the Umwelt
while (TempU.INSIDE(int(this.PVPos.x),int(this.PVPos.y)) ){ // while position of MENSCH is inside a wall do
this.PVPos = new PVector( random(TempU.BBmin[0],TempU.BBmax[0]),random(TempU.BBmin[1],TempU.BBmax[1]) ); // position MENSCH somewhere into the Umwelt
}
this.PVDir = new PVector( random(-.2,.2),random(-.2,.2) ); // create a random Motion
}
void Update(ArrayList ArrTemp,Umwelt TempU) { // if the method void is called ask for an ArrayList
//
containing all other humans and a Umwelt
//
containing the walls
float TempF;
PVector TempV;
MENSCH TempM;
// collision detection with Surrounding
PVector[] TempView = new PVector[3]; // The TempView Array will store 3 Vectors
TempView[0] = new PVector(this.PVDir.x,this.PVDir.y); // TempView[0] is straight ahead
TempView[1] = new PVector(-this.PVDir.y,this.PVDir.x); // 90º right
TempView[1] = PVector.add(TempView[1],TempView[0]); // TempView[1] is 45º left
TempView[2] = new PVector(this.PVDir.y,-this.PVDir.x); // 90º right
TempView[2] = PVector.add(TempView[2],TempView[0]); // TempView[2] is 45º right
// these are the directions we are looking for a collision
// with a wall and if so redirect the MENSCH
for (int ii = 0; ii < 3;ii++){ // cycle through all TempView Vectors
TempView[ii].normalize(); // scale the Vector to length: 1
TempView[ii].mult(this.View); // rescale the Vector to the length of the View
for (float i = this.View;i >0;i-=1) { // look every meter; if you imagine a city
//
every meter will be enough
// if you do the collision detection for a building
// with walls thinner then a meter a
//
smaller number the 1 will be necessary
TempV = new PVector(TempView[ii].x,TempView[ii].y); // copy the current TempView Vector into TempV
TempV.limit(i); // limit TempV to the current distance i
TempV.add(this.PVPos); // get the position
if (TempU.INSIDE(int(TempV.x),int(TempV.y)) ) { // if this position is inside a wall:
TempView[ii].limit(i); // limit the current TempView to this distance
}
}
} // now the TempView vectors contain the
//
maximum walking distances
// straight ahead, to the left,
// to the right before the MENSCH hits a wall;
//
based upon these distances the MENSCH will
// change it's path;
pushStyle(); // display settings for collision detection display
stroke(197,252,18);
strokeWeight(2);
noFill();
if (TempView[0].mag() < this.Size) { // if standing next to a wall then:
this.PVDir = new PVector(0,0); // set movement to 0;
ellipse(this.PVPos.x,this.PVPos.y,this.Size,this.Size); // display collision detection to screen
}
else if (TempView[1].mag() > TempView[0].mag() && TempView[1].mag() > TempView[2].mag() ) { // else if there is the most space to your left:
line(this.PVPos.x,this.PVPos.y,this.PVPos.x+TempView[1].x,this.PVPos.y+TempView[1].y); // display collision detection to screen
TempView[1].normalize(); // scale the Vector to length: 1
this.PVDir.add(TempView[1]); // add deviation to the movement direction so
//
that the MENSCHen avoids the wall
this.PVDir.limit(this.PVDir.mag()-1); // limit the length of the vector so that MENSCH
//
keeps it's speed
}
else if (TempView[2].mag() > TempView[0].mag() && TempView[2].mag() > TempView[1].mag() ) { // else if there is the most space to your right:
line(this.PVPos.x,this.PVPos.y,this.PVPos.x+TempView[2].x,this.PVPos.y+TempView[2].y); // display collision detection to screen
TempView[2].normalize(); // scale the Vector to length: 1
this.PVDir.add(TempView[2]); // add deviation to the movement direction so that
//
the MENSCHen avoids the wall
this.PVDir.limit(this.PVDir.mag()-1); // limit the length of the vector so that
//
MENSCH keeps it's speed
}
// collision detection with other MENSCHen
for (int i = 0; i < ArrTemp.size();i++){ // cycle through all MENSCHen stored in ArrTemp
TempM = (MENSCH) ArrTemp.get(i); // get the i'th MENSCH to compare
TempV = PVector.add(this.PVPos,this.PVDir); // get the future position of this MENSCH
TempF = TempV.dist(TempM.PVPos); // calculate the distance between the future
//
position of this MENSCH and the other MENSCH
if (TempF < this.Size + TempM.Size && ArrTemp.indexOf(this) != i) { // if the distance between the future
//
position if this MENSCH and the other MENSCH is to small
// and it is not himself
TempV = PVector.sub(TempV,TempM.PVPos); // get the Vector from the other MENSCH
//
to the future position of this MENSCH
TempV.limit((this.Size+TempM.Size)-TempF); // limits the length so that the deviation is a minimum
this.PVDir.add(TempV); // add deviation to the movement direction so
//
that the two MENSCHen do not collide
ellipse(this.PVPos.x,this.PVPos.y,this.Size,this.Size); // display collision detection to screen
}
}
popStyle();
this.PVDir.limit(MaxSpeed); // limits the speed of the current Motion
this.PVPos.add(this.PVDir); // adds the current Motion to the Position
this.PVDir.add( new PVector( random(-.05,.05),random(-.05,.05) ) ); // changes the current Motion a little bit
this.PVDir.limit(MaxSpeed); // limits the speed of the current Motion
}
/** call to display the human on the screen
*/
void Render() {
pushStyle();
fill(0);
ellipse(this.PVPos.x,this.PVPos.y,.1,.1);
noFill();
stroke(120);
ellipse(this.PVPos.x,this.PVPos.y,this.Size,this.Size);
stroke(247,5,167);
line(this.PVPos.x,this.PVPos.y,this.PVPos.x+this.PVDir.x*10,this.PVPos.y+this.PVDir.y*10);
popStyle();
}
}