public class ForceCircle_opt extends ForceCircle implements Freezable {
	protected boolean alive = true;
	protected boolean frozen;
	protected boolean collide = true;
	protected boolean responsive = true;

	public ForceCircle_opt(double x, double y, double radius, double mass){
		this(x, y, 0, 0, radius, mass, 1);
	}
	
	public ForceCircle_opt(double x, double y, double vx, double vy, double radius, double mass){
		this(x, y, vx, vy, radius, mass, 1);
	}
	public ForceCircle_opt(double x, double y, double vx, double vy, double radius, double mass, double restitution){
		this(x, y, vx, vy, radius, mass, restitution, true);
	}
	public ForceCircle_opt(double x, double y, double vx, double vy, double radius, double mass, double restitution,
			boolean collide){
		this(x, y, vx, vy, radius, mass, restitution, collide, false);
	}
	public ForceCircle_opt(double x, double y, double vx, double vy, double radius, double mass, double restitution,
			boolean collide, boolean frozen){
		super(x, y, vx, vy, radius, mass, restitution);
		this.collide = collide;
		this.frozen = frozen;
		ends = new LinkedList<Constraint>();
	}
	public ForceCircle_opt(double x, double y, double angle, double force, double radius, double mass,
			double restitution, boolean collide, boolean frozen, boolean polar){
		super(x, y, angle, force, radius, mass, restitution, polar);
		this.collide = collide;
		this.frozen = frozen;
		ends = new LinkedList<Constraint>();
	}
	public boolean isFrozen(){
		return frozen;
	}
	public double getRestitution(Object o){
		return restitution;
	}
	public void setFrozen(boolean frozen){
		this.frozen = frozen;
	}
	public boolean isCollide(Object o){
		return collide;
	}
	public boolean isResponsive(Object o){
		return responsive;
	}
	public void setCollide(boolean collide){
		this.collide = collide;
	}
	public void setResponsive(boolean responsive){
		this.responsive = responsive;
	}
	public boolean isAlive(){
		return alive;
	}
	public void setAlive(boolean alive){
		this.alive = alive;
	}
	public Vector responsiveAcceleration(PointVector pv, double t, Point b){
		Vector v = super.responsiveAcceleration(pv, t, b);
		
		if (b instanceof Gel) {
			Gel c = (Gel) b;
			Vector r = new RectVector(x - c.getX(), y - c.getY());
			
			// taken from http://www.plunk.org/~trina/thesis/html/thesis_toc.html
			double w = Gel.W(r.getLength(), this.radius);
			if (w > 0) {
				Vector f = r.getUnitVector().scale(w * 500 * radiussq);
				if (b instanceof Gel)
					f.scale(8 / ((Gel) b).getMass());
				v.add(f);
			}
			if(CircleMath.checkcirclecollide(this, c))
				v.add(new RectVector(-.1 * pv.getvx(), -.1 * pv.getvy()));
		}
		
		Constraint c;
		for(ListIterator<Constraint> i = ends.listIterator(); i.hasNext(); ){
			c = i.next();
			if(c.end == b){
				Vector r = VectorMath.getVector(b, pv);
				double x = c.distance - r.getLength();
				
				if (java.lang.Double.isInfinite(x) || java.lang.Double.isNaN(x))
					x = 0;
				if (x > 100)
					x = 100;
				else if (x < -100)
					x = -100;
				
				Vector unit = r.getUnitVector();
				v.add(unit.scale(-x * .95));
				// not quite sure what this is for (drag?)
				// v.add(unit.scale(-VectorMath.dotproduct(pv, r) * .0001));
				
				// instantaneous angular velocity
				/*double l = VectorMath.crossproduct(unit, pv);
				
				if (java.lang.Double.isInfinite(l) || java.lang.Double.isNaN(l))
					l = 0;
				
				if (l > 100)
					l = 100;
				else if (l < -100)
					l = -100;
				
				if (l > 0)
					v.add(new RectVector(unit.getvy(), -unit.getvx()).scale(Math.abs(l) * .1));
				else if(l < 0)
					v.add(new RectVector(-unit.getvy(), unit.getvx()).scale(Math.abs(l) * .1));*/
			}
		}

		return v;
	}
	
	public class Constraint {
		public Point end;
		public double distance;
		
		private Constraint(Point end, double distance){
			this.end = end;
			this.distance = distance;
		}

	}
	
	private LinkedList<Constraint> ends;

	public void addEnd(Point end, double distance) {
		ends.add(new Constraint(end, distance));
	}

	public LinkedList<Constraint> getEnds() {
		return ends;
	}
	
} public class ForceCircle_opt_color extends ForceCircle_opt implements Colored {
	private Color color;

	public ForceCircle_opt_color(double x, double y, double vx, double vy, double radius, double mass, Color color){
		super(x, y, vx, vy, radius, mass);
		this.color = color;
	}

	public ForceCircle_opt_color(double x, double y, double vx, double vy, double radius, double mass,
			double restitution, Color color){
		super(x, y, vx, vy, radius, mass, restitution);
		this.color = color;
	}

	public ForceCircle_opt_color(double x, double y, double vx, double vy, double radius, double mass,
			double restitution, boolean collide, Color color){
		super(x, y, vx, vy, radius, mass, restitution, collide);
		this.color = color;
	}

	public ForceCircle_opt_color(double x, double y, double angle, double force, double radius, double mass,
			double restitution, boolean collide, Color color, boolean polar){
		super(x, y, angle, force, radius, mass, restitution, collide, false, polar);
		this.color = color;
	}
	
	public Color getColor(){
		return color;
	}

	public void setColor(Color color){
		this.color = color;
	}
	
	@Override
	public boolean isCollide(Object o) {
		if (o instanceof Accelerator)
			return false;
		if (o instanceof Boundaries || o instanceof StaticLine || o instanceof StaticCircle)
			return true;
		return super.isCollide(o);
	}

} public class Gel extends ForceCircle implements Colored {
	public static final Color color = new Color(26, 141, 240, 100);
	
	public Gel(double x, double y, double vx, double vy, double radius,
			double mass, double restitution) {
		super(x, y, vx, vy, radius, mass, restitution);
	}

	@Override
	public boolean isCollide(Object o) {
		if (o instanceof ForceCircle)
			return false;
		return true;
	}

	public boolean isResponsive(Object o) {
		return true;
	}

	public Vector responsiveAcceleration(PointVector pv, double t, Point b) {
		Vector v = super.responsiveAcceleration(pv, t, b);

		if (b instanceof Circle) {
			Circle c = (Circle) b;
			Vector r = new RectVector(x - c.getX(), y - c.getY());
			
			// taken from http://www.plunk.org/~trina/thesis/html/thesis_toc.html
			double w = W(r.getLength(), this.radius);
			if (w > 0) {
				Vector f = r.getUnitVector().scale(w * 500 * radiussq);
				if (b instanceof Gel)
					f.scale(8 / ((Gel) b).getMass());
				if (b instanceof ForceCircle)
					f.scale(4 / ((ForceCircle) b).getMass());
				v.add(f);
			}
			if(CircleMath.checkcirclecollide(this, c))
				v.add(new RectVector(-.1 * pv.getvx(), -.1 * pv.getvy()));
		}

		return v;
	}

	// taken from http://www.plunk.org/~trina/thesis/html/thesis_toc.html
	public static final double W(double dist, double radius) {
		double c = 1 / (Math.PI * radius * radius * radius);
		double q = dist / radius;

		if (q > 0 && q <= 1) {
			return c * (1 + 3 / 2 * q * q + 3 / 4 * q * q * q);
		} else if (q > 1 && q <= 2) {
			return c * (1 / 4 * (2 - q) * (2 - q) * (2 - q));
		}
		return 0;
	}

	@Override
	public Color getColor() {
		return color;
	}
} public class Mover extends StaticCircle implements Accelerator {
	private boolean alive;
	private int direction;
	
	public Mover(double x, double y, double power, int direction) {
		super(x, y, power);
		alive = true;
		this.direction = direction;
	}

	@Override
	public Vector accelerate(Force f, PointVector pv, double t) {
		if (f instanceof Circle && CircleMath.checkcirclecollide(this, ((Circle)f)))
			return RectVector.ZERO;
		return PhysicsMath.inverseSquaredAttraction(-radius * radius * 250 * direction, this, pv);
	}
	
	public boolean isCollide(Object o){
		return false;
	}
	
	public boolean isResponsive(Object o){
		return true;
	}
	
	public void setAlive(boolean alive){
		this.alive = alive;
	}
	
	public boolean isAlive(){
		return alive;
	}

	public void setDirection(int direction) {
		this.direction = direction;
	}
} public class Particle extends ForceCircle implements Colored, Living {
	protected Color color;
	protected double age;

	public Particle(double x, double y, double angle, double magnitude,
			double radius, double mass, double restitution, int life,
			Color color, boolean polar) {
		super(x, y, magnitude * Math.cos(angle), magnitude * Math.sin(angle),
				radius, mass, restitution);
		this.age = life;
		this.color = color;
	}

	public Particle(double x, double y, double vx, double vy, double radius,
			double mass, int life, Color color) {
		super(x, y, vx, vy, radius, mass);
		this.age = life;
		this.color = color;
	}

	@Override
	public void age(double time) {
		age -= time;
	}

	@Override
	public Color getColor() {
		return color;
	}

	@Override
	public double getRestitution(Object o) {
		return super.getRestitution(o);
	}

	@Override
	public boolean isAlive() {
		return age > 0;
	}

	@Override
	public boolean isCollide(Object o) {
		return !(o instanceof Vector) || o instanceof Boundaries;
	}

	@Override
	public void setAge(double age) {
		this.age = age;
	}

	public void setColor(Color color) {
		this.color = color;
	}
} public class Pusher extends StaticCircle implements Accelerator, Painter {
	public static final Color color = new Color(255, 125, 125);

	private Vector direction;

	public Pusher(double x, double y, double radius, double angle) {
		super(x, y, radius);
		direction = new RectVector(Math.cos(angle), Math.sin(angle));
	}
	
	public Pusher(double x, double y, double radius, double vx, double vy) {
		super(x, y, radius);
		direction = new RectVector(vx, vy).getUnitVector();
	}
	
	public Vector getDirection(){
		return direction;
	}
	
	public boolean isCollide(Object o){
		return false;
	}

	@Override
	public Vector accelerate(Force f, PointVector pv, double t) {
		if (f instanceof Circle
				&& CircleMath.checkcirclecollide(this, ((Circle) f))){
			Vector v = new RectVector(direction);
			return v.scale(this.distance(pv) * radius / 50 / f.getMass());
		}
		return RectVector.ZERO;
	}

	@Override
	public void paint(Graphics2D g) {
		g.setColor(new Color(255, 125, 125));
		g.fill(new Ellipse2D.Double(getX() - getRadius(), getY() - getRadius(), 2 * getRadius(), 2 * getRadius()));
		
		g.setColor(new Color(255, 45, 15));
		g.draw(new Line2D.Double(getX(), getY(), getX() + getRadius()*getDirection().getvx(), getY() + getRadius()*getDirection().getvy()));
		Vector right = VectorMath.rotate(getDirection(), Math.PI/10);
		g.draw(new Line2D.Double(getX() + getRadius()*getDirection().getvx(), getY() + getRadius()*getDirection().getvy(),
				getX() + .8*getRadius()*right.getvx(), getY() + .8*getRadius()*right.getvy()));
		Vector left = VectorMath.rotate(getDirection(), -Math.PI/10);
		g.draw(new Line2D.Double(getX() + getRadius()*getDirection().getvx(), getY() + getRadius()*getDirection().getvy(),
				getX() + .8*getRadius()*left.getvx(), getY() + .8*getRadius()*left.getvy()));
	}

} public class Constraint {
	public Point end;
	public double distance;
		
	private Constraint(Point end, double distance){
		this.end = end;
		this.distance = distance;
	}

} public interface Freezable {
	public void setFrozen(boolean frozen);
	public boolean isFrozen();
} public interface Colored {
	public Color getColor();
} public class Renderer {
	public List<ForceCircle> forceCircles;
	public List<StaticCircle> staticCircles;
	public List<StaticLine> staticLines;

	public Color defaultColor = Color.gray;

	public Renderer(List<ForceCircle> forceCircles,
			List<StaticCircle> staticCircles, List<StaticLine> staticLines) {
		this.forceCircles = forceCircles;
		this.staticCircles = staticCircles;
		this.staticLines = staticLines;
	}

	public void render(Graphics2D g) {
		for (StaticCircle sc : staticCircles) {
			render(g, sc);
		}
		for (StaticLine l : staticLines) {
			render(g, l);
		}
		for (ForceCircle fc : forceCircles) {
			render(g, (Circle)fc);
		}
	}
	
	public void render(Graphics2D g, Circle c){
		if (c instanceof Painter)
			((Painter) c).paint(g);
		else {
			if (c instanceof Colored)
				g.setColor(((Colored) c).getColor());
			else
				g.setColor(defaultColor);
			g.fill(new Ellipse2D.Double(c.getMinX(), c.getMinY(), c
					.getWidth(), c.getHeight()));
		}
	}
	
	public void render(Graphics2D g, Line l){
		if (l instanceof Painter)
			((Painter) l).paint(g);
		else {
			if (l instanceof Colored)
				g.setColor(((Colored) l).getColor());
			else
				g.setColor(defaultColor);
			g.draw(new Line2D.Double(l.getX1(), l.getY1(), l.getX2(), l
					.getY2()));
		}
	}
} public abstract class AbstractAction implements Action {

	@Override
	public void act(int action, InputEvent event) {

	}

} public interface Action {
	public static final int PRESSED = 1;
	public static final int TYPED = 2;
	public static final int RELEASED = 3;
	public static final int HELD = 4;
	/**
	 * Triggers this action to act.
	 * 
	 * @param action The action that was performed.
	 * @param event The event that triggered this action.
	 * @see InputEvent
	 * @see KeyEvent
	 * @see MouseEvent
	 * @see MouseWheelEvent
	 */
	public void act(int action, InputEvent event);
} public class HoldState implements Action, BiState {
	public boolean state;

	public HoldState() {
		state = false;
	}

	public HoldState(boolean initalState) {
		state = initalState;
	}

	@Override
	public void act(int action, InputEvent event) {
		if (action == Action.PRESSED)
			state = true;
		else if (action == Action.RELEASED)
			state = false;
	}

	@Override
	public boolean getState() {
		return state;
	}

	@Override
	public void setState(boolean state) {
		this.state = state;
	}

} public class InputBind implements MouseListener, MouseMotionListener,
		MouseWheelListener, KeyListener {
	public Map<Integer, String> mouseWheelMap;
	public Map<Integer, String> mouseMap;
	public Map<Integer, String> keyMap;
	public Map<String, Action> actionMap;
	// current
	public int x;
	public int y;

	public InputBind() {
		this(new HashMap<Integer, String>(), new HashMap<Integer, String>(),
				new HashMap<Integer, String>(), new HashMap<String, Action>());
	}

	public InputBind(Map<Integer, String> mouseMap,
			Map<Integer, String> mouseWheelMap, Map<Integer, String> keyMap,
			Map<String, Action> actionMap) {
		this.mouseMap = mouseMap;
		this.mouseWheelMap = mouseWheelMap;
		this.keyMap = keyMap;
		this.actionMap = actionMap;
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (keyMap.containsKey(e.getKeyCode()))
			actionMap.get(keyMap.get(e.getKeyCode())).act(Action.PRESSED, e);
	}

	@Override
	public void keyReleased(KeyEvent e) {
		if (keyMap.containsKey(e.getKeyCode()))
			actionMap.get(keyMap.get(e.getKeyCode())).act(Action.RELEASED, e);
	}

	@Override
	public void keyTyped(KeyEvent e) {
		if (keyMap.containsKey(e.getKeyCode()))
			actionMap.get(keyMap.get(e.getKeyCode())).act(Action.TYPED, e);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		x = e.getX();
		y = e.getY();
		if (mouseMap.containsKey(e.getButton()))
			actionMap.get(mouseMap.get(e.getButton())).act(Action.TYPED, e);
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
		x = e.getX();
		y = e.getY();
		if (mouseMap.containsKey(e.getButton()))
			actionMap.get(mouseMap.get(e.getButton())).act(Action.PRESSED, e);
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		x = e.getX();
		y = e.getY();
		if (mouseMap.containsKey(e.getButton()))
			actionMap.get(mouseMap.get(e.getButton())).act(Action.RELEASED, e);
	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		x = e.getX();
		y = e.getY();

		if (mouseWheelMap.containsKey((int) Math.signum(e.getWheelRotation()))) {
			for (int i = 0; i < Math.abs(e.getWheelRotation()); i++) {
				actionMap.get(
						mouseWheelMap.get((int) Math.signum(e
								.getWheelRotation()))).act(Action.PRESSED, e);
			}
			actionMap.get(
					mouseWheelMap.get((int) Math.signum(e.getWheelRotation())))
					.act(Action.RELEASED, e);
			actionMap.get(
					mouseWheelMap.get((int) Math.signum(e.getWheelRotation())))
					.act(Action.TYPED, e);
		} else if (mouseWheelMap.containsKey(e.getButton())) {
			actionMap.get(mouseWheelMap.get(e.getButton())).act(Action.PRESSED,
					e);
			actionMap.get(mouseWheelMap.get(e.getButton())).act(
					Action.RELEASED, e);
			actionMap.get(mouseWheelMap.get(e.getButton())).act(
					Action.TYPED, e);
		}

	}

	public void addMouseWheelAction(Integer button, String name, Action action) {
		mouseWheelMap.put(button, name);
		actionMap.put(name, action);
	}

	public void addMouseAction(Integer button, String name, Action action) {
		mouseMap.put(button, name);
		actionMap.put(name, action);
	}

	public void addKeyAction(Integer key, String name, Action action) {
		keyMap.put(key, name);
		actionMap.put(name, action);
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		x = e.getX();
		y = e.getY();
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		x = e.getX();
		y = e.getY();
	}

} public class SetState implements Action, BiState {
	public boolean state;

	@Override
	public void act(int action, InputEvent event) {
		if (action == Action.PRESSED)
			state = true;
	}

	@Override
	public void setState(boolean state) {
		this.state = state;
	}

	@Override
	public boolean getState() {
		return state;
	}

} public class ToggleState implements Action, BiState {
	public boolean state;
	
	public ToggleState(){
		state = false;
	}
	
	public ToggleState(boolean initalState){
		state = initalState;
	}
	
	@Override
	public void act(int action, InputEvent event) {
		if(action == Action.PRESSED)
			state = !state;
	}

	@Override
	public boolean getState() {
		return state;
	}

	@Override
	public void setState(boolean state) {
		this.state = state;
	}

} public class VectorMath {
	public static final Vector add(Vector v, Vector u) {
		return new RectVector(v.getvx() + u.getvx(), v.getvy() + u.getvy());
	}
	public static final Vector subtract(Vector v, Vector u) {
		return new RectVector(v.getvx() - u.getvx(), v.getvy() - u.getvy());
	}
	/**
	 * Computes the length of a vector.
	 * 
	 * @param vx The x component of the vector.
	 * @param vy The y component of the vector.
	 * @return The length of the vector.
	 */
	public static final double length(double vx, double vy){
		return Point.distance(0, 0, vx, vy);
	}
	/**
	 * Computes the dot product of two vectors.
	 * 
	 * @param u A <code>Vector</code>.
	 * @param v Another <code>Vector</code>.
	 * @return The dot product <b>u</b> and <b>v</b>.
	 */
	public static final double dotproduct(Vector u, Vector v){
		return dotproduct(u.getvx(), u.getvy(), v.getvx(), v.getvy());
	}
	/**
	 * Computes the dot product of two vectors.
	 * 
	 * @param vx1 The x component of the first vector.
	 * @param vy1 The y component of the first vector.
	 * @param vx2 The x component of the second vector.
	 * @param vy2 The y component of the second vector.
	 * @return The dot product of two vectors.
	 */
	public static final double dotproduct(double vx1, double vy1, double vx2, double vy2){
		return vx1 * vx2 + vy1 * vy2;
	}
	/**
	 * Computes the cosine of the smaller angle between the two vectors. Formula is <br>
	 * dotproduct(u, v)/|u||v|
	 * 
	 * @param u A <code>Vector</code>.
	 * @param v Another <code>Vector</code>.
	 * @return The cosine of the smaller angle between <b>u</b> and <b>v</b>.
	 */
	public static final double cosproj(Vector u, Vector v){
		return dotproduct(u, v) / (u.getLength() * v.getLength());
	}
	/**
	 * Computes the cosine of the smaller angle between the two vectors. Formula is <br>
	 * dotproduct(u, v)/|u||v|
	 * 
	 * @param vx1 The x component of the first vector.
	 * @param vy1 The y component of the first vector.
	 * @param vx2 The x component of the second vector.
	 * @param vy2 The y component of the second vector.
	 * @return The cosine of the smaller angle between the two vectors.
	 */
	public static final double cosproj(double vx1, double vy1, double vx2, double vy2){
		return dotproduct(vx1, vy1, vx2, vy2) / (length(vx1, vy1) * length(vx2, vy2));
	}
	/**
	 * Computes the angle between the two vectors. Uses dot product.
	 * 
	 * @param u A <code>Vector</code>.
	 * @param v Another <code>Vector</code>.
	 * @return The angle between <b>u</b> and <b>v</b>.
	 */
	public static final double anglebetween(Vector u, Vector v){
		return Math.acos(cosproj(u, v));
	}
	/**
	 * Computes the angle between the two vectors. Uses dot product.
	 * 
	 * @param vx1 The x component of the first vector.
	 * @param vy1 The y component of the first vector.
	 * @param vx2 The x component of the second vector.
	 * @param vy2 The y component of the second vector.
	 * @return The angle between the two vectors.
	 */
	public static final double anglebetween(double vx1, double vy1, double vx2, double vy2){
		return Math.acos(cosproj(vx1, vy1, vx2, vy2));
	}
	/**
	 * Computes the cross product of two 2-dimensional vectors.
	 * 
	 * @param u A <code>Vector</code>.
	 * @param v Another <code>Vector</code>.
	 * @return The cross product of <b>u</b> and <b>v</b>.
	 */
	public static final double crossproduct(Vector u, Vector v){
		return crossproduct(u.getvx(), u.getvy(), v.getvx(), v.getvy());
	}
	/**
	 * Computes the cross product of two 2-dimensional vectors.
	 * 
	 * @param vx1 The x component of the first vector.
	 * @param vy1 The y component of the first vector.
	 * @param vx2 The x component of the second vector.
	 * @param vy2 The y component of the second vector.
	 * @return Yhe cross product of two 2-dimensional vectors.
	 */
	public static final double crossproduct(double vx1, double vy1, double vx2, double vy2){
		return vx1 * vy2 - vy1 * vx2;
	}
	/**
	 * Computes the sine of the smaller angle between the two vectors. Formula is <br>
	 * crossproduct(u, v)/|u||v|
	 * 
	 * @param u A <code>Vector</code>.
	 * @param v Another <code>Vector</code>.
	 * @return The sine of the smaller angle between <b>u</b> and <b>v</b>.
	 */
	public static final double sinproj(Vector u, Vector v){
		return crossproduct(u, v) / (u.getLength() * v.getLength());
	}
	/**
	 * Computes the sine of the smaller angle between the two vectors. Formula is <br>
	 * crossproduct(u, v)/|u||v|
	 * 
	 * @param vx1 The x component of the first vector.
	 * @param vy1 The y component of the first vector.
	 * @param vx2 The x component of the second vector.
	 * @param vy2 The y component of the second vector.
	 * @return The sine of the smaller angle between the two vectors.
	 */
	public static final double sinproj(double vx1, double vy1, double vx2, double vy2){
		return crossproduct(vx1, vy1, vx2, vy2) / (length(vx1, vy1) * length(vx2, vy2));
	}
	
	public static final boolean equaldirection(double x1, double y1, double x2, double y2, double x3, double y3, double v1len, double v2len){
		//1 = common point between the two vectors
		//2 = where vector 1 points to
		//3 = where vector 2 points to
		//v1len = length of vector from 1 to 2
		//v2len = length of vetor from 1 to 3
		if(x1-x2 != 0 || y1-y2 != 0){ // check to make sure that x2 and y2 goes somewhere 
			double cos = (((x1-x2)*(x1-x3)+(y1-y2)*(y1-y3))/ (Math.abs(v1len)*Math.abs(v2len)));
			if(cos > .995 && cos <= 1) return true;
			else return false;
		}else return true;
	}
	public static final boolean equaldirection(double x1, double y1, double x2, double y2, double x3, double y3, double v1len, double v2len, double range){
		//range is how close the vector has to be to the other vector
		//0.999 would be basically equivalent to the other vector
		//-.999 would be 180 degrees
		//0 would be perpendicular
		if(x1-x2 != 0 || y1-y2 != 0){ // check to make sure that x2 and y2 goes somewhere 
			double cos = (((x1-x2)*(x1-x3)+(y1-y2)*(y1-y3))/ (Math.abs(v1len)*Math.abs(v2len)));
			if(cos > range && cos <= 1) return true;
			else return false;
		}else return true;
	}
	public static final boolean equaldirection(double vx1, double vy1, double vx2, double vy2, double v1len, double v2len, double range){
		//range is how close the vector has to be to the other vector
		//0.999 would be basically equivalent to the other vector
		//-.999 would be 180 degrees
		//0 would be perpendicular
		if(vx1 != 0 || vy1 != 0){ // check to make sure that x2 and y2 goes somewhere 
			double cos = (((vx1)*(vx2)+(vy1)*(vy2))/ (Math.abs(v1len)*Math.abs(v2len)));
			if(cos > range && cos <= 1) return true;
			else return false;
		}else return true;
	}
	public static final boolean equaldirection(double angle1, double angle2, double range){
		if(angle1 > Math.PI*2) angle1 -= Math.PI*2;
		else if(angle1 < 0) angle1 += Math.PI*2;
		if(angle2 > Math.PI*2) angle2 -= Math.PI*2;
		else if(angle2 < 0) angle2 += Math.PI*2;
		if(Math.abs(angle1-angle2) < range) return true;
		return false;
	}
	
	/**
     * Finds the shortest distance between a line and a point.
     * @param x1 The x value of the first point of the line.
     * @param y1 The y value of the first point of the line.
     * @param lx1 The x value of the second point of the line.
     * @param ly1 The y value of the second point of the line.
     * @param lx2 The x value of the point.
     * @param ly2 The y value of the point.
     * @return The shortest distance between a line and a point.
     */
    public static final double linepointdistance(double x1, double y1, double lx1, double ly1, double lx2, double ly2){
		Point p = closestpointonline(x1, y1, lx1, ly1, lx2, ly2);
		return (double)Point.distance(lx2, ly2, p.getX(), p.getY());
	}
    /**
     * gives you the shortest distance squared between a line and a point
     * @param x1 the x value of the first point of the line
     * @param y1 the y value of the first point of the line
     * @param x2 the x value of the second point of the line
     * @param y2 the y value of the second point of the line
     * @param x3 the x value of the point
     * @param y3 the y value of the point
     * @return the shortest distance squared between a line and a point
     */
    public static final double linepointdistancesq(double x1, double y1, double x2, double y2, double x3, double y3){
    	double A1 = (y2 - y1);
    	double B1 = (x1 - x2);
    	double C1 = (y2 - y1)*x1 + (x1 - x2)*y1;
    	double C2 = -B1*x3 + A1*y3;
    	double det = (A1*A1 - (-B1*B1));
    	double cx = 0;
    	double cy = 0;
    	if(det != 0){
	    	cx = (A1*C1 - B1*C2)/det;
	    	cy = (A1*C2 - -B1*C1)/det;
    	}
    	return Math.abs((cx-x3)*(cx-x3)+(cy-y3)*(cy-y3));
    }
    
    public static final Point closestpointonline(StaticLine l, Point p){
    	return closestpointonline(l.getX(), l.getY(), l.getX2(), l.getY2(), p.getX(), p.getY());
    }
    
	/**
	 * Finds a point on the given line closest to the given point.
	 * 
	 * @param lx1
	 *            The x value of the first point of the line.
	 * @param ly1
	 *            The y value of the first point of the line.
	 * @param lx2
	 *            The x value of the second point of the line.
	 * @param ly2
	 *            The y value of the second point of the line.
	 * @param x0
	 *            The x value of the point.
	 * @param y0
	 *            The y value of the point.
	 * @return A <code>Point</code> with the coordinates of the point on the
	 *         line closest to the given point.
	 */
	public static final Point closestpointonline(double lx1, double ly1,
			double lx2, double ly2, double x0, double y0) {
		double A1 = (ly2 - ly1);
		double B1 = (lx1 - lx2);
		double C1 = (ly2 - ly1) * lx1 + (lx1 - lx2) * ly1;
		double C2 = -B1 * x0 + A1 * y0;
		double det = (A1 * A1 - (-B1 * B1));
		double cx = 0;
		double cy = 0;
		if (det != 0) {
			cx = (double) ((A1 * C1 - B1 * C2) / det);
			cy = (double) ((A1 * C2 - -B1 * C1) / det);
		} else {
			cx = x0;
			cy = y0;
		}
		return new Point(cx, cy);
	}
	
	/**
	 * Gets the {@link Vector} from the <code>tail</code> {@link Point} to the <code>head</code> point.
	 * @param head the end of the <code>Vector</code>
	 * @param tail the beginning of the <code>Vector</code>
	 * @return the {@link Vector} from the <code>tail</code> to the <code>head</code>.
	 */
	public static final Vector getVector(Point head, Point tail){
		return new RectVector(head.getX() - tail.getX(), head.getY() - tail.getY());
	}
	
	/**
	 * Rotates a vector without changing it.
	 * 
	 * @param v
	 *            the vector to be rotated
	 * @param angle
	 *            the angle to rotate by
	 * @return The rotated vector.
	 */
	public static final Vector rotate(Vector v, double angle) {
		return new RectVector(v.getvx() * Math.cos(angle) - v.getvy()
				* Math.sin(angle), v.getvx() * Math.sin(angle) + v.getvy()
				* Math.cos(angle));
	}
} public interface Circle extends Rect {
	/**
	 * (double) getRadius
	 * 
	 * @return the radius
	 */
	public double getRadius();

	/**
	 * (double) getRadius
	 * 
	 * @return the radius squared (radius^2)
	 */
	public double getRadiusSq();


	/**
	 * Sets the radius of the circle.
	 * 
	 * @param radius
	 *            The new radius of this circle.
	 */
	public void setRadius(double radius);

} public class Force extends PointVector implements Vector {
	protected double length;
	protected double mass;
	protected double restitution = 1; // maybe i should put this in _opt
	
	public Force(double x, double y, double mass){
		this(x, y, 0, 0, mass, 1);
	}
	
	public Force(double x, double y, double vx, double vy, double mass){
		this(x, y, vx, vy, mass, 1);
	}

	/**
	 * Creates a {@link Force} object.
	 * 
	 * @param x
	 *            The x component of the location.
	 * @param y
	 *            The y component of the location.
	 * @param vx
	 *            The x component of the velocity.
	 * @param vy
	 *            The y component of the velcotiy.
	 * @param mass
	 *            The mass of the object.
	 * @param restitution
	 *            The % energy left after a collision.
	 */
	public Force(double x, double y, double vx, double vy, double mass,
			double restitution) {
		super(x, y, vx, vy);
		this.length = VectorMath.length(vx, vy); // distance formula
		this.mass = mass;
		if (restitution > 1)
			restitution = 1;
		else if (restitution < 0)
			restitution = 0;
		this.restitution = restitution;
	}

	public Force(double x, double y, double angle, double force, double mass,
			double restitution, boolean polar) {
		this(x, y, force * Math.cos(angle), force * Math.sin(angle), mass,
				restitution);
	}

	public Force(Force f) {
		super(f);
		this.length = f.getLength();
		this.mass = f.getMass();
		this.restitution = f.getRestitution(f);
	}

	public Force(Point p, Vector v, double mass) {
		super(p, v);
		this.length = v.getLength();
		this.mass = mass;
	}

	public Force(PointVector pv, double mass) {
		super(pv);
		this.length = pv.getLength();
	}

	/**
	 * The acceleration of this {@link Force}.
	 * 
	 * @param pv
	 *            the current position of this object
	 * @param t
	 *            the time interval
	 * @return This object's acceleration.
	 */
	public Vector getAcceleration(PointVector pv, double t) {
		return new RectVector(0, 0);
	}

	public int compareTo(Force o) {
		if (this.length > o.length)
			return -1;
		else if (this.length < o.length)
			return 1;
		else
			return 0;
	}

	@Override
	public double getLength() {
		return length;
	}

	public double getMass() {
		return mass;
	}

	public double getnormvx() {
		if (this.length > 0)
			return this.vx / this.length;
		else
			return 0;
	}

	public double getnormvy() {
		if (this.length > 0)
			return this.vy / this.length;
		else
			return 0;
	}

	@Override
	public double getRestitution(Object o) {
		return restitution;
	}

	/**
	 * Acceleration on this {@link Force} that depends <code>b</code>.
	 * 
	 * @param pv
	 *            The current point being integrated.
	 * @param t
	 *            The time interval.
	 * @param b
	 *            The force that is being compared to.
	 * @return The acceleration on this object that is dependent on
	 *         <code>b</code>.
	 */
	public Vector responsiveAcceleration(PointVector pv, double t, Point b) {
		return new RectVector(0, 0);
	}
	
	@Override
	public Vector scale(double scalar) {
		this.vx *= scalar;
		this.vy *= scalar;
		this.length *= scalar;
		
		return this;
	}

	public void setMass(double mass) {
		this.mass = mass;
	}

	@Override
	public void setPointVector(PointVector v) {
		this.x = v.getX();
		this.y = v.getY();
		if (!this.isFrozen()) {
			if (this.vx != v.getvx() || this.vy != v.getvy()) {
				this.vx = v.getvx();
				this.vy = v.getvy();
				this.length = VectorMath.length(vx, vy);
			}
		}
	}
	
	@Override
	public void setRect(double vx, double vy){
		this.vx = vx;
		this.vy = vy;
		this.length = VectorMath.length(vx, vy);
	}

	public void setRestitution(double restitution) {
		if (restitution > 1)
			restitution = 1;
		else if (restitution < 0)
			restitution = 0;
		this.restitution = restitution;
	}

	@Override
	public void setVector(Vector v) {
		setRect(v.getvx(), v.getvy());
	}

	@Override
	public void setvx(double vx) {
		this.vx = vx;
		this.length = VectorMath.length(vx, vy);
	}

	@Override
	public void setvy(double vy) {
		this.vy = vy;
		this.length = VectorMath.length(vx, vy);
	}

	@Override
	public String toString() {
		return super.toString() + "; F = " + this.length + "; m = " + this.mass
				+ "; Cr = " + this.restitution;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		long temp;
		temp = java.lang.Double.doubleToLongBits(length);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		temp = java.lang.Double.doubleToLongBits(mass);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		temp = java.lang.Double.doubleToLongBits(restitution);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		Force other = (Force) obj;
		if (java.lang.Double.doubleToLongBits(length) != java.lang.Double
				.doubleToLongBits(other.length))
			return false;
		if (java.lang.Double.doubleToLongBits(mass) != java.lang.Double
				.doubleToLongBits(other.mass))
			return false;
		if (java.lang.Double.doubleToLongBits(restitution) != java.lang.Double
				.doubleToLongBits(other.restitution))
			return false;
		return true;
	}

} public class ForceCircle extends Force implements Circle {
	protected double radius;
	protected double radiussq; // probably won't dump but not all that useful to keep

	/**
	 * Creates a <code>ForceCircle</code> at (<code>x</code>, <code>y</code>) with the specified mass and radius. Vector
	 * components are set to 0 (no movement).
	 * 
	 * @param x The x value.
	 * @param y The y value.
	 * @param radius The radius of the circle.
	 * @param mass The mass of the circle.
	 */
	public ForceCircle(double x, double y, double radius, double mass){
		this(x, y, 0, 0, radius, mass);
	}
	/**
	 * Creates a <code>ForceCircle</code> at (<code>x</code>, <code>y</code>) with vector components &#60<code>vx</code>
	 * , <code>vy</code>&#62 and the specified mass and radius.
	 * 
	 * @param x The x value.
	 * @param y The y value.
	 * @param vx The horizontal vector component.
	 * @param vy The vertical vector component.
	 * @param radius The radius of the circle.
	 * @param mass The mass of the circle.
	 */
	public ForceCircle(double x, double y, double vx, double vy, double radius, double mass){
		this(x, y, vx, vy, radius, mass, 1);
	}
	/**
	 * Creates a <code>ForceCircle</code> at (<code>x</code>, <code>y</code>) with vector components &#60<code>vx</code>
	 * , <code>vy</code>&#62 and the specified mass and radius.
	 * 
	 * @param x The x value.
	 * @param y The y value.
	 * @param vx The horizontal vector component.
	 * @param vy The vertical vector component.
	 * @param radius The radius of the circle.
	 * @param mass The mass of the circle.
	 */
	public ForceCircle(double x, double y, double vx, double vy, double radius, double mass, boolean polar){
		this(x, y, vx, vy, radius, mass, 1);
	}
	public ForceCircle(double x, double y, double vx, double vy, double radius, double mass, double restitution){
		super(x, y, vx, vy, mass, restitution);
		this.radius = radius;
		this.radiussq = radius * radius;
	}
	public ForceCircle(double x, double y, double vx, double vy, double radius, double mass, double restitution, boolean polar){
		super(x, y, vx, vy, mass, restitution, polar);
		this.radius = radius;
		this.radiussq = radius * radius;
	}

	public ForceCircle(Force f, double radius){
		super(f);
		this.setRadius(radius);
	}
	public ForceCircle(ForceCircle f){
		super(f);
		this.radius = f.getRadius();
		this.radiussq = f.getRadiusSq();
	}
	public ForceCircle(Point p, Vector v, double radius, double mass){
		super(p, v, mass);
		this.setRadius(radius);
	}
	public ForceCircle(PointVector v, double radius, double mass){
		super(v, mass);
		this.setRadius(radius);
	}

	@Override
	public boolean equals(Object obj){
		if(this == obj)
			return true;
		if(!super.equals(obj))
			return false;
		if(getClass() != obj.getClass())
			return false;
		ForceCircle other = (ForceCircle)obj;
		if(java.lang.Double.doubleToLongBits(radius) != java.lang.Double.doubleToLongBits(other.radius))
			return false;
		return true;
	}
	@Override
	public double getRadius(){
		return radius;
	}
	@Override
	public double getRadiusSq(){
		return radiussq;
	}
	@Override
	public int hashCode(){
		final int prime = 31;
		int result = super.hashCode();
		result = (int)(prime * result + java.lang.Double.doubleToLongBits(radius));
		return result;
	}
	@Override
	public void setRadius(double radius){
		if(radius > 0){
			this.radius = radius;
			this.radiussq = radius * radius;
		}
	}
	@Override
	public double getMaxX() {
		return x + radius;
	}
	@Override
	public double getMaxY() {
		return y + radius;
	}
	@Override
	public double getMinX() {
		return x - radius;
	}
	@Override
	public double getMinY() {
		return y - radius;
	}
	@Override
	public double getHeight() {
		return 2 * radius;
	}
	@Override
	public double getWidth() {
		return 2 * radius;
	}
	@Override
	public void setHeight(double height) {
		setRadius(height / 2);
	}
	@Override
	public void setWidth(double width) {
		setRadius(width / 2);
	}
} public class Point {
	
	protected double x, y;
	
	/**
	 * Finds the midpoint between two points, in rectangular coordinates.
	 * 
	 * @param x1 The x value of the first point.
	 * @param y1 The y value of the first point.
	 * @param x2 The x value of the second point.
	 * @param y2 The y value of the second point.
	 * @return A <code>Point</code> with the coordinates of the midpoint of (x1, y1) and (x2, y2).
	 */
	public static final Point midpoint(double x1, double y1, double x2, double y2){
		return new Point(((x1 + x2) / 2), ((y1 + y2) / 2));
	}
	/**
	 * Finds the midpoint between two points.
	 * 
	 * @param p1 The first <code>Point</code>.
	 * @param p2 The second <code>Point</code>.
	 * @return The midpoint between <b>p1</b> and <b>p2</b>.
	 */
	public static final Point midpoint(Point p1, Point p2){
		return midpoint(p1.getX(), p1.getY(), p2.getX(), p2.getY());
	}
	
	/**
	 * Constructs a Point with the coordinates (0, 0).
	 */
	public Point(){
		x = 0;
		y = 0;
	}
	/**
	 * Constructs a Point with specified x and y values.
	 * 
	 * @param x The x value.
	 * @param y The y value.
	 */
	public Point(double x, double y){
		if(java.lang.Double.isNaN(x) || java.lang.Double.isInfinite(x))
			x = 0;
		if(java.lang.Double.isNaN(y) || java.lang.Double.isInfinite(y))
			y = 0;
		this.x = x;
		this.y = y;
	}
	public Point(Point p){
		this(p.getX(), p.getY());
	}
	/**
	 * Contstructs a <code>Point</code>, given a <code>Vector</code>. It takes the endpoint of the head of the vector if
	 * the tail of the vector is at (0, 0).
	 * 
	 * @param v The vector to be used.
	 */
	public Point(Vector v){
		this(v.getvx(), v.getvy());
	}

	@Override
	public boolean equals(Object obj){
		if(this == obj)
			return true;
		if(obj == null)
			return false;
		if(getClass() != obj.getClass())
			return false;
		Point other = (Point)obj;
		if(java.lang.Double.doubleToLongBits(x) != java.lang.Double.doubleToLongBits(other.x))
			return false;
		if(java.lang.Double.doubleToLongBits(y) != java.lang.Double.doubleToLongBits(other.y))
			return false;
		return true;
	}
	/**
	 * Return's this object's location (included to match Point2D).
	 * 
	 * @return This object.
	 */
	public Point getLocation(){
		return this;
	}

	/**
	 * Returns the (1 - ) coefficient of restitution between this object and another object.
	 * <code>a.getRestitution(b)</code> does not necessarily have to equal <code>b.getRestitution(a)</code>, but the
	 * coefficient of restitution for <code>a</code> is determined by <code>a.getRestitution(b)</code> to avoid casting
	 * b. Default is 1.
	 * 
	 * @param o The <code>Object</code> to be checked against.
	 * @return The coefficient of restitution between this object and <b>o</b> if this object collides into <b>o</b>.
	 */
	public double getRestitution(Object o){
		return 1;
	}

	public double getX(){
		return x;
	}
	public double getY(){
		return y;
	}
	public Point getPoint(){
		return this;
	}
	@Override
	public int hashCode(){
		final int prime = 31;
		int result = 1;
		result = (int)(prime * result + java.lang.Double.doubleToLongBits(x));
		result = (int)(prime * result + java.lang.Double.doubleToLongBits(y));
		return result;
	}
	
	/**
	 * @return Whether or not this {@link Point} is alive.
	 */
	public boolean isAlive() {
		return true;
	}

	/**
	 * Checks if this object collides with another object. Default is <code>true</code>. <code>a.isCollide(b)</code> and
	 * <code>b.isCollide(a)</code> must be <code>true</code> for collision checking to go through.
	 * 
	 * @param o The <code>Object</code> to be checked against.
	 * @return Whether or not this object collides with <b>o</b>.
	 */
	public boolean isCollide(Object o){
		return true;
	}
	/**
	 * Checks if this object responds to collision with another object. Should not return <code>true</code> if
	 * <code>isCollide(<b>o</b>)</code> returns <code>false</code>. Default is <code>true</code>.
	 * <code>a.isResponsive(b)</code> does not have to equal <code>b.isResponsive(a)</code>, but the reaction of
	 * <code>a</code> depends on the value of <code>a.isResponsive(b)</code>.
	 * 
	 * @param o The <code>Object</code> to be checked against.
	 * @return Whether or not this object responds to <b>o</b>.
	 */
	public boolean isResponsive(Object o){
		return isCollide(o);
	}

	/**
	 * Converts the X and Y values into doubles and sets both of the X and Y values in one function.
	 * 
	 * @param x the new x value
	 * @param y the new y value
	 */
	public void setPoint(double x, double y){
		this.x = x;
		this.y = y;
	}
	/**
	 * Changes the x and y coordinates of this point to match those of the argument.
	 * 
	 * @param p The new coordinates.
	 */
	public void setPoint(Point p){
		this.x = p.getX();
		this.y = p.getY();
	}
	public void setX(double x){
		this.x = x;
	}
	public void setY(double y){
		this.y = y;
	}
	@Override
	public String toString(){
		return String.format("(%4.8f, %4.8f)", this.x, this.y);
	}
	public Point translate(double dx, double dy){
		setPoint(x + dx, y + dy);
		return this;
	}
	public Point translate(Vector v){
		return translate(v.getvx(), v.getvy());
	}
	
	/**
     * Returns the square of the distance between two points.
     *
     * @param x1 the X coordinate of the first specified point
     * @param y1 the Y coordinate of the first specified point
     * @param x2 the X coordinate of the second specified point
     * @param y2 the Y coordinate of the second specified point
     * @return the square of the distance between the two
     * sets of specified coordinates.
     * @since 1.2
     */
    public static double distanceSq(double x1, double y1,
                                    double x2, double y2)
    {
        x1 -= x2;
        y1 -= y2;
        return (x1 * x1 + y1 * y1);
    }

    /**
     * Returns the distance between two points.
     *
     * @param x1 the X coordinate of the first specified point
     * @param y1 the Y coordinate of the first specified point
     * @param x2 the X coordinate of the second specified point
     * @param y2 the Y coordinate of the second specified point
     * @return the distance between the two sets of specified
     * coordinates.
     * @since 1.2
     */
    public static double distance(double x1, double y1,
                                  double x2, double y2)
    {
        x1 -= x2;
        y1 -= y2;
        return Math.sqrt(x1 * x1 + y1 * y1);
    }

    /**
     * Returns the square of the distance from this
     * <code>Point2D</code> to a specified point.
     *
     * @param px the X coordinate of the specified point to be measured
     *           against this <code>Point2D</code>
     * @param py the Y coordinate of the specified point to be measured
     *           against this <code>Point2D</code>
     * @return the square of the distance between this
     * <code>Point2D</code> and the specified point.
     * @since 1.2
     */
    public double distanceSq(double px, double py) {
        px -= getX();
        py -= getY();
        return (px * px + py * py);
    }

    /**
     * Returns the square of the distance from this
     * <code>Point2D</code> to a specified <code>Point2D</code>.
     *
     * @param pt the specified point to be measured
     *           against this <code>Point2D</code>
     * @return the square of the distance between this
     * <code>Point2D</code> to a specified <code>Point2D</code>.
     * @since 1.2
     */
    public double distanceSq(Point pt) {
        double px = pt.getX() - this.getX();
        double py = pt.getY() - this.getY();
        return (px * px + py * py);
    }

    /**
     * Returns the distance from this <code>Point2D</code> to
     * a specified point.
     *
     * @param px the X coordinate of the specified point to be measured
     *           against this <code>Point2D</code>
     * @param py the Y coordinate of the specified point to be measured
     *           against this <code>Point2D</code>
     * @return the distance between this <code>Point2D</code>
     * and a specified point.
     * @since 1.2
     */
    public double distance(double px, double py) {
        px -= getX();
        py -= getY();
        return Math.sqrt(px * px + py * py);
    }

    /**
     * Returns the distance from this <code>Point2D</code> to a
     * specified <code>Point2D</code>.
     *
     * @param pt the specified point to be measured
     *           against this <code>Point2D</code>
     * @return the distance between this <code>Point2D</code> and
     * the specified <code>Point2D</code>.
     * @since 1.2
     */
    public double distance(Point pt) {
        double px = pt.getX() - this.getX();
        double py = pt.getY() - this.getY();
        return Math.sqrt(px * px + py * py);
    }
} public class PointVector extends Point implements Vector, Line {
	protected double vx = 0;
	protected double vy = 0;
	
	public PointVector(){
		this(0, 0);
	}

	public PointVector(double x, double y) {
		this(x, y, 0, 0);
	}

	public PointVector(double x, double y, double vx, double vy) {
		super(x, y);
		this.vx = vx;
		this.vy = vy;
	}

	public PointVector(Point p) {
		this(p.getX(), p.getY(), 0, 0);
	}

	public PointVector(Point p, Vector v) {
		this(p.getX(), p.getY(), v.getvx(), v.getvy());
	}

	public PointVector(PointVector pv) {
		this(pv.getX(), pv.getY(), pv.getvx(), pv.getvy());
	}

	public PointVector(Vector v) {
		this(0, 0, v.getvx(), v.getvy());
	}

	@Override
	public PointVector add(Vector v) {
		setRect(getvx() + v.getvx(), getvy() + v.getvy());
		return this;
	}

	@Override
	public double dot(Vector v) {
		return getvx() * v.getvx() + getvy() * v.getvy();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		PointVector other = (PointVector) obj;
		if (java.lang.Double.doubleToLongBits(x) != java.lang.Double.doubleToLongBits(other.x))
			return false;
		if (java.lang.Double.doubleToLongBits(y) != java.lang.Double.doubleToLongBits(other.y))
			return false;
		if (java.lang.Double.doubleToLongBits(vx) != java.lang.Double.doubleToLongBits(other.vx))
			return false;
		if (java.lang.Double.doubleToLongBits(vy) != java.lang.Double.doubleToLongBits(other.vy))
			return false;
		return true;
	}

	@Override
	public double getAngle() {
		return Math.atan2(this.vy, this.vx);
	}

	@Override
	public Rect getBounds() {
		return StaticRect.fromUpperLeft((int)Math.min(getX1(), getX2()), (int)Math.min(getY1(), getY2()), (int)Math.max(getX1(), getX2()), (int)Math.max(getY1(), getY2()));
	}

	@Override
	public double getLength() {
		return VectorMath.length(vx, vy);
	}
	
	@Override
	public Point getP1() {
		return new Point(getX1(), getY1());
	}

	@Override
	public Point getP2() {
		return new Point(getX2(), getY2());
	}

	@Override
	public Vector getUnitVector() {
		double length = getLength();
		return new RectVector(getvx() / length, getvy() / length);
	}

	/**
	 * Returns the vector components.
	 * 
	 * @return The vector components of this <code>PointVector</code>.
	 */
	public Vector getVector() {
		return new RectVector(this.vx, this.vy);
	}

	@Override
	public double getvx() {
		return vx;
	}

	@Override
	public double getvy() {
		return vy;
	}

	@Override
	public double getX1() {
		return x;
	}

	@Override
	public double getX2() {
		return x + vx;
	}

	@Override
	public double getY1() {
		return y;
	}

	@Override
	public double getY2() {
		return y + vy;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = (int) (prime * result + java.lang.Double.doubleToLongBits(vx));
		result = (int) (prime * result + java.lang.Double.doubleToLongBits(vy));
		return result;
	}

	/**
	 * Checks if this object is frozen (immobile or static).
	 * 
	 * @return Whether or not this object is frozen.
	 */
	public boolean isFrozen() {
		return false;
	}

	@Override
	public Vector rotate(double angle) {
		setRect(getvx() * Math.cos(angle) - getvy() * Math.sin(angle), getvx()
				* Math.sin(angle) + getvy() * Math.cos(angle));
		return this;
	}
	@Override
	public Vector scale(double scalar) {
		this.vx *= scalar;
		this.vy *= scalar;
		
		return this;
	}

	@Override
	public void setAngle(double angle) {
		double length = getLength();
		this.vx = length * Math.cos(angle);
		this.vy = length * Math.sin(angle);
	}

	@Override
	public void setLength(double length) {
		double origlen = getLength();
		setRect((length * (getvx() / origlen)), (length * (getvy() / origlen)));
	}

	@Override
	public void setLine(double x1, double y1, double x2, double y2) {
		x = x1;
		y = y1;
		vx = x2 - x1;
		vy = y2 - y1;
	}

	public void setPointVector(PointVector v) {
		this.x = v.getX();
		this.y = v.getY();
		this.vx = v.getvx();
		this.vy = v.getvy();
	}

	@Override
	public void setPolar(double angle, double length) {
		setRect(length * Math.cos(angle), length * Math.sin(angle));
	}

	@Override
	public void setRect(double vx, double vy) {
		this.vx = vx;
		this.vy = vy;
	}

	@Override
	public void setVector(Vector v) {
		this.vx = v.getvx();
		this.vy = v.getvy();
	}

	@Override
	public void setvx(double vx) {
		this.vx = vx;
	}

	@Override
	public void setvy(double vy) {
		this.vy = vy;
	}

	@Override
	public Vector subtract(Vector v) {
		setRect(getvx() - v.getvx(), getvy() - v.getvy());
		return this;
	}
	
	public PointVector translate(Vector v){
		translate(v.getvx(), v.getvy());
		return this;
	}

	@Override
	public String toString() {
		return super.toString() + String.format("\t<%4.8f, %4.8f>", this.vx, this.vy);
	}
} public class RectVector extends AbstractVector implements Vector {

	public static final RectVector ZERO = new RectVector(0, 0);

	private double vx;
	private double vy;

	public RectVector(double vx, double vy) {
		this.vx = vx;
		this.vy = vy;
	}

	public RectVector(Vector v) {
		setVector(v);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		RectVector other = (RectVector) obj;
		if (Double.doubleToLongBits(vx) != Double.doubleToLongBits(other.vx))
			return false;
		if (Double.doubleToLongBits(vy) != Double.doubleToLongBits(other.vy))
			return false;
		return true;
	}

	@Override
	public double getvx() {
		return this.vx;
	}

	@Override
	public double getvy() {
		return this.vy;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		long result = 1;
		result = prime * result + Double.doubleToLongBits(vx);
		result = prime * result + Double.doubleToLongBits(vy);
		return (int) result;
	}

	public void setRect(double vx, double vy) {
		this.vx = vx;
		this.vy = vy;
	}

	@Override
	public void setVector(Vector v) {
		this.vx = v.getvx();
		this.vy = v.getvy();
	}

	@Override
	public void setvx(double vx) {
		this.vx = vx;
	}

	@Override
	public void setvy(double vy) {
		this.vy = vy;
	}

	@Override
	public String toString() {
		return "RectVector <" + vx + ", " + vy + ">";
	}
} public class StaticCircle extends Point implements Circle {
	protected double radius;
	protected double radiussq;

	public StaticCircle(double x, double y, double radius){
		super(x, y);
		this.radius = radius;
		this.radiussq = radius * radius;
	}
	public StaticCircle(Point p, double radius){
		super(p);
		setRadius(radius);
	}
	@Override
	public boolean equals(Object obj){
		if(this == obj)
			return true;
		if(!super.equals(obj))
			return false;
		if(getClass() != obj.getClass())
			return false;
		StaticCircle other = (StaticCircle)obj;
		if(java.lang.Double.doubleToLongBits(radius) != java.lang.Double.doubleToLongBits(other.radius))
			return false;
		return true;
	}
	@Override
	public Rect getBounds() {
		return StaticRect.fromUpperLeft((int)(x - radius), (int)(y - radius), (int)(2 * radius), (int)(2 * radius));
	}

	@Override
	public double getMaxX() {
		return x + radius;
	}
	@Override
	public double getMaxY() {
		return y + radius;
	}

	@Override
	public double getMinX() {
		return x - radius;
	}
	@Override
	public double getMinY() {
		return y - radius;
	}
	@Override
	public double getRadius(){
		return radius;
	}
	@Override
	public double getRadiusSq(){
		return radiussq;
	}
	@Override
	public int hashCode(){
		final int prime = 31;
		int result = super.hashCode();
		result = (int)(prime * result + java.lang.Double.doubleToLongBits(radius));
		return result;
	}
	@Override
	public void setRadius(double radius){
		radius = Math.abs(radius);
		this.radius = radius;
		this.radiussq = radius * radius;
	}
	@Override
	public String toString(){
		return "(" + this.x + ", " + this.y + "); r = " + this.radius;
	}
	@Override
	public double getHeight() {
		return 2 * radius;
	}
	@Override
	public double getWidth() {
		return 2 * radius;
	}
	@Override
	public void setHeight(double height) {
		setRadius(height / 2);
	}
	@Override
	public void setWidth(double width) {
		setRadius(width / 2);
	}
} public class StaticLine extends Point implements Line {
	private double x2, y2;

	public StaticLine(double x1, double y1, double x2, double y2) {
		super(x1, y1);
		this.x2 = x2;
		this.y2 = y2;
	}

	public Point getClosestPointOnLine(double x, double y) {
		return VectorMath.closestpointonline(this.getX1(), this.getY1(),
				this.getX2(), this.getY2(), x, y);
	}

	public Point getClosestPointOnLine(Point p) {
		return VectorMath.closestpointonline(this, p);
	}

	@Override
	public Rect getBounds() {
		return StaticRect.fromUpperLeft((int) Math.min(getX1(), getX2()), (int) Math.min(getY1(), getY2()), (int) Math.max(getX1(), getX2()),
				(int) Math.max(getY1(), getY2()));
	}

	@Override
	public Point getP1() {
		return new Point(getX1(), getY1());
	}

	@Override
	public Point getP2() {
		return new Point(getX2(), getY2());
	}

	@Override
	public double getX1() {
		return x;
	}

	@Override
	public double getX2() {
		return x2;
	}

	@Override
	public double getY1() {
		return y;
	}

	@Override
	public double getY2() {
		return y2;
	}

	@Override
	public void setLine(double x1, double y1, double x2, double y2) {
		x = x1;
		y = y1;
		this.x2 = x2;
		this.y2 = y2;
	}
} public interface Vector {
	/**
	 * Adds a vector to this vector.
	 * 
	 * @param v
	 *            The vector to be added.
	 * 
	 * @return The resultant vector.
	 */
	public Vector add(Vector v);

	/**
	 * Takes the dot product of this vector with another vector.
	 * 
	 * @param v
	 *            The vector to be multiplied.
	 * @return The resultant vector.
	 */
	public double dot(Vector v);

	/**
	 * Returns the angle of the x and y components when translating to polar
	 * coordinates.
	 * 
	 * @return The angle of the x and y components.
	 */
	public double getAngle();

	/**
	 * Gets the length of the <code>Vector</code>.
	 * 
	 * @return The length of the <code>Vector</code>.
	 */
	public double getLength();

	/**
	 * Gets the normal vector.
	 * 
	 * @return The normal vector.
	 */
	public Vector getUnitVector();

	/**
	 * Gets the x component.
	 * 
	 * @return The x component.
	 */
	public double getvx();

	/**
	 * Gets the y component.
	 * 
	 * @return The y component.
	 */
	public double getvy();

	/**
	 * Scales this vector.
	 * 
	 * @param scalar
	 *            The scalar to multiply this vector by.
	 * 
	 * @return The resultant vector.
	 */
	public Vector scale(double scalar);

	/**
	 * Subtracts the given vector from this vector.
	 * 
	 * @param v
	 *            The vector to subtract.
	 * @return The resultant vector.
	 */
	public Vector subtract(Vector v);

	/**
	 * Rotates this vector.
	 * 
	 * @param angle
	 *            The angle to rotate this vector by.
	 * @return The rotated vector.
	 */
	public Vector rotate(double angle);

	/**
	 * Sets the angle (in radians).
	 * 
	 * @param angle
	 *            The new angle (in radians).
	 */
	public void setAngle(double angle);

	/**
	 * Sets the length.
	 * 
	 * @param length
	 *            The new length.
	 */
	public void setLength(double length);

	/**
	 * Sets the values of this {@link Vector} to the given polar coordinates.
	 * 
	 * @param angle
	 *            The angle of the new vector.
	 * @param length
	 *            The length of the new vector.
	 */
	public void setPolar(double angle, double length);

	/**
	 * Sets the values of this {@link Vector} to the given rectangular
	 * coordinates.
	 * 
	 * @param vx
	 *            The x component of the new vector.
	 * @param vy
	 *            The y component of the new vector.
	 */
	public void setRect(double vx, double vy);

	/**
	 * Sets the values of this <code>Vector</code> to the values of another
	 * <code>Vector</code>. Does not guarantee equality.
	 * 
	 * @param v
	 *            The new values for this <code>Vector</code>.
	 */
	public void setVector(Vector v);

	/**
	 * Sets the x component.
	 * 
	 * @param vx
	 *            The new x component.
	 */
	public void setvx(double vx);

	/**
	 * Sets the y component.
	 * 
	 * @param vy
	 *            The new y component.
	 */
	public void setvy(double vy);
} public class PhysicsEngine implements Accelerator {
	
	//list of forces
	public ArrayList<ForceCircle> ForceCircles;
	
	//lines
	public ArrayList<StaticLine> Lines;
	//static circles... mainly for collision stuff that never moves
	public ArrayList<StaticCircle> StaticCircles;
	
//these are reference variables - checked but not changed
	
	private double time, deltaTime;
	
	private byte boundDetection;
	private byte boundResponse;
	private Rect bounds;
	
	private Integrator integrator;
	
//these variables are meant for the engine and not to be modified by externally except through generalforce
	
	public static final byte BOUNDS_DETECT_INSIDE = 1;
	public static final byte BOUNDS_DETECT_MIDDLE = 0;
	public static final byte BOUNDS_DETECT_OUTSIDE = -1;
	
	public static final byte BOUNDS_RESPOND_NONE = 0;
	public static final byte BOUNDS_RESPOND_BOUNCE = 1;
	
	/** started summer '07

	 * <feature list>
	 * - unlimited number of objects
	 * - moving all objec2ts in a certain direction
	 * - different types of boundaries
	 * - obj-obj collision
	 * - obj-obj gravity
	 * - //lines & line-obj collsion
	 * - static objects (circles) useful for maps
	 * - trigger objects (circles) useful to tell if an object is where the user is supposed to get it
	 * - explosions (outward and directed)
	 * - moving trigger objects
	 * - collision selectiveness (pass the object you are checking collision with)
	 * <in the future>
	 *  restructure program for more efficency
	 *  support for bullets (some of the functions are already there)
	 *  double matrix collision reducer [grid system] so fewer calculations are done for collisions
	 *  line-line collsion detection, i need to differentiate between static/moving lines
	 *  polygons and bounding circles for polygons
	 *  
	 */
	
	/**
	 * Creates a new {@link PhysicsEngine} with the specified width and height.
	 */
	public PhysicsEngine(int width, int height){
		this(new StaticRect(width / 2, height / 2, width, height), BOUNDS_DETECT_INSIDE, BOUNDS_RESPOND_BOUNCE);
	}
	
	public PhysicsEngine(Rect bounds, byte boundDetection, byte boundResponse){
		this(new ArrayList<ForceCircle>(), new ArrayList<StaticLine>(), new ArrayList<StaticCircle>(), bounds, boundDetection, boundResponse);
	}
	
	public PhysicsEngine(ArrayList<ForceCircle> ForceCircles, ArrayList<StaticLine> Lines, ArrayList<StaticCircle> StaticCircles, Rect bounds, byte boundDetection, byte boundResponse){
		this.ForceCircles = ForceCircles;
		this.Lines = Lines;
		this.StaticCircles = StaticCircles;
		
		this.bounds = bounds;
		this.boundDetection = boundDetection;
		this.boundResponse = boundResponse;
		
		this.integrator = new RK4Integrator();
		
		time = 1;
		deltaTime = .5;
	}
	
	public String toString(){
		return "Force Engine: by Eric Leong";
	}
	
	public static final double getVersion(){ //returns the version number
		return 2;
	}

	
	
	/**
	 * Main method of <code>PhysicsEngine</code>, takes each of the forcecircles and adjusts their values by one frame.
	 */
	public void components(){ //add all vector components
		
		Vector[] velocities = new Vector[ForceCircles.size()];
		
		// every object is integrated separately
		for(int i = 0; i < ForceCircles.size(); i++){
			Force f = ForceCircles.get(i);
			if(!f.isFrozen()){
				// TODO: don't actually move the object forward (this interferes with collision detection)
				PointVector pv = integrator.integrate(this, f, time, deltaTime);
				// XXX: I have no idea which this is supposed to be
//				f.setVector(VectorMath.getVector(pv, f));
				velocities[i] = pv.getVector();
//				f.setPointVector(pv);
				
				if(Double.isInfinite(f.getX()) || Double.isNaN(f.getX()))
					f.setX(0);
				if(Double.isInfinite(f.getY()) || Double.isNaN(f.getY()))
					f.setY(0);
				if(Double.isInfinite(f.getvx()) || Double.isNaN(f.getvx()))
					f.setvx(0);
				if(Double.isInfinite(f.getvy()) || Double.isNaN(f.getvy()))
					f.setvy(0);
				
				if(f.getvx() > -1E-2 && f.getvx() < 1E-2)
					f.setvx(0);
				if(f.getvy() > -1E-2 && f.getvy() < 1E-2)
					f.setvy(0);
			}
		}
		
		try{
			// TODO: clean this up : determine why circles still intersect
			// TODO: determine why circles can't rest on two lines
			Collideresult cr;
			cr = checkforcecirclescollide(ForceCircles, StaticCircles, Lines);
			if(cr.collidelist.size() > 0)
				cr = checkforcecirclescollide(ForceCircles, StaticCircles, Lines, cr.collidetime, cr.modified, false);
			
			for(int i = Math.min(ForceCircles.size(), cr.modified.length) - 1; i >= 0; i--){
				ForceCircle fc = ForceCircles.get(i);
				if(!fc.isFrozen()){
					if(!cr.modified[i]){ //unchanged, so move it forward
						fc.setPoint(fc.getX2(), fc.getY2());
						fc.setVector(velocities[i]);
						
						if(cr.collidetime[i] == 1) { //if it has not been moved forward (in the last collide() call) , move it forward
							//the collide function moves collided forcecircles forward if they have collided in that session
							fc.setPoint(fc.getX() + (1-cr.timepassed[i])*fc.getvx(), fc.getY() + (1-cr.timepassed[i])*fc.getvy());
							//there may still be more of the vector to move forward but you haven't done the collision checking what's left
						}
					} else {
						// XXX: this seems to solve a problem with circles sticking to lines
						if(cr.collidetime[i] == 0) {
							fc.setPoint(fc.getX2(), fc.getY2());
						}
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public Vector accelerate(Force f, PointVector pv, double t) {
		Vector next = f.getAcceleration(pv, t);
		for (ForceCircle b : ForceCircles){
			if (f.isResponsive(b)) {
				next.add(f.responsiveAcceleration(pv, t, b));
				if (b instanceof Accelerator)
					next.add(((Accelerator) b).accelerate(f, pv, t));
			}
		}
		for (StaticCircle sc : StaticCircles) {
			if (f.isResponsive(sc)) {
				next.add(f.responsiveAcceleration(pv, t, sc));
				if (sc instanceof Accelerator)
					next.add(((Accelerator) sc).accelerate(f, pv, t));
			}
		}
		for (StaticLine l : Lines){
			if (f.isResponsive(l)) {
				next.add(f.responsiveAcceleration(pv, t, l));
				if (l instanceof Accelerator)
					next.add(((Accelerator) l).accelerate(f, pv, t));
			}
		}
		return next;
	}
	
/*
 * END OF COMPONENTS
 */
	
	/**
	 * An object that has collided into another object.
	 * 
	 * @author Eric
	 * 
	 */
	private class Collider {
		/**
		 * The object that performed the collision.
		 */
		private Object collideobj;
		/**
		 * The location of the object in the array that contains it.
		 */
		private Integer collideindex;
		/**
		 * The amount of power transferred by the object.
		 */
		private Vector collideforce;
		
		@SuppressWarnings("unused")
		public Collider(Vector collideobj, Integer collidewith){
			this.collideobj = collideobj;
			this.collideindex = collidewith;
			this.collideforce = collideobj;
		}
		public Collider(Object collideobj, Integer collidewith, Vector collideforce){
			this.collideobj = collideobj;
			this.collideindex = collidewith;
			this.collideforce = collideforce;
		}
		public Object getCollideobj(){
			return collideobj;
		}
		public Integer getCollidewith(){
			return collideindex;
		}
		public Vector getCollideforce(){
			return collideforce;
		}
		/**
		 * Sets a new force transfered to the object.
		 * @param collideforce The new <code>Vector</code>.
		 */
		public void setCollideforce(Vector collideforce){
			this.collideforce = collideforce;
		}
		public String toString(){
			return collideobj.getClass().getSimpleName() + " @ " + collideindex + " hit with " + collideforce.toString();
		}
	}

	/**
	 * Stores a reference to the <code>Object</code> an <code>Object</code> has collided into and the index of the
	 * <code>Object</code>. Don't modify the lists directly.
	 * 
	 * @author Eric
	 */
	private class Collideclassindex {
		private ArrayList<Collider> colliders; // object you collided into
		private int numforcecircles;

		public Collideclassindex(){
			colliders = new ArrayList<Collider>(1);
			numforcecircles = 0;
		}
		/**
		 * Creates a new instance of <code>Collideclassindex</code> with the specified arguments.
		 * 
		 * @param collideclass The class of the <code>Object</code> the <code>Object</code> collided into.
		 * @param collidewith The index of the <code>Object</code> that was collided into.
		 */
		@SuppressWarnings("unused")
		public Collideclassindex(Object collideclass, int collidewith, Vector collideforce){
			colliders = new ArrayList<Collider>(1);
			colliders.add(new Collider(collideclass, collidewith, collideforce));
		}

		/**
		 * Returns whether or not there have been any collisions by testing if <code>size()</code> > 0.
		 * 
		 * @return <code>true</code> if there are collisions.
		 */
		public boolean collided(){
			return size() > 0;
		}
		/**
		 * Resets this object.
		 */
		public void reset(){
			this.colliders.trimToSize();
			this.colliders.clear();
			numforcecircles = 0;
		}
		public void setCollided(Object collideobj, int collidewith, Vector collideforce){
			if(size() > 0)
				reset();
			if(collideobj instanceof ForceCircle && !((ForceCircle)collideobj).isFrozen())
				numforcecircles++;
			colliders.add(new Collider(collideobj, collidewith, collideforce));
		}
		public void addCollided(Object collideobj, int collidewith, Vector collideforce){
			if(collideobj instanceof ForceCircle && !((ForceCircle)collideobj).isFrozen())
				numforcecircles++;
			colliders.add(new Collider(collideobj, collidewith, collideforce));
		}
		public ArrayList<Collider> getColliders(){
			return colliders;
		}
		public int getNumforcecircles(){
			return numforcecircles;
		}
		public boolean containsBoundaries(){
			for(Collider o : this.colliders){
				if(o.getCollideobj() instanceof Boundaries)
					return true;
			}
			return false;
		}
		public Collider contains(Object o){
			for(Collider c : colliders){
				if(c.getCollideobj().equals(o))
					return c;
			}
			return null;
		}
		/**
		 * 
		 * @return the size of <b>colliders</b>.
		 */
		public int size(){
			return this.colliders.size();
		}
		public String toString(){
			String s = "";
			for(Collider c : colliders){
				s += c.toString() + "\n";
			}
			return s;
		}
	}

	/**
	 * private class that contains the resultant vectors and the index of the <code>ForceCircle</code> that each
	 * <code>ForceCircle</code> collided with.
	 * 
	 * @author Eric
	 */
	private class Collideresult {
		/**
		 * The new <code>PointVector</code> for each of the <code>ForceCircles</code>.
		 */
		protected PointVector[] resultants;
		/**
		 * The list of <code>ForceCircles</code> that collided.
		 */
		protected ArrayList<Integer> collidelist;
		/**
		 * The Object, index, and power transferred of each object that collided into a certain object.
		 */
		protected Collideclassindex[] collideinto;
		/**
		 * The amount of time passed to arrive at the location given by <b>resultvectors</b> from the location given by
		 * circles.
		 */
		protected double[] timepassed;
		/**
		 * The amount of time passed to arrive at the location given by <b>resultvectors</b> from the initial location.
		 */
		protected double[] collidetime; // when each object collided
		/**
		 * Whether or not a vector has been modified since it's initial location (cumulative over a whole frame)
		 */
		protected boolean[] modified; // whether or not a forcecircle has been modified

		/**
		 * Creates a <code>Collideresult</code> with the specified parameters.
		 * 
		 * @param resultvectors the new <code>PointVector</code> for each of the <code>ForceCircles</code>.
		 * @param collideinto the Object, index, and power transferred of each object that collided into a certain
		 * object.
		 * @param collidelist the list of <code>ForceCircles</code> that collided.
		 * @param timepassed the amount of time passed to arrive at the location given by <b>resultvectors</b> from the
		 * location given by circles.
		 * @param collidetime the amount of time passed to arrive at the location given by <b>resultvectors</b> from the
		 * initial location.
		 * @param modified whether or not a vector has been modified since it's initial location (cumulative over a
		 * whole frame)
		 */
		public Collideresult(PointVector[] resultvectors, Collideclassindex[] collideinto,
				ArrayList<Integer> collidelist, double[] timepassed, double[] collidetime, boolean[] modified){
			this.resultants = resultvectors;
			this.collideinto = collideinto;
			this.collidelist = collidelist;
			this.timepassed = timepassed;
			this.collidetime = collidetime;
			this.modified = modified;
		}
		public String toString(){
			return collidelist.toString();
		}
	}
	
	/**
	 * Checks collision between <code>ForceCircles</code> and
	 * <code>StaticCircles</code>.
	 * 
	 * @param forceCircle
	 *            a list of <code>ForceCircles</code>.
	 * @param staticcircles
	 *            a list of <code>StaticCircles</code>.
	 * @return the new locations and vectors after any collisions.
	 */
	public final Collideresult checkforcecirclescollide(List<ForceCircle> forceCircle,
			ArrayList<StaticCircle> staticcircles, ArrayList<StaticLine> lines){
		double[] time = new double[forceCircle.size()];
		boolean[] collided = new boolean[forceCircle.size()];
		for(int i = forceCircle.size() - 1; i >= 0; i--)
			time[i] = 1;
		return checkforcecirclescollide(forceCircle, staticcircles, lines, time, collided, true);
	}

	/**
	 * Checks for collision between <code>ForceCircles</code> and other
	 * <code>Objects</code>. Can be run multiple times using the
	 * <code>timepassed</code> and <code>collided</code> fields of
	 * <code>Collideresult</code> to calculate successive collisions, allowing
	 * for one <code>Object</code> to collide with multiple <code>Objects</code>
	 * at different times along it's initial vector.
	 * 
	 * @param forceCircle2
	 *            The <code>ArrayList</code> of <code>ForceCircles</code> that
	 *            are to be tested for collisions between themselves and other
	 *            <code>Objects</code>.
	 * @param staticcircles
	 *            An <code>ArrayList</code> of <code>StaticCircles</code> that
	 *            are to be tested against <b>circles</b> for collision.
	 * @param timepassed
	 *            The amount of time (between 0 and 1) that has passed to get
	 *            from the Object's initial position to the object's current
	 *            position as returned by <b>circles</b>.
	 * @param modified
	 *            An array corresponding with <b>circles</b> that indicates
	 *            whether or not that specific <code>ForceCircle</code> has
	 *            collided with another <code>Object</code> due to it's initial
	 *            vector. <code>false</code> if the vector in <b>circles</b> is
	 *            the same as the original (before collision testing) vector.
	 * @param fullcheck
	 *            If <code>true</code>, checks every <code>ForceCircle</code>
	 *            against every other. If <code>false</code>, does not check
	 *            collision between two <code>ForceCircles</code> if
	 *            <b>collided</b> for both <code>ForceCircles</code> is
	 *            <code>false</code>.
	 * @return A <code>Collideresult</code> that contains: </br> The resultant
	 *         <code>PointVector</code> for each object, a list of
	 *         <code>ForceCircles</code> that collided, the time of each
	 *         <code>ForceCircle</code> collision, what each
	 *         <code>ForceCircle</code> collided into (if anything), an adjusted
	 *         <code>timepassed</code> that takes into account the new
	 *         collisions, and a corrected <b>collided</b> adjusted for the new
	 *         collisions.
	 */
	public Collideresult checkforcecirclescollide(List<ForceCircle> forceCircle2,
			ArrayList<StaticCircle> staticcircles, ArrayList<StaticLine> lines, double[] timepassed, boolean[] modified, boolean fullcheck){
		Collideresult cr = checkforcecirclescollidetime(forceCircle2, staticcircles, lines, timepassed, modified, fullcheck);
		ArrayList<Object> collidedinto = new ArrayList<Object>();
		for(int i = cr.resultants.length - 1; i >= 0; i--){
			// set the objects new position + velocity
			if(cr.collideinto[i].collided())
				forceCircle2.get(i).setPointVector(cr.resultants[i]);
			collidedinto.clear();
			
			// trigger objects if necessary
			for (int j = cr.collideinto[i].size() - 1; j >= 0; j--) {
				Object o = cr.collideinto[i].getColliders().get(j).getCollideobj();
				collidedinto.add(o);
				if (o instanceof Triggerable)
					((Triggerable) o).trigger(new Object[]{forceCircle2.get(i)});
			}
			if (forceCircle2.get(i) instanceof Triggerable)
				((Triggerable) forceCircle2.get(i)).trigger(collidedinto.toArray());
		}
		return cr;
	}

	/**
	 * Checks for collision between <code>ForceCircles</code> and other
	 * <code>Objects</code>. Does not move objects forward and does not trigger
	 * <code>Triggers</code>. Use <code>checkforcecirclescollide()</code> for
	 * multiple calls. Should only be used for collision testing between moving
	 * <code>ForceCircles</code>.
	 * 
	 * @param forceCircle2
	 *            The <code>ArrayList</code> of <code>ForceCircles</code> that
	 *            are to be tested for collisions between themselves and other
	 *            <code>Objects</code>.
	 * @param staticcircles
	 *            An <code>ArrayList</code> of <code>StaticCircles</code> that
	 *            are to be tested against <b>circles</b> for collision.
	 * @param timepassed
	 *            The amount of time (between 0 and 1) that has passed to get
	 *            from the Object's initial position to the object's current
	 *            position as returned by <b>circles</b>.
	 * @param modified
	 *            An array corresponding with <b>circles</b> that indicates
	 *            whether or not that specific <code>ForceCircle</code> has
	 *            collided with another <code>Object</code> due to it's initial
	 *            vector. <code>false</code> if the vector in <b>circles</b> is
	 *            the same as the original (before collision testing) vector.
	 * @param fullcheck
	 *            If <code>true</code>, checks every <code>ForceCircle</code>
	 *            against every other. If <code>false</code>, does not check
	 *            collision between two <code>ForceCircles</code> if
	 *            <b>collided</b> for both <code>ForceCircles</code> is
	 *            <code>false</code>.
	 * @return A <code>Collideresult</code> that contains: </br> The resultant
	 *         <code>PointVector</code> for each object, a list of
	 *         <code>ForceCircles</code> that collided, the time of each
	 *         <code>ForceCircle</code> collision, what each
	 *         <code>ForceCircle</code> collided into (if anything), an adjusted
	 *         <code>timepassed</code> that takes into account the new
	 *         collisions, and a corrected <b>collided</b> adjusted for the new
	 *         collisions.
	 */
	// add sliding (or rolling)
	// then add gridding (sectioning off of areas) :\
	public final Collideresult checkforcecirclescollidetime(List<ForceCircle> forceCircle2,
			ArrayList<StaticCircle> staticcircles, ArrayList<StaticLine> lines, double[] timepassed, boolean[] modified, boolean fullcheck){
		
		double upperxbound = bounds.getMaxX();
		double upperybound = bounds.getMaxY();
		double lowerxbound = bounds.getMinX();
		double lowerybound = bounds.getMinY();
		
		//refereces to the forcecircle you're currently working on
		ForceCircle a;
		ForceCircle b = null;
		
		PointVector[] results = new PointVector[forceCircle2.size()]; // the resultant vectors
		double[] closestdistsq = new double[forceCircle2.size()]; // the dist between circle and collision
		//stores what object each object collided into
		Collideclassindex[] collisionindex = new Collideclassindex[forceCircle2.size()];
		double[] collisiontimes = new double[forceCircle2.size()];

		// fill arrays
		for(int i = forceCircle2.size() - 1; i >= 0; i--){ 
			// done backwards to prevent overruns when arraylist is modified
			closestdistsq[i] = -1;
			collisionindex[i] = new Collideclassindex();
//			results[i] = new PointVector(circles.get(i));
			results[i] = forceCircle2.get(i);
			collisiontimes[i] = 1;
		}
		// test collision with walls
		int walls = 0;
		for(int i = Math.min(forceCircle2.size(), timepassed.length) - 1; i >= 0; i--){ //count down so you don't have out of bounds
			a = forceCircle2.get(i);
			if(!fullcheck && !modified[i])
				continue;
			if(a.isFrozen()) 
				continue;
			
			if (boundResponse == BOUNDS_RESPOND_NONE)
				continue;
			
			double cx1 = 0, cy1 = 0;
			walls = 0;
			
			double rad = a.getRadius() * boundDetection;
			if (boundResponse != BOUNDS_RESPOND_NONE) {
				// are you outside bounds?
				if (a.getX() + rad > upperxbound) // right
					a.setX(upperxbound - rad);
				if (a.getX() - rad < lowerxbound) // left
					a.setX(lowerxbound + rad);
				if (a.getY() + rad > upperybound) // bottom
					a.setY(upperybound - rad);
				if (a.getY() - rad < lowerybound) // top
					a.setY(lowerybound + rad);
			}
			// top
			if(a.getY2() - rad < lowerybound){
				if(!a.isCollide(new Boundaries(Boundaries.top, boundDetection))) continue;
				double A1 = ((lowerybound + rad) - (lowerybound + rad));
				double B1 = (lowerxbound - upperxbound);
				double C1 = ((lowerybound + rad) - (lowerybound + rad)) * lowerxbound
						+ (lowerxbound - upperxbound) * (lowerybound + rad);
				double A2 = (a.getvy());
				double B2 = (-a.getvx());
				double C2 = ((a.getvy()) * a.getX() + (-a.getvx()) * a.getY());
				double det = A1 * B2 - A2 * B1;
				double cx = 0;
				// line - vector intersect
				if(det != 0){
					//location of collision
					cx = (B2 * C1 - B1 * C2) / det;
					// closest point to obj1 on line
					double distsq = a.distanceSq(cx, lowerybound + rad);
					//if collision is after the end of the vector, it's not a collision
					if(!((timepassed[i] < 1 && timepassed[i] >= 0) && ((1 - timepassed[i]) * a.getLength())
							* ((1 - timepassed[i]) * a.getLength()) < distsq)){
						if(distsq < closestdistsq[i] || closestdistsq[i] < 0){
							walls = Boundaries.top;
							cx1 = (double)cx;
							cy1 = lowerybound + rad;
							closestdistsq[i] = distsq;
						}else if(distsq == closestdistsq[i]){ // on the line (same (x,y) values)
							walls += Boundaries.top;
							cx1 = (double)cx;
							cy1 = lowerybound + rad;
						}
					}
				}
			}
			// right
			if(a.getX2() + rad > upperxbound){
				if(!a.isCollide(new Boundaries(Boundaries.right, boundDetection))) continue;
				double A1 = (upperybound - lowerybound);
				double C1 = (upperybound - lowerybound) * (upperxbound - rad)
						+ ((upperxbound - rad) - (upperxbound - rad)) * lowerybound;
				double A2 = (a.getvy());
				double B2 = (-a.getvx());
				double C2 = ((a.getvy()) * a.getX() + (-a.getvx()) * a.getY());
				double det = A1 * B2;
				double cy = 0;
				// line - vector intersect
				if(det != 0){
					cy = (A1 * C2 - A2 * C1) / det;
					double distsq = Point.distanceSq(a.getX(), a.getY(), upperxbound - rad, cy);
					//if collision is after the end of the vector, it's not a collision
					if(!((timepassed[i] < 1 && timepassed[i] >= 0) && ((1 - timepassed[i]) * a.getLength())
							* ((1 - timepassed[i]) * a.getLength()) < distsq)){
						if(distsq < closestdistsq[i] || closestdistsq[i] < 0){
							walls = Boundaries.right;
							cx1 = upperxbound - rad;
							cy1 = (double)cy;
							closestdistsq[i] = distsq;
						}else if(distsq == closestdistsq[i]){ // on the line (same (x,y) values)
							walls += Boundaries.right;
							cx1 = upperxbound - rad;
							cy1 = (double)cy;
						}
					}
				}
			}
			// bottom
			if(a.getY2() + rad > upperybound){
				if(!a.isCollide(new Boundaries(Boundaries.bottom, boundDetection))) continue;
				double A1 = ((upperybound - rad) - (upperybound - rad));
				double B1 = (lowerxbound - upperxbound);
				double C1 = ((upperybound - rad) - (upperybound - rad)) * lowerxbound
						+ (lowerxbound - upperxbound) * (upperybound - rad);
				double A2 = (a.getvy());
				double B2 = (-a.getvx());
				double C2 = ((a.getvy()) * a.getX() + (-a.getvx()) * a.getY());
				double det = A1 * B2 - A2 * B1;
				double cx = 0;
				// line - vector intersect
				if(det != 0){
					cx = (B2 * C1 - B1 * C2) / det;
					double distsq = Point.distanceSq(a.getX(), a.getY(), cx, upperybound - rad);
					//if collision is after the end of the vector, it's not a collision
					if(!((timepassed[i] < 1 && timepassed[i] >= 0) && ((1 - timepassed[i]) * a.getLength())
							* ((1 - timepassed[i]) * a.getLength()) < distsq)){
						if(distsq < closestdistsq[i] || closestdistsq[i] < 0){
							walls = Boundaries.bottom;
							cx1 = (double)cx;
							cy1 = upperybound - rad;
							closestdistsq[i] = distsq;
						}else if(distsq == closestdistsq[i]){ // on the line (same (x,y) values)
							walls += Boundaries.bottom;
							cy1 = upperybound - rad;
							cx1 = cx;
						}
					}
				}
			}
			// left
			if(a.getX2() - rad < lowerxbound){
				if(!a.isCollide(new Boundaries(Boundaries.left, boundDetection))) continue;
				double A1 = (upperybound - lowerybound);
				double B1 = ((lowerxbound + rad) - (lowerxbound + rad));
				double C1 = (upperybound - lowerybound) * (lowerxbound + rad)
						+ ((lowerxbound + rad) - (lowerxbound + rad)) * lowerybound;
				double A2 = (a.getvy());
				double B2 = (-a.getvx());
				double C2 = ((a.getvy()) * a.getX() + (-a.getvx()) * a.getY());
				double det = A1 * B2 - A2 * B1;
				double cy = 0;
				// line - vector intersect
				if(det != 0){ //location of collision
					cy = (A1 * C2 - A2 * C1) / det;
					double distsq = Point.distanceSq(a.getX(), a.getY(), lowerxbound + rad, cy);
					//if collision is after the end of the vector, it's not a collision
					if(!((timepassed[i] < 1 && timepassed[i] >= 0) && ((1 - timepassed[i]) * a.getLength())
							* ((1 - timepassed[i]) * a.getLength()) < distsq)){
						if(distsq < closestdistsq[i] || closestdistsq[i] < 0){
							walls = Boundaries.left;
							cx1 = lowerxbound + rad;
							cy1 = (double)cy;
							closestdistsq[i] = distsq;
						}else if(distsq == closestdistsq[i]){ // on the line (same (x,y) values)
							walls += Boundaries.left;
							cx1 = lowerxbound + rad;
							cy1 = (double)cy;
						}
					}
				}
			}
			if(closestdistsq[i] >= 0){
				if(!collisionindex[i].collided())
					results[i] = new PointVector(cx1, cy1);
				if(closestdistsq[i] < 0.00001 && closestdistsq[i] > 0){
					// a.setVector(closesta);
					closestdistsq[i] = 0;
					collisiontimes[i] = 0;
				}
				if(closestdistsq[i] > 0){
					results[i] = new PointVector(cx1, cy1);
				}
				// the impact force is wrong because it's not calculated (will be calculated when it matters)
				collisionindex[i].setCollided(new Boundaries(walls, boundDetection), walls, a);
				// if(closestdistsq[i] == 0) array.get(i).setVector(closesta);
			}
		}
//test collision with lines
		
		StaticLine line;
		for(int i = Math.min(forceCircle2.size(), timepassed.length) - 1; i >= 0; i--){
			//important to not change staticcircle between calls to this method
			//otherwise fullcheck should be true
			//an object that has not collided with any other object within a particular frame
			//should not have collision checking done again against the list of static circles
			if(!fullcheck && !modified[i])
				continue;
			a = forceCircle2.get(i);
			if(a.isFrozen())
				continue;
			for(int j = lines.size() - 1; j >= 0; j--){
				line = lines.get(j);
				if(!a.isCollide(line))
					continue;
				Point intersp = VectorMath.closestpointonline(line.getX1(), line.getY1(), line.getX2(), line.getY2(), a.getX(), a.getY());
				double distsq = Point.distanceSq(intersp.getX(), intersp.getY(), a.getX(), a.getY());
				if(distsq < a.getRadiusSq()){
					double cx = 0, cy = 0;
					if(distsq == 0){ //circle is on the line
						Point pm = Point.midpoint(line.getP1(), line.getP2());
						double lineLength = line.getP1().distance(line.getP2());
						double distsq2 = a.distanceSq(pm);
						if(distsq2 < Math.pow(a.getRadius() + lineLength/2, 2) ){
							if(distsq2 != 0){
								double dist = a.distance(pm);
								double vx = (double)((a.getX() - pm.getX()) / dist);
								double vy = (double)((a.getY() - pm.getY()) / dist);
								cx = pm.getX() + (a.getRadius() + lineLength/2) * vx;
								cy = pm.getY() + (a.getRadius() + lineLength/2) * vy;
							}else{ //circle is at midpoint
								cx = a.getX();
								cy = a.getY();
							}
							if(closestdistsq[i] == -1)
								results[i] = new PointVector((double)cx, (double)cy);
							else
								results[i].setPoint((double)cx, (double)cy);
							if(closestdistsq[i] == 0){
								collisionindex[i].addCollided(line, j, a.getVector());
							}else{
								collisionindex[i].setCollided(line, j, a.getVector());
							}
							closestdistsq[i] = 0;
							continue;
						}else if(distsq2 == Math.pow(a.getRadius() + lineLength/2, 2) && a.getLength() == 0){
							continue;
						}
					}else if(Math.min(line.getX1(), line.getX2()) <= intersp.getX()
							&& intersp.getX() <= Math.max(line.getX1(), line.getX2())
							&& Math.min(line.getY1(), line.getY2()) <= intersp.getY()
							&& intersp.getY() <= Math.max(line.getY1(), line.getY2())){ //hits the line
						double dist = Math.sqrt(distsq);
						double vx = (double)((a.getX() - intersp.getX()) / dist);
						double vy = (double)((a.getY() - intersp.getY()) / dist);
						cx = intersp.getX() + a.getRadius() * vx;
						cy = intersp.getY() + a.getRadius() * vy;
						if(closestdistsq[i] == -1)
							results[i] = new PointVector((double)cx, (double)cy);
						else
							results[i].setPoint((double)cx, (double)cy);
						if(closestdistsq[i] == 0){
							collisionindex[i].addCollided(line, j, a.getVector());
						}else{
							collisionindex[i].setCollided(line, j, a.getVector());
						}
						closestdistsq[i] = 0;
						continue;
					}else if(Point.distanceSq(a.getX(), a.getY(), line.getX1(), line.getY1()) < a.getRadiusSq()){
						 //hits one end of the line
						double dist = Point.distance(a.getX(), a.getY(), line.getX1(), line.getY1());
						double vx = (double)((a.getX() - line.getX1()) / dist);
						double vy = (double)((a.getY() - line.getY1()) / dist);
						cx = line.getX1() + a.getRadius() * vx;
						cy = line.getY1() + a.getRadius() * vy;
						if(closestdistsq[i] == -1)
							results[i] = new PointVector((double)cx, (double)cy);
						else
							results[i].setPoint((double)cx, (double)cy);
						if(closestdistsq[i] == 0){
							collisionindex[i].addCollided(line, j, a.getVector());
						}else{
							collisionindex[i].setCollided(line, j, a.getVector());
						}
						closestdistsq[i] = 0;
						continue;
					}else if(Point.distanceSq(a.getX(), a.getY(), line.getX2(), line.getY2()) < a.getRadiusSq()){
						//hits the other end of the line
						double dist = Point.distance(a.getX(), a.getY(), line.getX2(), line.getY2());
						double vx = (double)((a.getX() - line.getX2()) / dist);
						double vy = (double)((a.getY() - line.getY2()) / dist);
						cx = line.getX2() + a.getRadius() * vx;
						cy = line.getY2() + a.getRadius() * vy;
						if(closestdistsq[i] == -1)
							results[i] = new PointVector((double)cx, (double)cy);
						else
							results[i].setPoint((double)cx, (double)cy);
						if(closestdistsq[i] == 0){
							collisionindex[i].addCollided(line, j, a.getVector());
						}else{
							collisionindex[i].setCollided(line, j, a.getVector());
						}
						closestdistsq[i] = 0;
						continue;
					}
		    	}
				double A1 = (line.getY2() - line.getY1());
		    	double B1 = (line.getX1() - line.getX2());
		    	double C1 = (line.getY2() - line.getY1())*line.getX1() + (line.getX1() - line.getX2())*line.getY1();
		    	double A2 = (a.getvy());
		    	double B2 = (-a.getvx());
		    	double C2 = ((a.getvy())*a.getX() + (-a.getvx())*a.getY());
		    	double det = A1*B2 - A2*B1;
		    	//double dist = (line.getX2()-line.getX1()*obj1.getY()-line.getY1() - line.getY2()-line.getY1()*obj1.getX()-line.getX1())/line.getlength(0);
		    	double cx = 0;
		    	double cy = 0;
		    	//line - vector intersect
		    	if(det != 0){
			    	cx = (B2*C1 - B1*C2)/det;
			    	cy = (A1*C2 - A2*C1)/det;
		    	}
		    	/*double avx = a.getRadius()*a.getnormvx();
		    	double avy = a.getRadius()*a.getnormvy();*/
		    	/*double lvx = a.getRadius()*(line.getX2()-line.getX1())/line.getlength(0);
		    	double lvy = a.getRadius()*(line.getY2()-line.getY1())/line.getlength(0);*/
		    	//on the line
		    	Point p = VectorMath.closestpointonline(line.getX1(), line.getY1(), line.getX2(), line.getY2(), a.getX2(), a.getY2());
		    	//on the vector
		    	Point p1 = VectorMath.closestpointonline(a.getX(), a.getY(), a.getX2(), a.getY2(), line.getX1(), line.getY1());
		    	Point p2 = VectorMath.closestpointonline(a.getX(), a.getY(), a.getX2(), a.getY2(), line.getX2(), line.getY2());
		    	
		    	if(((Point.distanceSq(p.getX(), p.getY(), a.getX2(), a.getY2()) < a.getRadiusSq() && 
		    			Math.min(line.getX1(), line.getX2()) <= p.getX() && p.getX() <= Math.max(line.getX1(), line.getX2()) && 
		    			Math.min(line.getY1(), line.getY2()) <= p.getY() && p.getY() <= Math.max(line.getY1(), line.getY2()) ) ||
		    			(Point.distanceSq(p1.getX(), p1.getY(), line.getX1(), line.getY1()) < a.getRadiusSq() &&
		    				Math.min(a.getX(), a.getX()+a.getvx()) <= p1.getX() && p1.getX() <= Math.max(a.getX(), a.getX()+a.getvx()) && 
		    	    		Math.min(a.getY(), a.getY()+a.getvy()) <= p1.getY() && p1.getY() <= Math.max(a.getY(), a.getY()+a.getvy()) ) ||
		    			(Point.distanceSq(p2.getX(), p2.getY(), line.getX2(), line.getY2()) < a.getRadiusSq() &&
		    					Math.min(a.getX(), a.getX()+a.getvx()) <= p2.getX() && p2.getX() <= Math.max(a.getX(), a.getX()+a.getvx()) && 
		    	    			Math.min(a.getY(), a.getY()+a.getvy()) <= p2.getY() && p2.getY() <= Math.max(a.getY(), a.getY()+a.getvy()) ) ||
		    			(Math.min(a.getX(), a.getX()+a.getvx()) <= cx && cx <= Math.max(a.getX(), a.getX()+a.getvx()) && 
		    			Math.min(a.getY(), a.getY()+a.getvy()) <= cy && cy <= Math.max(a.getY(), a.getY()+a.getvy()) && 
		    			Math.min(line.getX1(), line.getX2()) <= cx && cx <= Math.max(line.getX1(), line.getX2()) && 
		    			Math.min(line.getY1(), line.getY2()) <= cy && cy <= Math.max(line.getY1(), line.getY2())))
		    			|| (Point.distanceSq(line.getX1(), line.getY1(), a.getX2(), a.getY2()) <= a.getRadiusSq() || 
			    			Point.distanceSq(line.getX2(), line.getY2(), a.getX2(), a.getY2()) <= a.getRadiusSq())
		    			 ){
		    		double A3 = -B1;
			    	double B3 = A1;
			    	double C3 = A3*a.getX() + B3*a.getY();
			    	double det2 = (A1*B3 - A3*B1);
			    	double cx2 = 0;
			    	double cy2 = 0;
			    	if(det2 != 0){
			    		//closest point to obj1 on line
				    	cx2 = (B3*C1 - B1*C3)/det2;
				    	cy2 = (A1*C3 - A3*C1)/det2;
				    	/*g2.setColor(Color.gray);
				    	g2.fillRect((int)cx2 - 1, (int)cy2 - 1, 3, 3);*/
				    	
				    	//old method
				    	/*double dis = Math.sqrt(Math.abs((cx-a.getX())*(cx-a.getX()) + (cy-a.getY())*(cy-a.getY())));
				    	double dis2 = Math.sqrt(Math.abs((cx-cx2)*(cx-cx2) + (cy-cy2)*(cy-cy2)));
				    	double ang = Math.acos(VectorMath.dotproduct(cx, cy, cx2, cy2, a.getX(), a.getY())/(dis2*dis));
				    	double falldist = a.getRadius()/Math.sin(ang);*/
				    	//new method is 3x faster
				    	//how much to move back on the movement vector of a
				    	double falldist = (Point.distance(cx, cy, a.getX(), a.getY()) * a.getRadius()) / Point.distance(cx2, cy2, a.getX(), a.getY());
				    	//actual point of collision for the circle
				    	cx = cx + (-falldist) * a.getnormvx();
				    	cy = cy + (-falldist) * a.getnormvy();
				    	double C4 = A3*cx + B3*cy;
				    	double cx4 = (B3*C1 - B1*C4) / det2;
				    	double cy4 = (A1*C4 - A3*C1) / det2;
				    	/*g2.setColor(Color.black);
				    	g2.fillRect((int)cx4 - 1, (int)cy4 - 1, 3, 3);*/
				    	//does the circle collide parallel to the line?
				    	if(Math.min(line.getX1(), line.getX2()) <= cx4 && cx4 <= Math.max(line.getX1(), line.getX2()) && 
				    			Math.min(line.getY1(), line.getY2()) <= cy4 && cy4 <= Math.max(line.getY1(), line.getY2())){
					    	//real closest point on line
				    		double cx3 = cx2;
				    		double cy3 = cy2;
					    	cx2 = (cx2 + (cx - cx4));
					    	cy2 = (cy2 + (cy - cy4));
					    	
					    	double distsqa = Math.pow((cx - a.getX()), 2) + Math.pow((cy - a.getY()), 2);
					    	if((distsqa <= closestdistsq[i] || closestdistsq[i] < 0 || a.isFrozen())){
						    	RectVector v = null;
						    	if(!a.isFrozen()){
									if(collisionindex[i].collided() && closestdistsq[i] == distsqa){
									}else{
										// wipe out whoever you collided with before if they are farther away
										for(int l = 0; l < collisionindex[i].size(); l++){
											if(collisionindex[i].collided()
													&& collisionindex[i].getColliders().get(l).getCollideobj() instanceof ForceCircle
													&& (closestdistsq[i] > distsqa)){
												results[collisionindex[i].getColliders().get(l).getCollidewith()] = new PointVector(
														forceCircle2.get(collisionindex[i].getColliders().get(l).getCollidewith()));
												closestdistsq[collisionindex[i].getColliders().get(l).getCollidewith()] = -1;
											}
										}
									}
									if(Point.distanceSq(cx2, cy2, a.getX(), a.getY()) < 1e-8){ //circle is on the line
								    	Point pr = VectorMath.closestpointonline((double)(line.getX1() + (cx - cx3)), (double)(line.getY1() + (cy - cy3)),
								    			(double)(line.getX2() + (cx - cx3)), (double)(line.getY2() + (cy - cy3)), a.getX2(), a.getY2());
							    		v = new RectVector((double)((pr.getX() + (pr.getX()-a.getX2())) - a.getX()), (double)((pr.getY() + (pr.getY() - a.getY2())) - a.getY()));
										v = (RectVector)v.getUnitVector();
										v = new RectVector(v.getvx() * a.getLength(), v.getvy() * a.getLength());
							    	}else{ //circle is far from line
										v = new RectVector((double)((a.getX() - 2 * (cx2 - cx)) - cx), (double)((a.getY() - 2 * (cy2 - cy)) - cy));
										v = (RectVector)v.getUnitVector();
										v = new RectVector(v.getvx() * a.getLength(), v.getvy() * a.getLength());
							    	}
									v = (RectVector)v.getUnitVector();
									v = new RectVector(v.getvx() * a.getLength(), v.getvy() * a.getLength());
									if(closestdistsq[i] == -1)
										results[i] = new PointVector((double)cx, (double)cy);
									else
										results[i].setPoint((double)cx, (double)cy);
									if(closestdistsq[i] == distsqa){
										collisionindex[i].addCollided(line, j, v);
									}else{
										collisionindex[i].setCollided(line, j, v);
									}
									closestdistsq[i] = distsqa;
								}
					    	}
				    	}else{ //circle collides with a point
				    		double sumradsq = (a.getRadius()) * (a.getRadius());
							// if both objects aren't moving.. just make sure that they aren't close enough to collide
							Point pc1 = VectorMath.closestpointonline(a.getX(), a.getY(), a.getX2(), a.getY2(), line.getX1(), line.getY1());
							double distsq1 = Point.distanceSq(pc1.getX(), pc1.getY(), line.getX1(), line.getY1());
							double distsq_test1 = Point.distanceSq(pc1.getX(), pc1.getY(), a.getX(), a.getY());
							Point pc2 = VectorMath.closestpointonline(a.getX(), a.getY(), a.getX2(), a.getY2(), line.getX2(), line.getY2());
							double distsq2 = Point.distanceSq(pc2.getX(), pc2.getY(), line.getX2(), line.getY2());
							double distsq_test2 = Point.distanceSq(pc2.getX(), pc2.getY(), a.getX(), a.getY());
							// check if the resultant circle collides or if the point is inside the circle or if the point
							// is on the line segment
							double cdist = 0;
							if(distsq_test1 < distsq_test2 && distsq1 <= distsq2){
								// find point of collision
								// distance from closest point on line to point of collision
								cdist = Math.sqrt(Math.abs((sumradsq) - distsq1));
								cx = (pc1.getX() - cdist * a.getnormvx());
								cy = (pc1.getY() - cdist * a.getnormvy());
								cx2 = line.getX1();
								cy2 = line.getY1();
							}else if(distsq_test1 > distsq_test2 && distsq1 >= distsq2){
								cdist = Math.sqrt(Math.abs((sumradsq) - distsq2));
								cx = (pc2.getX() - cdist * a.getnormvx());
								cy = (pc2.getY() - cdist * a.getnormvy());
								cx2 = line.getX2();
								cy2 = line.getY2();
							}else{
								if(distsq1 < distsq2){
									if(distsq_test1 < distsq_test2 || Point.distanceSq(cx4, cy4, line.getX1(), line.getY1()) <= sumradsq){
										cdist = Math.sqrt(Math.abs((sumradsq) - distsq1));
										cx = (pc1.getX() - cdist * a.getnormvx());
										cy = (pc1.getY() - cdist * a.getnormvy());
										cx2 = line.getX1();
										cy2 = line.getY1();
									}else{
										cdist = Math.sqrt(Math.abs((sumradsq) - distsq2));
										cx = (pc2.getX() - cdist * a.getnormvx());
										cy = (pc2.getY() - cdist * a.getnormvy());
										cx2 = line.getX2();
										cy2 = line.getY2();
									}
								}else if(distsq1 > distsq2){
									//special case
									if(distsq_test2 < distsq_test1 || Point.distanceSq(cx4, cy4, line.getX2(), line.getY2()) <= sumradsq){
										cdist = Math.sqrt(Math.abs((sumradsq) - distsq2));
										cx = (pc2.getX() - cdist * a.getnormvx());
										cy = (pc2.getY() - cdist * a.getnormvy());
										cx2 = line.getX2();
										cy2 = line.getY2();
									}else{
										cdist = Math.sqrt(Math.abs((sumradsq) - distsq1));
										cx = (pc1.getX() - cdist * a.getnormvx());
										cy = (pc1.getY() - cdist * a.getnormvy());
										cx2 = line.getX1();
										cy2 = line.getY1();
									}
								}else if(//checks if second nearest point on line is in the line segment or in inside the final circle
										!((Math.min(a.getX(), a.getX2()) <= pc2.getX() && pc2.getX() <= Math.max(a.getX(), a.getX2()) && 
								    			Math.min(a.getY(), a.getY2()) <= pc2.getY() && pc2.getY() <= Math.max(a.getY(), a.getY2()))
								    			 || Point.distanceSq(pc2.getX(), pc2.getY(), a.getX2(), a.getY2()) <= a.getRadiusSq())){
									cdist = Math.sqrt(Math.abs((sumradsq) - distsq1));
									cx = (pc1.getX() - cdist * a.getnormvx());
									cy = (pc1.getY() - cdist * a.getnormvy());
									cx2 = line.getX1();
									cy2 = line.getY1();
								}else if(!((Math.min(a.getX(), a.getX2()) <= pc1.getX() && pc1.getX() <= Math.max(a.getX(), a.getX2()) && 
								    			Math.min(a.getY(), a.getY2()) <= pc1.getY() && pc1.getY() <= Math.max(a.getY(), a.getY2())) ||
								    			Point.distanceSq(pc2.getX(), pc2.getY(), a.getX2(), a.getY2()) <= a.getRadiusSq())){
									cdist = Math.sqrt(Math.abs((sumradsq) - distsq2));
									cx = (pc2.getX() - cdist * a.getnormvx());
									cy = (pc2.getY() - cdist * a.getnormvy());
									cx2 = line.getX2();
									cy2 = line.getY2();
				    			}else{
									if(distsq_test1 < distsq_test2){
										cdist = Math.sqrt(Math.abs((sumradsq) - distsq1));
										cx = (pc1.getX() - cdist * a.getnormvx());
										cy = (pc1.getY() - cdist * a.getnormvy());
										cx2 = line.getX1();
										cy2 = line.getY1();
									}else{
										cdist = Math.sqrt(Math.abs((sumradsq) - distsq2));
										cx = (pc2.getX() - cdist * a.getnormvx());
										cy = (pc2.getY() - cdist * a.getnormvy());
										cx2 = line.getX2();
										cy2 = line.getY2();
									}
								}
							}
							double distsqa = Math.pow((cx - a.getX()), 2) + Math.pow((cy - a.getY()), 2);
							if((distsqa <= closestdistsq[i] || closestdistsq[i] < 0 || a.isFrozen())){
								RectVector v = null;
						    	if(!a.isFrozen()){
									if(collisionindex[i].collided() && closestdistsq[i] == distsqa){
										
									}else{
										// wipe out whoever you collided with before if they are farther away
										for(int l = 0; l < collisionindex[i].size(); l++){
											if(collisionindex[i].collided()
													&& collisionindex[i].getColliders().get(l).getCollideobj() instanceof ForceCircle
													&& (closestdistsq[i] > distsqa)){
												results[collisionindex[i].getColliders().get(l).getCollidewith()] = new PointVector(
														forceCircle2.get(collisionindex[i].getColliders().get(l).getCollidewith()));
												closestdistsq[collisionindex[i].getColliders().get(l).getCollidewith()] = -1;
											}
										}
									}
									v = new RectVector((double)(cx - (cx2 - cx) - cx), (double)(cy - (cy2 - cy) - cy));
									v = (RectVector)v.getUnitVector();
									v = new RectVector(v.getvx() * a.getLength(), v.getvy() * a.getLength());
									if(closestdistsq[i] == -1)
										results[i] = new PointVector((double)cx, (double)cy);
									else
										results[i].setPoint((double)cx, (double)cy);
									if(closestdistsq[i] == distsqa){
										collisionindex[i].addCollided(line, j, v);
									}else{
										collisionindex[i].setCollided(line, j, v);
									}
									closestdistsq[i] = distsqa;
								}
							}
				    	}
					}
		    	}
			}
		}
		// test collision with staticcircles
		StaticCircle c;
		for(int i = Math.min(forceCircle2.size(), timepassed.length) - 1; i >= 0; i--){
			//important to not change staticcircle between calls to this method
			//otherwise fullcheck should be true
			//an object that has not collided with any other object within a particular frame
			//should not have collision checking done again against the list of static circles
			if(!fullcheck && !modified[i])
				continue;
			a = forceCircle2.get(i);
			for(int j = staticcircles.size() - 1; j >= 0; j--){
				c = staticcircles.get(j);
				if(!c.isCollide(a) || !a.isCollide(c))
					continue;
				if(a.getX() == c.getX() && a.getY() == c.getY())
					continue;
				double cx1 = a.getX() + a.getvx();
				double cy1 = a.getY() + a.getvy();
				double cx2 = c.getX();
				double cy2 = c.getY();
				double vx1 = 0;
				double vy1 = 0;
				double vx2 = 0;
				double vy2 = 0;
				if(CircleMath.checkcirclecollide(a, c)){ // they intersect
					double dist = 0;
					// find midpoint and push out radius
					cx1 = a.getX();
					cy1 = a.getY();
					cx2 = c.getX();
					cy2 = c.getY();
					dist = (double)Math.sqrt((c.getX() - a.getX()) * (c.getX() - a.getX()) + (c.getY() - a.getY())
							* (c.getY() - a.getY()));
					double sumrad = a.getRadius() + c.getRadius();
					cx1 = cx2 = c.getX();
					cy1 = cy2 = c.getY();
					vx1 = (sumrad + .25F) * ((a.getX() - c.getX()) / dist);
					vy1 = (sumrad + .25F) * ((a.getY() - c.getY()) / dist);
					cx1 += vx1;
					cy1 += vy1;
					cx2 += vx2;
					cy2 += vy2;
					if((a.getvx() != 0 || a.getvy() != 0)){
						// check for intersection
						double d = VectorMath.dotproduct(a.getvx(), a.getvy(), c.getX() - cx1, c.getY() - cy1);
						if(d <= 0){
							// distance from starting point to the (a) point of collision
							if(!a.isFrozen() && collisionindex[i].collided()){
								for(int l = 0; l < collisionindex[i].size(); l++){
									if(collisionindex[i].getColliders().get(l).getCollideobj() instanceof ForceCircle
											&& CircleMath.checkcirclecollide(forceCircle2.get(i), forceCircle2
													.get(collisionindex[i].getColliders().get(l).getCollidewith()))){
										cx1 = (results[i].getX() + cx1) / 2;
										cy1 = (results[i].getY() + cy1) / 2;
									}
								}
							}
							double distsqa = Point.distanceSq(a.getX(), a.getY(), cx1, cy1);
							if((distsqa <= closestdistsq[i] || closestdistsq[i] < 0)){
								if(distsqa == closestdistsq[i]){
									cx1 = (results[i].getX() + cx1) / 2;
									cy1 = (results[i].getY() + cy1) / 2;
								}
								if(closestdistsq[i] == -1)
									results[i] = new PointVector(cx1, cy1);
								else
									results[i].setPoint(cx1, cy1);
								closestdistsq[i] = distsqa;
								collisionindex[i].setCollided(c, j, a);
							}
							continue;
						}
					}
				}else{ // c is frozen
					double sumradsq = (double)(a.getRadius() + c.getRadius()) * (a.getRadius() + c.getRadius());
					// if both objects aren't moving.. just make sure that they aren't close enough to collide
					if((a.getvx() == 0 && a.getvy() == 0)
							&& Point.distanceSq(a.getX(), a.getY(), c.getX(), c.getY()) >= sumradsq)
						continue;
					Point p = VectorMath.closestpointonline(a.getX(), a.getY(), a.getX2(), a.getY2(), c.getX(), c
							.getY());
					double distsq = (double)Point.distanceSq(p.getX(), p.getY(), c.getX(), c.getY());
					// check if the resultant circle collides or if the point is inside the circle or if the point is on
					// the line segment
					if(distsq < sumradsq
							&& (CircleMath.checkcirclecollide(a.getX2(), a.getY2(), a.getRadius(), c.getX(), c.getY(),
									c.getRadius()) || (p.getX() >= (Math.min(a.getX(), a.getX2()))
									&& p.getX() <= (Math.max(a.getX(), a.getX2()))
									&& p.getY() >= (Math.min(a.getY(), a.getY2())) && p.getY() <= (Math.max(a.getY(), a
									.getY2()))))){
						// find point of collision
						double cdist = Math.sqrt((sumradsq + .789) - distsq); // distance from closest point on line to
																				// point of collision
						cx1 = (double)(p.getX() - cdist * a.getnormvx());
						cy1 = (double)(p.getY() - cdist * a.getnormvy());
						if((!CircleMath.checkcirclecollide(cx1, cy1, a.getRadius(), c.getX(), c.getY(), c.getRadius()) && !(Point
								.distanceSq(a.getX2(), a.getY2(), cx1, cy1) <= a.getRadiusSq()))
								&& !(p.getX() >= (Math.min(a.getX(), a.getX2()))
										&& p.getX() <= (Math.max(a.getX(), a.getX2()))
										&& p.getY() >= (Math.min(a.getY(), a.getY2())) && p.getY() <= (Math.max(a
										.getY(), a.getY2()))))
							cx2 = c.getX();
						cy2 = c.getY();
					}else
						continue;
				}
				double distsqa = 0;
				if(a.getvx() != 0 || a.getvy() != 0){
					distsqa = Point.distanceSq(a.getX(), a.getY(), cx1, cy1);
				}
				if((distsqa <= closestdistsq[i] || closestdistsq[i] < 0 || forceCircle2.get(i).isFrozen())){
					if(!a.isFrozen() && distsqa == closestdistsq[i]){
						cx1 = (results[i].getX() + cx1) / 2;
						cy1 = (results[i].getY() + cy1) / 2;
					}
					if(!a.isFrozen()){
						if(collisionindex[i].collided() && closestdistsq[i] == distsqa){
						}else{
							// wipe out whoever you collided with before if they are farther away
							for(int l = 0; l < collisionindex[i].size(); l++){
								if(collisionindex[i].collided()
										&& collisionindex[i].getColliders().get(l).getCollideobj() instanceof ForceCircle
										&& (closestdistsq[i] > distsqa)){
									results[collisionindex[i].getColliders().get(l).getCollidewith()] = new PointVector(
											forceCircle2.get(collisionindex[i].getColliders().get(l).getCollidewith()));
									closestdistsq[collisionindex[i].getColliders().get(l).getCollidewith()] = -1;
								}
							}
						}
						if(closestdistsq[i] == -1)
							results[i] = new PointVector(cx1, cy1);
						else
							results[i].setPoint(cx1, cy1);
					}
					if(CircleMath.checkcirclecollide(a, c) || closestdistsq[i] == distsqa){
						collisionindex[i].addCollided(c, j, null);
					}else{
						collisionindex[i].setCollided(c, j, null);
					}
					if(CircleMath.checkcirclecollide(a, c))
						closestdistsq[i] = 0;
					else
						closestdistsq[i] = distsqa;
				}
			}
		}

	// START OF FOR LOOP for forcecircles
		for(int i = Math.min(forceCircle2.size(), timepassed.length) - 1; i >= 0; i--){
			a = forceCircle2.get(i);
			double cx1 = a.getX() + a.getvx();
			double cy1 = a.getY() + a.getvy();
			for(int j = i + 1; j < Math.min(forceCircle2.size(), timepassed.length); j++){
				b = forceCircle2.get(j);
				if(!a.isCollide(b) || !b.isCollide(a)) //don't collide with each other
					continue;
				if(a.getX() == b.getX() && a.getY() == b.getY()) //same location
					continue;
				//do not check collision between two objects that have not collided
				//and have already had collision checking done between each other
				//useful when running this method more than once (fullcheck enables this)
				if(!fullcheck && !modified[i] && !modified[j])
					continue;
				/*if(modified[i]){
					Graphics2D g = buf.createGraphics();
					g.setColor(Color.gray);
					g.drawOval((int)(a.getX()-a.getRadius()), (int)(a.getY()-a.getRadius()), (int)a.getRadius()*2, (int)a.getRadius()*2);
				}
				if(modified[j]){
					Graphics2D g = buf.createGraphics();
					g.setColor(Color.gray);
					g.drawOval((int)(b.getX()-b.getRadius()), (int)(b.getY()-b.getRadius()), (int)b.getRadius()*2, (int)b.getRadius()*2);
				}*/
				// default c1 and c2 values assumes you have not collided
				double cx2 = b.getX() + b.getvx();
				double cy2 = b.getY() + b.getvy();
				double vx1 = 0;
				double vy1 = 0;
				double vx2 = 0;
				double vy2 = 0;
				double collidetime = -1;
				//one of them is frozen
				if(a.isFrozen() || b.isFrozen()
						|| ((a.getvx() == 0 && a.getvy() == 0) || (b.getvx() == 0 && b.getvy() == 0))){
					if(CircleMath.checkcirclecollide(a, b)){ // they intersect
						double dist = 0;
						// find midpoint and push out radius
						cx1 = a.getX();
						cy1 = a.getY();
						cx2 = b.getX();
						cy2 = b.getY();
						dist = Point.distance(a.getX(), a.getY(), b.getX(), b.getY());
						double sumrad = a.getRadius() + b.getRadius();
						if(a.getLength() == 0 && b.getLength() == 0 && !a.isFrozen() && !b.isFrozen()){
							boolean abound = a.getMinX() == lowerxbound || a.getMaxX() == upperxbound
									|| a.getMinY() == lowerybound || a.getMaxY() == upperybound;
							boolean bbound = b.getMinX() == lowerxbound || b.getMaxX() == upperxbound
									|| b.getMinY() == lowerybound || b.getMaxY() == upperybound;
							if(abound && !bbound){
								cx2 = a.getX();
								cy2 = a.getY();
								vx2 = (double)((sumrad + .25F) * ((b.getX() - a.getX()) / dist));
								vy2 = (double)((sumrad + .25F) * ((b.getY() - a.getY()) / dist));
							}else if(!abound && bbound){
								cx1 = b.getX();
								cy1 = b.getY();
								vx1 = (double)((sumrad + .25F) * ((a.getX() - b.getX()) / dist));
								vy1 = (double)((sumrad + .25F) * ((a.getY() - b.getY()) / dist));
							}else{
								cx1 = (double)(a.getX() + a.getRadius() * ((b.getX() - a.getX()) / dist));
								cy1 = (double)(a.getY() + a.getRadius() * ((b.getY() - a.getY()) / dist));
								cx2 = (double)(b.getX() + b.getRadius() * ((a.getX() - b.getX()) / dist));
								cy2 = (double)(b.getY() + b.getRadius() * ((a.getY() - b.getY()) / dist));
								cx2 = cx1 = (cx1 + cx2) / 2;
								cy2 = cy1 = (cy1 + cy2) / 2;
								vx1 = (double)((a.getRadius() + .25) * ((a.getX() - b.getX()) / dist));
								vy1 = (double)((a.getRadius() + .25) * ((a.getY() - b.getY()) / dist));
								vx2 = (double)((b.getRadius() + .25) * ((b.getX() - a.getX()) / dist));
								vy2 = (double)((b.getRadius() + .25) * ((b.getY() - a.getY()) / dist));
							}
						}else{
							boolean abound = !b.isFrozen()
									&& (a.getMinX() == lowerxbound || a.getMaxX() == upperxbound
											|| a.getMinY() == lowerybound || a.getMaxY() == upperybound);
							boolean bbound = !a.isFrozen()
									&& (b.getMinX() == lowerxbound || b.getMaxX() == upperxbound
											|| b.getMinY() == lowerybound || b.getMaxY() == upperybound);
							if(abound && !bbound){
								cx2 = a.getX();
								cy2 = a.getY();
								vx2 = (double)((sumrad + .25F) * ((b.getX() - a.getX()) / dist));
								vy2 = (double)((sumrad + .25F) * ((b.getY() - a.getY()) / dist));
							}else if(!abound && bbound){
								cx1 = b.getX();
								cy1 = b.getY();
								vx1 = (double)((sumrad + .25F) * ((a.getX() - b.getX()) / dist));
								vy1 = (double)((sumrad + .25F) * ((a.getY() - b.getY()) / dist));
							}else{
								if((a.isFrozen() || ((a.getvx() == 0 && a.getvy() == 0)) && !b.isFrozen())){
									cx2 = cx1 = a.getX();
									cy2 = cy1 = a.getY();
									vx2 = (double)((sumrad + .25F) * ((b.getX() - a.getX()) / dist));
									vy2 = (double)((sumrad + .25F) * ((b.getY() - a.getY()) / dist));
								}
								if((b.isFrozen() || ((b.getvx() == 0 && b.getvy() == 0)) && !a.isFrozen())){
									cx1 = cx2 = b.getX();
									cy1 = cy2 = b.getY();
									vx1 = (double)((sumrad + .25F) * ((a.getX() - b.getX()) / dist));
									vy1 = (double)((sumrad + .25F) * ((a.getY() - b.getY()) / dist));
								}
							}
						}
						cx1 += vx1;
						cy1 += vy1;
						cx2 += vx2;
						cy2 += vy2;
					}else if((a.isFrozen() || (a.getvx() == 0 && a.getvy() == 0))){ // a is frozen
						double sumradsq = (double)(b.getRadius() + a.getRadius()) * (b.getRadius() + a.getRadius());
						// if both objects aren't moving.. just make sure that they aren't close enough to collide
						Point p = VectorMath.closestpointonline(b.getX(), b.getY(), b.getX2(), b.getY2(), a.getX(), a
								.getY());
						double distsq = (double)Point.distanceSq(p.getX(), p.getY(), a.getX(), a.getY());
						// check if the resultant circle collides or if the point is inside the circle or if the point
						// is on the line segment
						if(distsq < sumradsq
								&& (CircleMath.checkcirclecollide(b.getX2(), b.getY2(), b.getRadius(), a.getX(), a
										.getY(), a.getRadius()) || (p.getX() >= (Math.min(b.getX(), b.getX2()))
										&& p.getX() <= (Math.max(b.getX(), b.getX2()))
										&& p.getY() >= (Math.min(b.getY(), b.getY2())) && p.getY() <= (Math.max(b
										.getY(), b.getY2()))))){
							// find point of collision
							// distance from closest point on line to point of collision
							double cdist = Math.sqrt((sumradsq + .789) - distsq);
							cx2 = (double)(p.getX() - cdist * b.getnormvx());
							cy2 = (double)(p.getY() - cdist * b.getnormvy());
							/*
							 * if((!CircleMath.checkcirclecollide(cx1, cy1, b.getRadius(), a.getX(), a.getY(),
							 * a.getRadius()) && !(Point.distanceSq(b.getnx(), b.getny(), cx1, cy1) <=
							 * b.getRadiussq())) && !(p.getX() >= (Math.min(b.getX(), b.getnx())) && p.getX() <=
							 * (Math.max(b.getX(), b.getnx())) && p.getY() >= (Math.min(b.getY(), b.getny())) &&
							 * p.getY() <= (Math.max(b.getY(), b.getny())))) continue;
							 */
							cx1 = a.getX();
							cy1 = a.getY();
						}else
							continue;
					}else if((b.isFrozen() || (b.getvx() == 0 && b.getvy() == 0))){ // b is frozen
						double sumradsq = (double)(a.getRadius() + b.getRadius()) * (a.getRadius() + b.getRadius());
						// if both objects aren't moving.. just make sure that they aren't close enough to collide
						Point p = VectorMath.closestpointonline(a.getX(), a.getY(), a.getX2(), a.getY2(), b.getX(), b
								.getY());
						/*double A1 = (a.getny() - a.getY());
						double B1 = (a.getX() - a.getnx());
						double C1 = (a.getny() - a.getY())*a.getX() + (a.getX() - a.getnx())*a.getY();
						double C2 = -B1*b.getX() + A1*b.getY();
						double det = (A1*A1 - (-B1*B1));
						double cx = 0;
				    	double cy = 0;
				    	if(det != 0){
					    	cx = (A1*C1 - B1*C2)/det;
					    	cy = (A1*C2 - -B1*C1)/det;
				    	}*/
						double distsq = (double)Point.distanceSq(p.getX(), p.getY(), b.getX(), b.getY());
						// check if the resultant circle collides or if the point is inside the circle or if the point
						// is on the line segment
						/*if(!fullcheck){
							Graphics2D g = buf.createGraphics();
							g.setColor(Color.gray);
							g.fillRect((int)p.getX()-1, (int)p.getY()-1, 3, 3);
							g.setColor(Color.cyan);
							g.fillRect((int)a.getX()-1, (int)a.getY()-1, 3, 3);
							g.fillRect((int)a.getnx()-1, (int)a.getny()-1, 3, 3);
							System.out.println(p.getY() + " : " + a.getY() + " : " + a.getny() + " : " +
										  (p.getX() + 0.00005 >= Math.min(a.getX(), a.getnx())
										&& p.getX() - 0.00005 <= Math.max(a.getX(), a.getnx())
										&& p.getY() + 0.00005 >= Math.min(a.getY(), a.getny())
										&& p.getY() - 0.00005 <= Math.max(a.getY(), a.getny())
										   )
										   );
						}*/
						if(distsq < sumradsq
								&& (CircleMath.checkcirclecollide(a.getX() + a.getvx() * (1 - timepassed[i]), a.getY()
										+ a.getvy() * (1 - timepassed[i]), a.getRadius(), b.getX(), b.getY(), b
										.getRadius()) || (p.getX() + 0.00005 >= Math.min(a.getX(), a.getX2())
										&& p.getX() - 0.00005 <= Math.max(a.getX(), a.getX2())
										&& p.getY() + 0.00005 >= Math.min(a.getY(), a.getY2()) && p.getY() - 0.00005 <= Math
										.max(a.getY(), a.getY2())))){
							// find point of collision
							// distance from closest point on line to point of collision
							double cdist = Math.sqrt((sumradsq + .789) - distsq);
							cx1 = (double)(p.getX() - cdist * a.getnormvx());
							cy1 = (double)(p.getY() - cdist * a.getnormvy());
							/*
							 * if((!CircleMath.checkcirclecollide(cx1, cy1, a.getRadius(), b.getX(), b.getY(),
							 * b.getRadius()) && !(Point.distanceSq(a.getnx(), a.getny(), cx1, cy1) <=
							 * a.getRadiussq())) && !(p.getX() >= (Math.min(a.getX(), a.getnx())) && p.getX() <=
							 * (Math.max(a.getX(), a.getnx())) && p.getY() >= (Math.min(a.getY(), a.getny())) &&
							 * p.getY() <= (Math.max(a.getY(), a.getny())))) continue;
							 */
							cx2 = b.getX();
							cy2 = b.getY();
						}else
							continue;
					}else
						continue;
				}else if(CircleMath.checkcirclecollide(a, b)){
					// (specialized collision checking code since you don't want to touch actual a/b values
					// find midpoint and push out radius
					double dist = (double)Point.distance(a.getX(), a.getY(), b.getX(), b.getY());
					Rect aBoundBox = a.getBounds();
					Rect bBoundBox = b.getBounds();
					boolean abound = aBoundBox.getMinX() == lowerxbound || aBoundBox.getMaxX() == upperxbound
							|| aBoundBox.getMinY() == lowerybound || aBoundBox.getMaxY() == upperybound;
					boolean bbound = bBoundBox.getMinX() == lowerxbound || bBoundBox.getMaxX() == upperxbound
							|| bBoundBox.getMinY() == lowerybound || bBoundBox.getMaxY() == upperybound;
					double sumrad = a.getRadius() + b.getRadius();
					if(abound && !bbound){
						cx1 = cx2 = a.getX();
						cy1 = cy2 = a.getY();
						vx1 = 0;
						vy1 = 0;
						vx2 = (sumrad + .25F) * ((b.getX() - a.getX()) / dist);
						vy2 = (sumrad + .25F) * ((b.getY() - a.getY()) / dist);
					}else if(!abound && bbound){
						cx2 = cx1 = b.getX();
						cy2 = cy1 = b.getY();
						vx2 = 0;
						vy2 = 0;
						vx1 = (sumrad + .25F) * ((a.getX() - b.getX()) / dist);
						vy1 = (sumrad + .25F) * ((a.getY() - b.getY()) / dist);
					}else{
						cx1 = a.getX() + a.getRadius() * ((b.getX() - a.getX()) / dist);
						cy1 = a.getY() + a.getRadius() * ((b.getY() - a.getY()) / dist);
						cx2 = b.getX() + b.getRadius() * ((a.getX() - b.getX()) / dist);
						cy2 = b.getY() + b.getRadius() * ((a.getY() - b.getY()) / dist);
						cx2 = cx1 = (cx1 + cx2) / 2;
						cy2 = cy1 = (cy1 + cy2) / 2;
						vx1 = (double)((a.getRadius() + .25) * ((a.getX() - b.getX()) / dist));
						vy1 = (double)((a.getRadius() + .25) * ((a.getY() - b.getY()) / dist));
						vx2 = (double)((b.getRadius() + .25) * ((b.getX() - a.getX()) / dist));
						vy2 = (double)((b.getRadius() + .25) * ((b.getY() - a.getY()) / dist));
					}
					cx1 += vx1;
					cy1 += vy1;
					cx2 += vx2;
					cy2 += vy2;
					// are they heading toward each other?
					double d = VectorMath.dotproduct(a.getvx() - b.getvx(), a.getvy() - b.getvy(),
							b.getX() - a.getX(), b.getY() - a.getY());
					// System.out.println(d);
					if(d > 0
							|| CircleMath.checkcirclecollide(a.getX2(), a.getY2(), a.getRadius(), b.getX2(), b.getY2(),
									b.getRadius()) || (abound && !bbound && collisionindex[i].containsBoundaries())
							|| (!abound && bbound && collisionindex[j].containsBoundaries())){
						collidetime = 0;
					}else
						continue;
				}else{ // 2 moving non-intersecting circles! wee!
					double sumradsq = (a.getRadius() + b.getRadius()) * (a.getRadius() + b.getRadius());
					// uses b's frame of reference to make b not moving and a moving
					vx1 = a.getvx() - b.getvx();
					vy1 = a.getvy() - b.getvy();
					// find the closest point to b on the v line
					double A1 = ((a.getY() + vy1) - a.getY());
					double B1 = (a.getX() - (a.getX() + vx1));
					double C1 = A1 * a.getX() + B1 * a.getY();
					double C2 = -B1 * b.getX() + A1 * b.getY();
					double det = (A1 * A1 - (-B1 * B1));
					double cx = 0;
					double cy = 0;
					if(det != 0){
						cx = (A1 * C1 - B1 * C2) / det;
						cy = (A1 * C2 - -B1 * C1) / det;
					}
					double distsq = Point.distanceSq(cx, cy, b.getX(), b.getY());
					// check that the point is on the line segment
					if(distsq < sumradsq
							&& (CircleMath.checkcirclecollide(a.getX2(), a.getY2(), a.getRadius(), b.getX2(), b
									.getY2(), b.getRadius())
									|| CircleMath.checkcirclecollide(a.getX() + vx1, a.getY() + vy1, a.getRadius(), b
											.getX(), b.getY(), b.getRadius()) || ((double)cx >= (Math.min(a.getX(), a.getX() + vx1))
									&& (double)cx <= (Math.max(a.getX(), a.getX() + vx1))
									&& (double)cy >= (Math.min(a.getY(), a.getY() + vy1)) && (double)cy <= (Math.max(a.getY(), a.getY() + vy1))))){
						// find point of collision
						double dist = VectorMath.length(vx1, vy1); // length of v
						double dot = VectorMath.dotproduct(vx1 / dist, vy1 / dist, b.getX() - a.getX(), b.getY()
								- a.getY());
						double falldistsq = (sumradsq + .789F) - distsq;
						if(falldistsq - .789F > dot * dot) // just make sure you don't end up moving backwards
							continue;
						// distance to collision divided by length of v
						// When the two objects collide (between 0 and 1)
						collidetime = (dot - Math.sqrt(falldistsq)) / dist;
						if(collidetime < -.789 / dist || collidetime > 1)
							continue;
						cx1 = (double)(a.getX() + collidetime * a.getvx());
						cy1 = (double)(a.getY() + collidetime * a.getvy());
						cx2 = (double)(b.getX() + collidetime * b.getvx());
						cy2 = (double)(b.getY() + collidetime * b.getvy());
					}else
						continue;
				}
				/*
				 * Graphics g2 = buf.getGraphics(); g2.setColor(new Color(127, 127, 127, 176));
				 * g2.drawOval((int)(cx1-a.getRadius()), (int)(cy1-a.getRadius()),
				 * (int)(2a.getRadius()),(int)(2a.getRadius())); g2.drawOval((int)(cx2-b.getRadius()),
				 * (int)(cy2-b.getRadius()), (int)(2b.getRadius()),(int)(2b.getRadius()));
				 */

				// distance from starting point to the point of collision
				double distsqa = 0;
				double distsqb = 0;
				if(!CircleMath.checkcirclecollide(a, b)){ // if they intersect, it should be zero
					if(a.getvx() != 0 || a.getvy() != 0){
						distsqa = Point.distanceSq(a.getX(), a.getY(), cx1, cy1);
					}
					if(b.getvy() != 0 || b.getvy() != 0){
						distsqb = Point.distanceSq(b.getX(), b.getY(), cx2, cy2);
					}
				}else{
					if(Math.abs(timepassed[i] - timepassed[j]) > .1)
						continue;
				}
				if(timepassed[i] < 1 && timepassed[i] >= 0){ //if timepassed indicates the "real" vector is shorter
					//check to make sure the point of collision is within that "real" vector
					if(((1 - timepassed[i]) * a.getLength()) * ((1 - timepassed[i]) * a.getLength()) < distsqa)
						continue;
				}
				if(timepassed[j] < 1 && timepassed[j] >= 0){
					if(((1 - timepassed[j]) * b.getLength()) * ((1 - timepassed[j]) * b.getLength()) < distsqb)
						continue;
				}
				if((distsqa <= closestdistsq[i] || closestdistsq[i] < 0 || forceCircle2.get(i).isFrozen() || (forceCircle2.get(i)
						.getvx() == 0 && forceCircle2.get(i).getvy() == 0))
						&& (distsqb <= closestdistsq[j] || closestdistsq[j] < 0 || forceCircle2.get(j).isFrozen() || (forceCircle2
								.get(j).getvx() == 0 && forceCircle2.get(j).getvy() == 0))){
					//TODO:change in circletotal
					//store whether or not they are responsive to each other
					//just in case methods take a while to execute
					boolean arespondb = a.isResponsive(b);
					boolean bresponda = b.isResponsive(a);
					if(collidetime >= 0){ //adjust collision times
						if(!a.isFrozen() && arespondb && (a.getvx() != 0 || a.getvy() != 0)){
							collisiontimes[i] = collidetime;
						}else
							collisiontimes[i] = 0;
						if(!b.isFrozen() && bresponda && (b.getvx() != 0 || b.getvy() != 0)){
							collisiontimes[j] = collidetime;
						}else
							collisiontimes[j] = 0;
					}
					
					//average locations if multiple intersections
					if(!a.isFrozen() && collisionindex[i].collided() && arespondb){
						for(int l = 0; l < collisionindex[i].size(); l++){
							if(collisionindex[i].getColliders().get(l).getCollideobj() instanceof Circle
									&& (distsqa == closestdistsq[i] || (closestdistsq[i] == 0 && CircleMath
											.checkcirclecollide(a, (Circle)collisionindex[i].getColliders().get(l)
													.getCollideobj())))){
								cx1 = (results[i].getX() + cx1) / 2;
								cy1 = (results[i].getY() + cy1) / 2;
							}
						}
					}
					if(!b.isFrozen() && collisionindex[j].collided() && bresponda){
						for(int l = 0; l < collisionindex[j].size(); l++){
							if(collisionindex[j].getColliders().get(l).getCollideobj() instanceof Circle
									&& (distsqb == closestdistsq[j] || (closestdistsq[j] == 0 && CircleMath
											.checkcirclecollide((Circle)collisionindex[j].getColliders().get(l)
													.getCollideobj(), b)))){
								cx2 = (results[j].getX() + cx2) / 2;
								cy2 = (results[j].getY() + cy2) / 2;
							}
						}
					}
					if(!a.isFrozen() && arespondb){
						// you collided with another forcecircle at the same exact time
						if(collisionindex[i].collided() && closestdistsq[i] == distsqa){
						}else{
							// wipe out whoever you collided with before if they are farther away
							if(collisionindex[i].collided() && (closestdistsq[i] > distsqa || distsqa == 0)){
								for(int l = 0; l < collisionindex[i].size(); l++){
									if(collisionindex[i].getColliders().get(l).getCollidewith() < Math.min(forceCircle2.size(), timepassed.length)
											&& collisionindex[i].getColliders().get(l).getCollideobj() instanceof ForceCircle){
										results[collisionindex[i].getColliders().get(l).getCollidewith()] = new PointVector(
												forceCircle2.get(collisionindex[i].getColliders().get(l).getCollidewith()));
										closestdistsq[collisionindex[i].getColliders().get(l).getCollidewith()] = -1;
										collisionindex[collisionindex[i].getColliders().get(l).getCollidewith()]
												.reset();
									}
								}
							}
						}
					}
					if(!b.isFrozen() && bresponda){
						if(collisionindex[j].collided() && closestdistsq[j] == distsqb){
						}else{
							// wipe out whoever you collided with before if they are farther away
							if(collisionindex[j].collided() && (closestdistsq[j] > distsqb || distsqb == 0)){
								for(int l = 0; l < collisionindex[j].size(); l++){
									if(collisionindex[j].getColliders().get(l).getCollidewith() < Math.min(forceCircle2.size(), timepassed.length)
											&& collisionindex[j].getColliders().get(l).getCollideobj() instanceof ForceCircle){
										results[collisionindex[j].getColliders().get(l).getCollidewith()] = new PointVector(
												forceCircle2.get(collisionindex[j].getColliders().get(l).getCollidewith()));
										closestdistsq[collisionindex[j].getColliders().get(l).getCollidewith()] = -1;
										collisionindex[collisionindex[j].getColliders().get(l).getCollidewith()]
												.reset();
									}
								}
							}
						}
					}
					//change position if not frozen + responsive
					if(!a.isFrozen() && arespondb){
						if(closestdistsq[i] == -1)
							results[i] = new PointVector(cx1, cy1);
						else
							results[i].setPoint(cx1, cy1);
					}
					if(!b.isFrozen() && bresponda){
						if(closestdistsq[j] == -1)
							results[j] = new PointVector(cx2, cy2);
						else
							results[j].setPoint(cx2, cy2);
					}
					//if intersect, change dist + add new collided
					//TODO: is this right? throw into circletotal
					if(CircleMath.checkcirclecollide(a, b)){
//						if(arespondb){
							closestdistsq[i] = 0;
							collisionindex[i].addCollided(b, j, b);
//						}
//						if(bresponda){
							closestdistsq[j] = 0;
							collisionindex[j].addCollided(a, i, a);
//						}
					}else{ //if they there is no intersection, collided + real dist
						//TODO: respond?
//						if(arespondb){
							if(closestdistsq[i] == 0 || closestdistsq[i] == distsqa)
								collisionindex[i].addCollided(b, j, b);
							else
								collisionindex[i].setCollided(b, j, b);
							closestdistsq[i] = distsqa;
//						}
//						if(bresponda){
							if(closestdistsq[j] == 0 || closestdistsq[j] == distsqb)
								collisionindex[j].addCollided(a, i, a);
							else
								collisionindex[j].setCollided(a, i, a);
							closestdistsq[j] = distsqb;
//						}
					}
				}
			}// end of testing for forcecircles
		} // end of all collision testing

		int[] numstaticcircles = new int[forceCircle2.size()];
		int[] numfrozencircles = new int[forceCircle2.size()];
	//reduce energy for multiple circle collision checks
		for(int i = Math.min(forceCircle2.size(), timepassed.length) - 1; i >= 0; i--){
			a = forceCircle2.get(i);
			for(int k = 0; k < collisionindex[i].size(); k++){
				if(collisionindex[i].getColliders().get(k).getCollideobj() instanceof ForceCircle){
					b = (ForceCircle)collisionindex[i].getColliders().get(k).getCollideobj();
					if(b.isFrozen()) numfrozencircles[i]++;
					Collider tmp = collisionindex[collisionindex[i].getColliders().get(k).getCollidewith()].contains(a);
					if(tmp != null){
						Vector v = tmp.getCollideforce();
						if(VectorMath.dotproduct(a.getvx(), a.getvy(),
								results[collisionindex[i].getColliders().get(k).getCollidewith()].getX() - results[i].getX(), 
								results[collisionindex[i].getColliders().get(k).getCollidewith()].getY() - results[i].getY()) > 0 
								){
							collisionindex[collisionindex[i].getColliders().get(k).getCollidewith()].contains(a).setCollideforce(new RectVector(v.getvx() / collisionindex[i].getNumforcecircles(), v.getvy()
									/ collisionindex[i].getNumforcecircles()));
						}
					}
				}else if(collisionindex[i].getColliders().get(k).getCollideobj() instanceof StaticCircle){
					c = (StaticCircle)collisionindex[i].getColliders().get(k).getCollideobj();
					if(!CircleMath.checkcirclecollide(a, c) && 
							VectorMath.dotproduct(a.getvx(), a.getvy(), c.getX() - results[i].getX(), c.getY() - results[i].getY()) < 0){
						numstaticcircles[i] += 1;
					}
				}
			}
		}

		/*
		 * What we're going to do is take all the objects that have collided and what they have collided with and do the
		 * collision calculations. This is so that redundant calculations (on objects farther away) are not done and so
		 * multiple simultaneous collisions are handled correctly.
		 */
		// all the objects that have collided with another object (indicates to the outside that
		// these objects should NOT be moved)
		ArrayList<Integer> collidedwith = new ArrayList<Integer>((int)Math.ceil(forceCircle2.size() / 10));

		// "buckets" this is so that a - b distance isn't calculated at a and at b
		/*
		 * double[] lengths = new double[circles.size()]; for(int i = 0; i<circles.size(); i++) lengths[i] = -1;
		 */
		for(int i = 0; i < results.length; i++){ // calculate resultant
			if(collisionindex[i].collided()){
				a = forceCircle2.get(i);
				if(a.isFrozen()){
					results[i].setRect(0, 0);
					continue;
				}
				double vx1 = 0, vy1 = 0;/* , vx2 = 0, vy2 = 0; */
				// check for intersect before you change vector direction
				double totalmass = a.getMass();
				boolean intersect = false;
				boolean addedself = false;
				boolean hitmovinginto = false;
				double cx1 = results[i].getX();
				double cy1 = results[i].getY();
				double avgx = 0; // average locations of the circles you collided into
				double avgy = 0;
				double avgrad = 0;
				double numforcecircles = collisionindex[i].getNumforcecircles();// number of forcecircles collided into
				double sumvx = 0; // sum of vectors of the circles collided into
				double sumvy = 0;
				double avgbounce = 0;
				//statics
				double avgstaticx = 0;
				double avgstaticy = 0;
				double totalstaticmass = 0;

				// make sure that modifying i doesn't affect any objects down the line
				for(int k = 0; k < collisionindex[i].size(); k++){
					Object o = collisionindex[i].getColliders().get(k).getCollideobj();
					if(!a.isResponsive(o)) //check to make sure a reacts to colliding into o
						continue;
					avgbounce += forceCircle2.get(i).getRestitution(collisionindex[i].getColliders().get(k).getCollideobj());
					if(o instanceof Boundaries){
						Boundaries bound = (Boundaries)o;
						int wall = bound.getSide();
						if(boundResponse == BOUNDS_RESPOND_NONE){
							vx1 += a.getvx();
							vy1 += a.getvy();
							results[i].setPoint(a.getX2(), a.getY2());
						}else if(boundResponse == BOUNDS_RESPOND_BOUNCE){ // normal bouncing
							// left
							if(wall == Boundaries.left){
								wall -= Boundaries.left;
								double restitution = a.getRestitution(new Boundaries(Boundaries.left, boundDetection));
								vx1 += -(double)(a.getvx() * restitution);
								vy1 += (double)(a.getvy() * restitution);
							}else // bottom
							if(wall == Boundaries.bottom){
								wall -= Boundaries.bottom;
								double restitution = a.getRestitution(new Boundaries(Boundaries.bottom, boundDetection));
								vx1 += (double)(a.getvx() * restitution);
								vy1 += -(double)(a.getvy() * restitution);
							}else
							// right
							if(wall == Boundaries.right){
								wall -= Boundaries.right;
								double restitution = a.getRestitution(new Boundaries(Boundaries.right, boundDetection));
								vx1 += -(double)(a.getvx() * restitution);
								vy1 += (double)(a.getvy() * restitution);
							}else
							// top
							if(wall == Boundaries.top){
								wall -= Boundaries.top;
								double restitution = a.getRestitution(new Boundaries(Boundaries.top, boundDetection));
								vx1 += (double)(a.getvx() * restitution);
								vy1 += -(double)(a.getvy() * restitution);
							}else{
								double restitution = 1;
								// left
								if(wall >= Boundaries.left){
									wall -= Boundaries.left;
									restitution = a.getRestitution(new Boundaries(Boundaries.left, boundDetection));
								} // bottom
								if(wall == Boundaries.bottom){
									wall -= Boundaries.bottom;
									 restitution = a.getRestitution(new Boundaries(Boundaries.bottom, boundDetection));
								}
								// right
								if(wall >= Boundaries.right){
									wall -= Boundaries.right;
									restitution = a.getRestitution(new Boundaries(Boundaries.right, boundDetection));
								}
								// top
								if(wall >= Boundaries.top){
									wall -= Boundaries.top;
									restitution = a.getRestitution(new Boundaries(Boundaries.top, boundDetection));
								}
								vx1 -= a.getvx() * restitution;
								vy1 -= a.getvy() * restitution;
							}
						}else{
							Vector v = boundsresponse(boundResponse, a, bound);
							if(v != null){
								vx1 += v.getvx();
								vy1 += v.getvy();
							}
						}
					}else if(o instanceof ForceCircle){
						b = (ForceCircle)o;
						if(CircleMath.checkcirclecollide(a, b))
							intersect = true;
						if(b.isFrozen()){
							hitmovinginto = true;
							if(numstaticcircles[i] + numfrozencircles[i] > 1){
								avgstaticx += b.getX();
								avgstaticy += b.getY();
								totalmass += b.getMass();
								continue;
							}
							double len = Point.distance(cx1, cy1, b.getX(), b.getY());
							double nx = (b.getX() - cx1) / len;
							double ny = (b.getY() - cy1) / len;
							double a1 = 0;
							if(a.isFrozen()){
								a1 = 0;
							}else
								a1 = (double)(a.getvx() * nx + a.getvy() * ny);
							// totalmass += c.getMass();
							/* totala = totala + a1 - a2; */
							double p = (double)((2 * (a1)) / (a.getMass() + b.getMass()));
							// first forcecircle
							vx1 += (double)(a.getvx() - (p * a.getMass() * nx) + (p * b.getMass() * -nx));
							vy1 += (double)(a.getvy() - (p * a.getMass() * ny) + (p * b.getMass() * -ny));
							continue;
						}
						int j = collisionindex[i].getColliders().get(k).getCollidewith();
						avgx += results[j].getX();
						avgy += results[j].getY();
						if(numforcecircles > 1 && (b.getvx() != 0 || b.getvy() != 0) && VectorMath.crossproduct(a, b) < 0 &&
								VectorMath.dotproduct(a.getvx() - b.getvx(), a.getvy() - b.getvy(), a.getX() - b.getX(),
										a.getY() - b.getY()) > 0){
							hitmovinginto = true;
							// it's not results[i] because we're not looking for (x, y) we're looking for <x, y>
							double A1 = (a.getX() - (a.getX2()));
							double B1 = -((a.getY2()) - a.getY());
							double C1 = A1 * a.getX() + B1 * a.getY();
							double C2 = -B1 * b.getX() + A1 * b.getY();
							double det = (A1 * A1 - (-B1 * B1));
							double cx = 0;
							double cy = 0;
							cx = (A1 * C1 - B1 * C2) / det;
							cy = (A1 * C2 - -B1 * C1) / det;
							cx = cx + (cx - b.getX());
							cy = cy + (cy - b.getY());

							C2 = -B1 * (b.getX() + collisionindex[i].getColliders().get(k).getCollideforce().getvx()) + 
								A1 * (b.getY() + collisionindex[i].getColliders().get(k).getCollideforce().getvy());
							double cx2 = 0;
							double cy2 = 0;
							cx2 = (A1 * C1 - B1 * C2) / det;
							cy2 = (A1 * C2 - -B1 * C1) / det;
							cx2 = cx2 + (cx2 -(b.getX() + collisionindex[i].getColliders().get(k).getCollideforce().getvx()));
							cy2 = cy2 + (cy2 - (b.getY() + collisionindex[i].getColliders().get(k).getCollideforce().getvy()));

							sumvx += cx2 - cx;
							sumvy += cy2 - cy;
							/*
							 * sumvx += b.getvx(); sumvy += b.getvy();
							 */
						}else{
							sumvx += collisionindex[i].getColliders().get(k).getCollideforce().getvx();
							sumvy += collisionindex[i].getColliders().get(k).getCollideforce().getvy();
							/*System.out.println(collisionindex[i].getColliders().get(k).getCollideforce().getvx() == b.getvx() &&
									collisionindex[i].getColliders().get(k).getCollideforce().getvy() == b.getvy());*/
							/*sumvx += b.getvx();
							sumvy += b.getvy();*/
						}
						avgrad += b.getRadius();
						totalmass += b.getMass();
					}else if(o instanceof StaticCircle){
						// figure out if a static/force interesection warrants a collision mark
						c = (StaticCircle)o;
						if(!addedself && CircleMath.checkcirclecollide(a, c)
								&& VectorMath.dotproduct(a.getvx(), a.getvy(), c.getX() - a.getX(), c.getY()
										- a.getY()) < 0){ //moving away from obj
							vx1 += a.getvx();
							vy1 += a.getvy();
							addedself = true;
						}else if(numstaticcircles[i] + numfrozencircles[i]  > 1){
							avgstaticx += c.getX();
							avgstaticy += c.getY();
							totalmass += a.getMass();
						}else{
							double len = Point.distance(cx1, cy1, c.getX(), c.getY());
							double nx = (c.getX() - cx1) / len;
							double ny = (c.getY() - cy1) / len;
							double a1 = 0;
							if(a.isFrozen())
								a1 = 0;
							else
								a1 = (double)(a.getvx() * nx + a.getvy() * ny);
							double p = (double)((2 * (a1)) / (a.getMass() + a.getMass()));
							vx1 += (double)(a.getvx() - (p * a.getMass() * nx) + (p * a.getMass() * -nx));
							vy1 += (double)(a.getvy() - (p * a.getMass() * ny) + (p * a.getMass() * -ny));
						}
					}else if(o instanceof StaticLine){
						//TODO: infinite accumulation of energy?
						if(collisionindex[i].getColliders().get(k).getCollideforce() != null){
							vx1 += collisionindex[i].getColliders().get(k).getCollideforce().getvx();
							vy1 += collisionindex[i].getColliders().get(k).getCollideforce().getvy();
						}
					}
				}
				if(numstaticcircles[i] + numfrozencircles[i] > 1){
					double len = Point.distance(cx1, cy1, avgstaticx, avgstaticy);
					double nx = (avgstaticx - cx1) / len;
					double ny = (avgstaticy - cy1) / len;
					double a1 = 0;
					if(a.isFrozen())
						a1 = 0;
					else
						a1 = (double)(a.getvx() * nx + a.getvy() * ny);
					double p = (double)((2 * (a1)) / (a.getMass() + totalstaticmass));
					double vx = (double)(a.getvx() - (p * a.getMass() * nx) + (p * totalstaticmass * -nx));
					double vy = (double)(a.getvy() - (p * a.getMass() * ny) + (p * totalstaticmass * -ny));
					if(VectorMath.dotproduct(a.getvx() - vx, a.getvy() - vy, avgx - a.getX(), avgy
							- a.getY()) > 0){
						vx = -vx;
						vy = -vy;
					}
					vx1 += vx;
					vy1 += vy;
				}
				if(numforcecircles > 0){
					avgx /= numforcecircles;
					avgy /= numforcecircles;
					avgrad /= numforcecircles;
					if(!intersect || VectorMath.dotproduct(a.getvx() - sumvx, a.getvy() - sumvy, avgx - a.getX(), avgy
									- a.getY()) > 0){
						// maybe try to speed this up with buckets but it seems to slow it down (searching)
						double len = Point.distance(cx1, cy1, avgx, avgy);
						double nx = (avgx - cx1) / len;
						double ny = (avgy - cy1) / len;
						double a1 = 0;
						if(a.isFrozen()){
							a1 = 0;
						}else
							a1 = (a.getvx() * nx + a.getvy() * ny); // dot product
						double a2 = 0;
						a2 = (sumvx * nx + sumvy * ny); // dot product of the sum of colliders
						double p = (2 * (a1 - a2)) / (totalmass);
						if(!a.isFrozen()){
							double vx = (double)(a.getvx() - (p * a.getMass() * nx));
							double vy = (double)(a.getvy() - (p * a.getMass() * ny));
							if(numforcecircles > 1
									&& VectorMath.dotproduct(a.getvx() - vx, a.getvy() - vy, avgx - a.getX(), avgy
											- a.getY()) > 0){
								if(hitmovinginto && ((VectorMath.dotproduct(a.getvx(), a.getvy(), avgx - results[i].getX(), avgy - results[i].getY()) <= 0 
										|| VectorMath.dotproduct(a.getvx(), a.getvy(), sumvx, sumvy) <= 0))){
									nx = -nx;
									ny = -ny;
									vx = -(double)(sumvx - (p * totalmass / numforcecircles * nx));
									vy = -(double)(sumvy - (p * totalmass / numforcecircles * ny));
								}else{
									if(!hitmovinginto){
//										System.out.println(vx);
										/*vx /= numforcecircles;
										vy /= numforcecircles;*/
									}
									vx = -vx;
									vy = -vy;
								}
							}
							vx1 += vx;
							vy1 += vy;
						}
					}else{ // intersection
						vx1 = a.getvx();
						vy1 = a.getvy();
					}
				}
				avgbounce /= collisionindex[i].getColliders().size();
				if(closestdistsq[i] == -1)
					results[i] = new PointVector(results[i].getX(), results[i].getY());
				results[i].setRect(vx1 * avgbounce, vy1 * avgbounce);
				collidedwith.add(i);
				if(collisiontimes[i] == 1 && forceCircle2.get(i).getLength() != 0 && !intersect){
					if(closestdistsq[i] == 0)
						collisiontimes[i] = 0;
					else if(closestdistsq[i] > 0)
						collisiontimes[i] = Math.sqrt(closestdistsq[i])/forceCircle2.get(i).getLength();
					else
						collisiontimes[i] = forceCircle2.get(i).distance(results[i])/forceCircle2.get(i).getLength();
				}
				timepassed[i] += collisiontimes[i]*(1-timepassed[i]);
//				time[i] = collisiontimes[i];
				if(!results[i].equals(forceCircle2.get(i)))
					modified[i] = true;
			}
		}
		return new Collideresult(results, collisionindex, collidedwith, timepassed, collisiontimes, modified);
	}

	/**
	 * Used to specify a new boundary type. Calculates the response from a
	 * collision with a boundary.
	 * 
	 * @param bounds
	 *            the type of boundary.
	 * @param circle
	 *            the <code>ForceCircle</code> that requires a response from the
	 *            collision.
	 * @param boundaries
	 *            the boundaries the circle collided into.
	 * @return A {@link Vector} with the new direction of the
	 *         <code>ForceCircle</code>. This is <b>not</b> a
	 *         <code>Vector</code> representing the surface normal of the
	 *         boundary, the returned vector is not added to the direction of
	 *         the <code>ForceCircle</code>, it is the new vector of the
	 *         <code>ForceCircle</code>.
	 */
	protected Vector boundsresponse(int bounds, ForceCircle circle,
			Boundaries boundaries) {
		return circle;
	}
	
	public void addForceCircle(ForceCircle force) {
		ForceCircles.add(force);
	}

	public int getBoundDetection() {
		return boundDetection;
	}

	public void setBoundDetection(byte boundDetection) {
		this.boundDetection = boundDetection;
	}

	public ArrayList<StaticLine> getLines() {
		return Lines;
	}

	public StaticLine getLine(int i) {
		if (i >= 0 && i < Lines.size())
			return Lines.get(i);
		return null;
	}

	public void setLines(ArrayList<StaticLine> line) {
		Lines = line;
	}

	public void addLine(StaticLine line) {
		Lines.add(line);
	}

	public void removeLine(int i) {
		if (i >= 0 && i <= Lines.size() - 1)
			Lines.remove(i);
	}

	public ArrayList<StaticCircle> getStaticCircles() {
		return StaticCircles;
	}

	public StaticCircle getStaticCircle(int i) {
		return StaticCircles.get(i);
	}

	public void setStaticCircles(ArrayList<StaticCircle> staticCircle) {
		StaticCircles = staticCircle;
	}

	public void addStaticCircle(StaticCircle sc) {
		StaticCircles.add(sc);
	}

	/**
	 * clears arraylists
	 */
	public void clear() {
		this.ForceCircles.clear();
		this.Lines.clear();
		this.StaticCircles.clear();
	}

	public void setBounds(int width, int height){
		bounds = new StaticRect(width / 2, height / 2, width, height);
	}
	
	public void setBounds(Rect bounds) {
		this.bounds = bounds;
	}
	
	public Rect getBounds() {
		return bounds;
	}

	public void setBounds(Rect bounds, byte boundTypes) {
		setBounds(bounds);
		setBoundDetection(boundTypes);
	}

	public List<ForceCircle> getForceCircles() {
		return ForceCircles;
	}

	public ForceCircle getForceCircle(int i) {
		return ForceCircles.get(i);
	}

	public void setForceCircle(ArrayList<ForceCircle> forceCircle) {
		ForceCircles = forceCircle;
	}

	public double getTime() {
		return time;
	}

	public void setTime(double time) {
		this.time = time;
	}

	public double getDeltaTime() {
		return deltaTime;
	}

	public void setDeltaTime(double deltaTime) {
		this.deltaTime = deltaTime;
	}
	public byte getBoundResponse() {
		return boundResponse;
	}
	public void setBoundResponse(byte boundResponse) {
		this.boundResponse = boundResponse;
	}
	/**
	 * @param integrator the integrator to set
	 */
	public void setIntegrator(Integrator integrator) {
		this.integrator = integrator;
	}
	/**
	 * @return the integrator
	 */
	public Integrator getIntegrator() {
		return integrator;
	}

} public class PhysicsMath {
	
	/**
	 * Calculates the gravitational attraction between two forces.
	 * 
	 * @param g
	 *            The gravitational constant (G), the value depends on the units
	 *            used.
	 * @param a
	 *            A force.
	 * @param b
	 *            The force <b>a</b> is attracted to.
	 * @return A vector with the gravitational attraction of <b>a</b> to
	 *         <b>b</b>. <b>b</b> to <b>a</b> is simply the equalibriant or the
	 *         negative vector.
	 */
	public static final Vector gravitationalAcceleration(double g, Force a, Force b) {
		return inverseSquaredAttraction(g * b.getMass(), a, b);
	}
	
	/**
	 * Calculates attraction between two forces.
	 * 
	 * @param multiplier
	 *            The gravitational constant (G), the value depends on the units
	 *            used.
	 * @param a
	 *            A force.
	 * @param b
	 *            The force <b>a</b> is attracted to.
	 * @return A vector with the attraction of <b>a</b> to
	 *         <b>b</b>. <b>b</b> to <b>a</b> is simply the equlibriant or the
	 *         negative vector.
	 */
	public static final Vector inverseSquaredAttraction(double multiplier, Point a, Point b) {
		if (a.getX() == b.getX() && a.getY() == b.getY())
			return new RectVector(0, 0);
		double distancesq = a.distanceSq(b);

		double g = multiplier / distancesq;
		double dist = Point.distance(a.getX(), a.getY(), b.getX(), b.getY());

		return new RectVector(g * (b.getX() - a.getX()) / dist, g * (b.getY() - a.getY()) / dist);
	}
	
	public static final Vector inverseAttraction(double multiplier, Point a, Point b) {
		if (a.getX() == b.getX() && a.getY() == b.getY())
			return new RectVector(0, 0);
		
		double dist = a.distance(b);
		double scale = multiplier / dist;
		
		return new RectVector(scale * (b.getX() - a.getX()) / dist, scale * (b.getY() - a.getY()) / dist);
	}

	/**
	 * Calculates attraction between two forces.
	 * 
	 * @param multiplier
	 *            The gravitational constant (G), the value depends on the units
	 *            used.
	 * @param a
	 *            A force.
	 * @param b
	 *            The force <b>a</b> is attracted to.
	 * @return A vector with the attraction of <b>a</b> to
	 *         <b>b</b>. <b>b</b> to <b>a</b> is simply the equlibriant or the
	 *         negative vector.
	 */
	public static final Vector linearAttraction(double multiplier, Point a, Point b) {
		double dist = Point.distance(a.getX(), a.getY(), b.getX(), b.getY());

		// gravitational force
		double g = multiplier * dist;
		
		// normalized vector from i to j
		double fx = (g * ((b.getX() - a.getX()) / dist));
		double fy = (g * ((b.getY() - a.getY()) / dist));
		return new RectVector(fx, fy);
	}
} public class EulerIntegrator implements Integrator {

	@Override
	public PointVector integrate(Accelerator external, Force f, double t,
			double dt) {
		Vector a = f.getAcceleration(f, t).add(external.accelerate(f, f, t));
		return new PointVector(f).translate(f.getVector()).add(a);
	}

} public class RK4Integrator implements Integrator {

	private static class Derivative {
		double dx;
		double dy;
		double dvx;
		double dvy;
	}

	public static Vector accelerate(Force f, PointVector pv, double t) {
		return f.getAcceleration(pv, t);
	}

	private static Derivative evaluate(Accelerator external, Force initial,
			double t, double dt, Derivative d) {
		PointVector n = new PointVector(initial.getX() + d.dx * dt,
				initial.getY() + d.dy * dt, initial.getvx() + d.dvx * dt,
				initial.getvy() + d.dvy * dt);

		Derivative output = new Derivative();
		Vector v = accelerate(initial, n, t + dt).add(
				external.accelerate(initial, n, dt));
		output.dx = n.getvx();
		output.dvx = v.getvx();
		output.dy = n.getvy();
		output.dvy = v.getvy();
		return output;
	}

	public PointVector integrate(Accelerator external, Force f, double t,
			double dt) {
		Derivative a = evaluate(external, f, t, 0, new Derivative());
		Derivative b = evaluate(external, f, t + dt * 0.5, dt * 0.5, a);
		Derivative c = evaluate(external, f, t + dt * 0.5, dt * 0.5, b);
		Derivative d = evaluate(external, f, t + dt, dt, c);

		double dxdt = (1 / 6.0) * (a.dx + 2 * (b.dx + c.dx) + d.dx);
		double dvxdt = (1 / 6.0) * (a.dvx + 2 * (b.dvx + c.dvx) + d.dvx);
		double dydt = (1 / 6.0) * (a.dy + 2 * (b.dy + c.dy) + d.dy);
		double dvydt = (1 / 6.0) * (a.dvy + 2 * (b.dvy + c.dvy) + d.dvy);

		return new PointVector(f.getX() + dxdt * dt, f.getY() + dydt * dt,
				f.getvx() + dvxdt * dt, f.getvy() + dvydt * dt);
	}

}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.BufferStrategy;
import java.util.ListIterator;
import javax.swing.JComponent;
import javax.swing.JFrame;
import forceengine.demo.objects.ForceCircle_opt;
import forceengine.demo.objects.ForceCircle_opt_color;
import forceengine.demo.objects.Gel;
import forceengine.demo.objects.Mover;
import forceengine.demo.objects.Particle;
import forceengine.demo.objects.Pusher;
import forceengine.demo.objects.ForceCircle_opt.Constraint;
import forceengine.game.Freezable;
import forceengine.graphics.Colored;
import forceengine.graphics.Renderer;
import forceengine.input.AbstractAction;
import forceengine.input.Action;
import forceengine.input.HoldState;
import forceengine.input.InputBind;
import forceengine.input.SetState;
import forceengine.input.ToggleState;
import forceengine.math.VectorMath;
import forceengine.objects.Circle;
import forceengine.objects.Force;
import forceengine.objects.ForceCircle;
import forceengine.objects.Point;
import forceengine.objects.PointVector;
import forceengine.objects.RectVector;
import forceengine.objects.StaticCircle;
import forceengine.objects.StaticLine;
import forceengine.objects.Vector;
import forceengine.physics.PhysicsEngine;
import forceengine.physics.PhysicsMath;
import forceengine.physics.integrator.EulerIntegrator;
import forceengine.physics.integrator.RK4Integrator;
	private static final double gravaccel = 5;
	private static final Vector gravAccel = new RectVector(0, gravaccel);
	private static final double gravC = 100;
	
	public static void main(String args[]){
//		System.setProperty("sun.java2d.opengl","True");
//		System.setProperty("sun.java2d.d3d","True");
		@SuppressWarnings("unused")
		ForceEngineDemo test;
		test = new ForceEngineDemo(640, 480);
	}

	@SuppressWarnings("serial")
	private class WindowPane extends JComponent {

		protected void paintComponent(Graphics gp){ // whatever you do in here kills FPS as it's dragged;
			if(delay < 0)
				engine.setBounds(getWidth(), getHeight());
		}
		public WindowPane(){
			super();
		}
	}

	public ForceEngineDemo(int width, int height){
		engine = new PhysicsEngine(width, height){
			public Vector accelerate(Force f, PointVector pv, double t){
				Vector v = super.accelerate(f, pv, t);
				
				if(f != null && grabbed != null && f == grabbed){
					v.add(forceAccel);
				}
				
				// circular motion around a single point
//					v.add(new RectVector(getBounds().getWidth() / 4 - .5 * pv.getX(), getBounds().getHeight() / 4 - .5 * pv.getY()));
//					v.add(PhysicsMath.inverseAttraction(1000, pv, getBounds().getPoint()));
				
				// circular motion (twirling)
//					v.add(new RectVector(-.1*pv.getvy(), .1*pv.getvx()));
				
				// drag
				v.add(new RectVector(-drag * pv.getvx(), -drag * pv.getvy()));
				
				// spin
//					Vector spin = VectorMath.getVector(pv, getBounds().getPoint());
//					spin.setRect(spin.getvy(), -spin.getvx());
//					spin.scale(.1);
//					v.add(spin);
				
//					v.add(PhysicsMath.inverseAttraction(f.getMass() * pv.getLength() * pv.getLength(), pv, getBounds().getPoint()));

				// rocket
//					v.add(new RectVector(8 * pv.getnormvx(), 8 * pv.getnormvy()));
				
				if(gravity.state)
					v.add(gravAccel);
				
				if(windLeft.state)
					v.add(new RectVector(-5, 0));
				if(windRight.state)
					v.add(new RectVector(5, 0));
				if(windUp.state)
					v.add(new RectVector(0, -5));
				if(windDown.state)
					v.add(new RectVector(0, 5));
				
				if(gravitation.state){
					for (ForceCircle b : ForceCircles){
						if (f.isResponsive(b)) {
							v.add(PhysicsMath.gravitationalAcceleration(gravC, f, b));
						}
					}
				}
				
				return v;
			}
		};
		
		renderer = new Renderer(engine.ForceCircles, engine.StaticCircles, engine.Lines);
		
		// input
		inputBind = new InputBind();
		inputBind.addKeyAction(KeyEvent.VK_SPACE, "pause", pause);
		inputBind.addKeyAction(KeyEvent.VK_BACK_QUOTE, "dev", dev);
		inputBind.addKeyAction(KeyEvent.VK_F1, "help", help);
		inputBind.addKeyAction(KeyEvent.VK_G, "gravity", gravity);
		inputBind.addKeyAction(KeyEvent.VK_B, "gravitation", gravitation);
		inputBind.addKeyAction(KeyEvent.VK_F4, "fieldlines", fieldlines);
		
		inputBind.addKeyAction(KeyEvent.VK_A, "windLeft", windLeft);
		inputBind.addKeyAction(KeyEvent.VK_D, "windRight", windRight);
		inputBind.addKeyAction(KeyEvent.VK_W, "windUp", windUp);
		inputBind.addKeyAction(KeyEvent.VK_S, "windDown", windDown);
		
		inputBind.addKeyAction(KeyEvent.VK_EQUALS, "incRadius", incRadius);
		inputBind.keyMap.put(KeyEvent.VK_PLUS, "incRadius");
		inputBind.addKeyAction(KeyEvent.VK_MINUS, "decRadius", decRadius);
		inputBind.keyMap.put(KeyEvent.VK_SUBTRACT, "decRadius");
		
		inputBind.addKeyAction(KeyEvent.VK_PERIOD, "incBounce", incBounce);
		inputBind.addKeyAction(KeyEvent.VK_COMMA, "decBounce", decBounce);
		
		inputBind.addKeyAction(KeyEvent.VK_QUOTE, "incDrag", incDrag);
		inputBind.addKeyAction(KeyEvent.VK_SEMICOLON, "decDrag", decDrag);
		
		inputBind.addKeyAction(KeyEvent.VK_V, "collide", collide);
		inputBind.addKeyAction(KeyEvent.VK_ENTER, "liquid", liquid);
		
		inputBind.addKeyAction(KeyEvent.VK_DELETE, "removeFirst", removeFirst);
		inputBind.addKeyAction(KeyEvent.VK_BACK_SPACE, "removeLast", removeLast);
		
		inputBind.addKeyAction(KeyEvent.VK_CONTROL, "createLine", createLine);
		inputBind.addKeyAction(KeyEvent.VK_SHIFT, "createStatic", createStatic);
		inputBind.addKeyAction(KeyEvent.VK_ALT, "createConstraint", createConstraint);
		inputBind.addKeyAction(KeyEvent.VK_Z, "createPusher", createPusher);
		
		inputBind.addKeyAction(KeyEvent.VK_F5, "integrator", new AbstractAction(){
			public void act(int action, InputEvent e){
				if(action != Action.PRESSED)
					return;
				if(engine.getIntegrator() instanceof EulerIntegrator)