// Copyright (c) 2008 James A. Wilson All rights reserved. Use is // subject to license terms. // This file is part of CruiseSaver. // // CruiseSaver is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // CruiseSaver is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with CruiseSaver; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA package status.collisions; import java.util.logging.Logger; import status.logging.LogUtil; import vector.Vector2D; /** * * @author Nate Young, James Wilson * */ public class ParticleParty { private static final Logger logger = LogUtil.getLogger(ParticleParty.class); private static final double TIME_DIVISION = 3.0; private static final int MAX_SPEED = 7; private static final double MASS = 1.0; private double radius; // radius of particles private Orb[] balls; private final int height; private final int width; /** * * @param width * width of the "box" that particles are in * @param height * height of the "box" that particles are in */ public ParticleParty(int numorbs, int width, int height) { this.width = width; this.height = height; setNumberOfOrbs(numorbs); } public Orb getOrb(int i) { return balls[i]; } // update simulation public void next() { for (int i = 0; i < balls.length; i++) { Orb orb = balls[i]; move(orb); } // reset all collided flags for (int i = 0; i < balls.length; i++) { balls[i].collided = false; } } public void move(Orb orb) { // velocity moves orb orb.x += orb.v.x / TIME_DIVISION; orb.y += orb.v.y / TIME_DIVISION; // check for collisions with other orbs (or wall) for (int i = 0; !orb.collided && i < balls.length; i++) { if (orb == balls[i]) continue; if (orb.isIntersecting(balls[i], radius)) { // touching orb.collide(balls[i]); } while (orb.isIntersecting(balls[i], radius)) { move(orb); move(balls[i]); } } // check if we've run into a wall if ((orb.x - radius < 0) || ((orb.x) > width)) { orb.x = (orb.x - radius) < 0 ? radius : width; orb.v.x *= -1; } if ((orb.y - radius < 0) || ((orb.y) > height)) { orb.y = (orb.y - radius) < 0 ? radius : height; orb.v.y *= -1; } } private Vector2D randomPoint(int width, int height) { return new Vector2D((Math.random() * width) - radius, (Math.random() * height) - radius); } /** * Returns a random number between -MAX_SPEED and MAX_SPEED, inclusive, but * excluding 0. */ private Vector2D randomVelocity() { double x = (Math.random() * MAX_SPEED) + 1; if (Math.random() > 0.5) { x = -x; } double y = (Math.random() * MAX_SPEED) + 1; if (Math.random() > 0.5) { y = -y; } return new Vector2D(x, y); } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public void setNumberOfOrbs(int size) { logger.info("set number of orbs to " + size); balls = new Orb[size]; for (int i = 0; i < balls.length; ++i) { Vector2D center = randomPoint(width, height); balls[i] = new Orb(center.x, center.y, randomVelocity(), MASS); } } }