+++ CITIES AND MONSTERS +++

processing workshop 6, 7, 8, 9 JULY 11:00 - 18:00
IKA - akademie of fine arts 2 floor

 

This browser does not have a Java Plug-in.
Get the latest Java Plug-in here.

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();
  }

}