import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.text.*; import java.util.*; import java.util.zip.*; import netscape.javascript.*; import javax.comm.*; import javax.sound.midi.*; import javax.sound.midi.spi.*; import javax.sound.sampled.*; import javax.sound.sampled.spi.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.sax.*; import javax.xml.transform.stream.*; import org.xml.sax.*; import org.xml.sax.ext.*; import org.xml.sax.helpers.*; public class ManualParticleSnake extends BApplet {class RectParticle extends Particle {
public RectParticle() {}

  RectParticle(float x, float y, float z) {
    super(x, y, z);
  }

  void draw() {
    push();
    translate(pos[0], pos[1], pos[2]);
    if (fixed()) {
      stroke(0);
      fill(0xffFF0000);
    }
    else {
      stroke(100);
      fill(200, 200, 0);
    }
    box(5, 5, 5);
    pop();
  }
}

PSystem ps;

Particle a;

void setup() {
  size(400,400);
  ps = (PSystem)loadPlugin("PSystem");
  
  ps.setGravity(0);
  ps.defaultSpringStrength = .1f;
  ps.defaultSpringRestLength = 50;
  a = new RectParticle();
  a.fix();
  ps.addParticle(a);
  
  makeSpringBall(a, 50, 20);
}

float time = 0;

void loop() {
  background(0xff99CCCC);
  //translate(width/2, height/4);
  a.setPos(mouseX, mouseY, 0);
  stroke(0, 100, 0, 100);
  ps.draw();

  
  time = time+1;
}


void makeSpringBall(Particle startParticle, float size, int res) {

  float top[] = new float[3];
  float stackIncrement = TWO_PI/res;
  float rotIncrement  = TWO_PI/res;
  
  float y, angle, stackSize;
  float topAngle = 0;
  
  y = startParticle.pos[1];
  int nSlices;
  
  int nStacks = res / 2;
  Particle allInBall[][] = new Particle[nStacks][res];
    
  for (int stack = 0; stack < nStacks ; stack++) {  
    topAngle += stackIncrement;
    angle = 0;
    stackSize = abs(size*sin(topAngle));
    y = startParticle.pos[1] + size*(1 - cos(topAngle));
    if (stack == nStacks - 1) {
      nSlices = 1;
    }
    else {
      nSlices = res;
    }
    for (int slice = 0; slice < nSlices; slice++) {
      allInBall[stack][slice] = new RectParticle(stackSize*sin(angle), y, stackSize*cos(angle));
      ps.addParticle(allInBall[stack][slice]);
      angle += rotIncrement;
    }
  }
  
  for (int stack = 0; stack < nStacks - 1; stack++) {
    for (int slice = 0; slice < res; slice++) {
      ps.addSpring(allInBall[stack][slice],allInBall[stack][(slice+1)%res]);
      if (stack > 0)
        ps.addSpring(allInBall[stack][slice],allInBall[stack-1][slice]); 
    }
  }
  for (int slice = 0; slice < res; slice++) {
    ps.addSpring(startParticle,allInBall[0][slice]);
    ps.addSpring(allInBall[nStacks-2][slice],allInBall[nStacks-1][0]);
  }

}}