EntscheidungenParteiensysteme.png

a series of small vehicles connected through strings that try to move somewhere ( and only occasionally succeed ).

processing-sketch -›

import teilchen.*;
import teilchen.behavior.*;
import teilchen.constraint.*;
import teilchen.cubicle.*;
import teilchen.force.*;
import teilchen.integration.*;
import teilchen.util.*;

Physics mPhysics;

void settings() {
  size(640, 480);
}

void setup() {
  textFont(createFont("Courier", 9));

  mPhysics = new Physics();

  Box mBox = new Box();
  mBox.min().set(50, 50);
  mBox.max().set(width - 50, height - 50);
  mPhysics.add(mBox);

  ViscousDrag myDrag = new ViscousDrag(0.25f);
  mPhysics.add(myDrag);

  PVector mCenter = new PVector().set(width / 2, height / 2);
  float mRadius = 100;
  final int NUM = 42;
  for (int i=0; i < NUM; i++) {
    Particle p = new WanderParticle();
    mPhysics.add(p);
    float r = TWO_PI * (float)i/(float)NUM;
    float x = sin(r) * mRadius;
    float y = cos(r) * mRadius;
    p.position().set(PVector.add(mCenter, new PVector().set(x, y)));
    connectNeighbor(1);
    connectNeighbor(2);
    connectNeighbor(3);   
    connectNeighbor(4);
  }
  connectNeighbor(mPhysics.particles().size()-1);
}

void connectNeighbor(int n) {
  if (mPhysics.particles().size() > n) {
    int a = mPhysics.particles().size()-(n+1);
    int b = mPhysics.particles().size()-1;
    mPhysics.makeSpring(
      mPhysics.particles().get(a), 
      mPhysics.particles().get(b));
  }
}

void draw() {
  for (Particle p : mPhysics.particles()) {
    if (p instanceof WanderParticle) {
      WanderParticle w = (WanderParticle)p;
      w.update(1.0/frameRate);
    }
  }

  /* update the particle system */
  final float mDeltaTime = 1.0f / frameRate;
  mPhysics.step(mDeltaTime);

  /* draw */
  background(255);
  fill(0);
  textAlign(LEFT);
  text("LEFT WING", 10, height/2);
  textAlign(RIGHT);
  text("RIGHT WING", width-10, height/2);
  textAlign(CENTER);
  text("SOME PARTY", width/2, height - 10);
  noFill();
  stroke(0, 64);
  drawLinePointer(mPhysics.particles().size()/2);

  /* draw particles and connecting line */
  noFill();
  stroke(255, 0, 127, 64);
  for (IForce f : mPhysics.forces()) {
    if (f instanceof Spring) {
      Spring s = (Spring)f;
      line(s.a().position().x, s.a().position().y, s.b().position().x, s.b().position().y);
    }
  }

  fill(255);
  stroke(164);
  for (Particle p : mPhysics.particles()) {
    ellipse(p.position().x, p.position().y, 7, 7);
  }
}

void drawLinePointer(int pParticlePointer) {
  PVector a = new PVector().set(width/2, height - 12);
  PVector b = new PVector().set(mPhysics.particles().get(pParticlePointer).position().x, mPhysics.particles().get(pParticlePointer).position().y);
  PVector ab = PVector.sub(b, a);
  PVector aS = new PVector().set(ab).mult(1 - 0.945).add(a);
  PVector bS = new PVector().set(ab).mult(0.945).add(a);
  line(aS.x, aS.y, bS.x, bS.y);
}

class WanderParticle extends BasicParticle {
  PVector mDirection;
  float mUpdatePeriod;
  float mUpdateCounter;

  WanderParticle() {
    mDirection = new PVector();
    reset();
  }

  void reset() {
    mDirection.set(random(-30, 30), random(-30, 30));
    PVector mDirectionAdd = new PVector().set(mDirection).normalize().mult(10);
    mDirection.add(mDirectionAdd);
    mUpdatePeriod = random(3, 10);
    mUpdateCounter = 0;
  }

  void update(float pDeltaTime) {
    mUpdateCounter += pDeltaTime;
    if (mUpdateCounter > mUpdatePeriod) {
      reset();
    }
    position().add(PVector.mult(mDirection, pDeltaTime));
  }
}

see also Swarm Unintelligence Dog Leash