/** Internal routine for generating the List of particles on collision. */
    public static ArrayList<Particle> generateParticles(Ball ball, Body body) {
      double centerX = ball.getCenter().x();
      double centerY = ball.getCenter().y();

      double speed =
          ball.getVelocity().magnitude() * ((body != null) ? (body.getRadius() / 100.0) : 1);

      if (speed < .50) speed = .50;
      if (speed > 2.50) speed = 2.50;
      if (body != null) {
        double max = Math.pow(body.getRadius() + ball.getRadius(), 2);
        while (body.getCenter().distanceSquared(new Point2d(centerX, centerY)) < max) {
          centerX -= ball.getVelocity().xComponent();
          centerY -= ball.getVelocity().yComponent();
        }
      }

      ArrayList<Particle> particles = new ArrayList<Particle>();
      int num = (int) (300 * speed);
      if (num < 150) num = 150;
      else if (num > 400) num = 400;

      for (int i = 0; i < num; i++) {
        double angle = (Math.random() * 2 * Math.PI);
        double xSpeed = 0.75 * (Math.random() * speed * Math.cos(angle));
        double ySpeed = 0.75 * (Math.random() * speed * Math.sin(angle));

        Color c;
        double rand = Math.random();
        if (body == null) c = CalcHelp.getShiftedColor(ball.getColor(), 100);
        else if (rand < 0.3) c = CalcHelp.getShiftedColor(body.getColor(), 100);
        else if (rand < 0.40) c = CalcHelp.getShiftedColor(new Color(230, 130, 70), 100);
        else c = CalcHelp.getShiftedColor(ball.getColor(), 100);

        Particle newParticle = new Particle(centerX, centerY, xSpeed, ySpeed, c);
        particles.add(newParticle);
      }

      return particles;
    }
 void testHelper(Position position, Velocity velocity, Tester stepTest) {
   DummyPhysics physics = new DummyPhysics();
   physics.createGoalpost(Direction.NORTH);
   physics.createGoalpost(Direction.SOUTH);
   Ball ball = physics.createBall();
   ball.setPosition(position);
   ball.setVelocity(velocity);
   for (int i = 0; i < 1000; i++) {
     physics.step(dt);
     stepTest.test(ball.getPosition(), ball.getVelocity());
   }
   physics.clean();
 }
  /**
   * Starts the effect.
   *
   * @param currentLevel the level the effect is taking place on
   */
  public static void start(Level currentLevel) {
    started = true;
    CollisionEffect.currentLevel = currentLevel;
    Point2d shift = currentLevel.getShift();
    Ball ball = currentLevel.getBall();
    Body intersected = currentLevel.getIntersectingBody();
    particles = Particle.generateParticles(ball, intersected);
    shakeValues = new double[6];
    double speed = ball.getVelocity().magnitude();

    if (speed < .25) speed = .25;
    if (speed > 2.5) speed = 2.5;

    double shakeFactor = 3 * speed / currentLevel.getFollowFactor();
    if (currentLevel.getFollowFactor() == 0.0) shakeFactor = .25 * speed;
    // 1st value is multiplicative factor
    int sign1 = -1;
    if (ball.getCenter().x() + shift.x() < 0) {
      sign1 = 1;
    } else if (ball.getCenter().x() + shift.x() > 0) {
      sign1 = CalcHelp.randomSign();
    }
    shakeValues[0] = CalcHelp.randomDouble(35, 40) * shakeFactor * sign1;

    int sign2 = -1;
    if (ball.getCenter().y() + shift.y() < 0) {
      sign2 = 1;
    } else if (ball.getCenter().y() + shift.y() > 0) {
      sign2 = CalcHelp.randomSign();
    }
    shakeValues[3] = CalcHelp.randomDouble(35, 40) * shakeFactor * sign2;

    // 2nd value is sinusoidal factor
    shakeValues[1] = CalcHelp.randomDouble(45, 50);
    shakeValues[4] = CalcHelp.randomDouble(45, 50);

    // 3rd value is exponential factor
    shakeValues[2] = CalcHelp.randomDouble(-.0035, -.0045);
    shakeValues[5] = CalcHelp.randomDouble(-.0035, -.0045);

    startTime = System.currentTimeMillis();
    ball.setLaunched(false);
  }