| 6.170 | Laboratory in Software Engineering
Spring 2000 Problem Set 6: GizmoBall April 10, 2000: Preliminary Design due April 24, 2000: Initial Release due May 8, 2000: Implementation and Critique due No late projects accepted! May 9-11, 2000: Demonstration |
The advantage of GizmoBall over a traditional pinball machine is that GizmoBall allows users to construct their own machine layout. In fact, GizmoBall is more than just a pinball game because the user can use it to build complicated "Rube Goldberg" contraptions, with lots of moving gizmos, which are intended to be watched rather than played. (If you don't know what a Rube Goldberg machine is, check out one of these sites: http://www.anl.gov/OPA/rube/index.html or http://www.rube-goldberg.com).
You may reuse code from your work earlier in this semester. With the
exception of the standard Java libraries, do not
incorporate any other code in your project. If in doubt, check with your TA.
While borrowing code from others is usually good software engineering
practice, in this project it will be considered cheating.
| Stage | Due date | % of project grade | Graded on |
|---|---|---|---|
| Preliminary design | April 10 |
|
Have you identified the issues? |
| Weekly meetings
with TA |
April 11-May 4 |
|
Participation of all team members. |
| Initial Release | April 24 |
|
Is it a good design? Is the required functionality present? |
| Design Critique | May 8 |
|
Are the tradeoffs & alternatives thoroughly analyzed? |
| Implementation &
test |
May 8 |
|
Does it work, have you demonstrated that it works? |
The final report is due by 4:30 pm on May 8, 2000. Because of end of term constraints, late assignments will not be accepted.
GizmoBall has a graphical user interface that allows a user to:
The picture above illustrates the most important features of GizmoBall. First a gizmo palette on the side provides the user with a variety of operations (square, circle, triangle, flipper) for placing gizmos in the playing area. Next a "modifications" toolbar on the bottom provides the user with a variety of operations (move, delete, rotate) for editing the gizmos in the playing area.
Note, in particular, that the modifications toolbar provides a connect button. After this button is pressed the user can connect gizmos together. For example, the user might click on one of the flippers, and then on one of the circular bumpers. This indicates that every time the bumper is hit, the flipper will move. Alternatively, the user might click on one of the flippers and then hit one of the keys on the keyboard. This indicates that every time the user presses that key the flipper will move. Several triggers might activate the same flipper.
In addition, in the example, there is a blue bar across the bottom of the playing area called the absorber gizmo. This gizmo "eats" the ball when the ball crosses it, and then holds the ball in the lower right hand corner of the playing area. The absorber gizmo also has an action associated with it, such that if the absorber is holding the ball and the absorber's action is triggered, the absorber will shoot the ball straight up in the direction of top of the playing area.
Finally, there is a menu at the top of the window. The buttons on the menu allow the user to save or load game configurations and also to run or stop the game. In the picture a game is in progress: the ball is the small red circle near the upper right hand corner. It has just hit one of the green circular bumpers and is heading up toward one of the magenta flippers.
It should be possible for you to express your final design in under 20 pages. In addition to the sections from the preliminary design, the final design contains the following.
It is vitally important that your TA have versions of the descriptive parts of the Revised Specification, Implementation Overview, and Validation Strategy that accurately describe your submitted code and what you actually did for testing or validation. If the description is not accurate, the submission will not be graded accurately.
Judging will be done initially by the TAs and final judgements will be made by the lecturers. One project can win multiple prizes. Winners will be announced at the last class on May 11.
We have also provided you with a library of physics routines for calculating the dynamics of elastic collisions. You are welcome to use this code as is, or modify it in any way that you like.
Setup:
You should make sure that all members of your group can compile and execute the demo GUI.
The animation example and the physics library will be available in /mit/6.170/src/ps6 sometime soon. We will provide specific instructions for downloading these resources.
The specifications for the physics library are also provided at the end of this document.
For many of you, GizmoBall is the first large software engineering project you have to do in a team. You will be surprised at how challenging it is to keep the separate changes made by team members integrated into a single version of the source code. An automated tool that helps with this problem is called a revision control package. We strongly recommend that you use one.
The most widely used (free) revision control package is the Concurrent Version Control (CVS). CVS is available on Athena. If you work at home on a Linux machine, it probably has CVS installed already. For Windows machines, download WinCVS from http://www.wincvs.org/. For Macs, download MacCVS from http://www.maccvs.org/.
Athena provides an extensive CVS manual. Use the command info cvs to access the manual. You will want to read the sections "Starting a new project" and "Overview/A sample session" to get started. Additionally, if one or more of your group members wants to work from home, you will want to read the section on "Repository/Remote repositories."
Additional information is available from http://www.mit.edu/iap/unixdev/www/cvs.html and http://www.gnu.org/manual/cvs-1.9/cvs.html.
Another tool we strongly recommend you use is called make. This tool allows you to write a makefile which is a model of your system: which files contain code, what work needs to be done to compile the system, what work needs to be done to run your tests, what work needs to be done to clean up the directory, etc. Once you have written the makefile, you can do any of these tasks by typing a single command.
On athena, type info make.

INFORMAL DESCRIPTION
Gizmoball files are command scripts. The syntax is, perhaps, somewhat richer than one might design for a simple game, but we also wanted the file format to be usable for debugging and testing the program independently of the GUI. That is, the file format specifies a standard interface that everyone must implement, so that the TAs can test the functionality of your program. As such, the files specify commands for exercising all the functionality of your program, including deleting and modifying gizmos, not just a list of gizmos and their positions.
Each Gizmoball file is made up of multiple lines. Each line represents a different command. Each command is made up of an opcode and zero or more arguments. For example:
Triangle 0 7This is a single command. It's opcode is "Triangle" and its arguments are "0" and "7". This command specifies that the program should create a new triangular bumper at the location <0,7>. There are similar commands for creating square and circular bumpers and flippers.
The syntax of Gizmoball files is designed to be easy for your program to read. Each command lives on a seperate line so that you can use the BufferedReader.readLine() method to read in each command. The tokens of each command are seperated by spaces or tabs so you can use the StringTokenizer class to break up each line into its constituent parts.
Notice that the Triangle command doesn't specify a rotation for the triangle. Instead, the triangle command specifies that the triangle should be placed at a default rotation, and if you want the triangle at a different rotation you need to use the "Rotate" command:
Triangle 3 5 Rotate 3 5 Rotate 3 5This creates a triangle bumper at position <3,5> and then rotates it twice by 90 degrees in the clockwise direction, for a total rotation of 180 degrees. Along with the Rotate command, there are also commands for moving gizmos and deleting gizmos. For example:
Square 10 2 Square 15 15 Delete 10 2In this example we create a square bumper at <10,2>, another at <15,15> and then delete the square bumper at <10,2>, leaving one square bumper at <15,15>.
There are also commands for connecting triggers to actions. For example:
Square 13 13 LeftFlipper 5 18 Connect 5 18 13 13This creates a square bumper at <13,13> and a left handed flipper at <5,18>. Then the "Connect" command specifies that the flippers action should be triggered whenever the ball hits the square bumper.
You can also specify that the action of a gizmo is associated with a particular key being pressed or released with the KeyConnect command:
RightFlipper 9 18 KeyConnect 9 18 32This specifies that the right handed flipper at <9,18> should be activated whenever the space bar key is pressed or released ("32" is the symbol number that the Java AWT gives to the space bar).
Because you might also want to allow the absorber and outer walls to trigger various actions, there are special position markers for those gizmos:
KeyConnect Absorber 127 Connect 9 18 OuterWallsThis set of commands would cause the absorbers actions to be triggered by key 127 (the "Delete" key) and would have the ball hitting any of the outer walls trigger the action of the gizmo at <9,18>.
The final command in the gizmoball file allows you to specify the position and velocity of the ball. Because the ball can be at intermediate points within a particular square, the coordinates are specified as floating point numbers:
Ball 14.2 4.5 -3.4 -2.3Here is the gizmoball file for the example shown above. It specifies a triangular bumper in the upper right hand corner, a bunch of circular and square bumpers and a few flippers. The action of the upper flippers is triggered by the "space" key, the action of the lower flippers are triggered by the "q" and "w" keys, and also by hitting some of the circular bumpers. The action of the absorber is triggered both by the "delete" key and also by the absorber itself! This allows the game to run continuously. Every time the ball hits the absorber, the absorber immediately shoots it back up towards the top again.
Triangle 19 0 Rotate 19 0 Square 0 2 Square 1 2 Square 2 2 Square 3 2 Square 4 2 Square 5 2 Square 6 2 Square 7 2 Square 8 2 Square 13 2 Square 14 2 Square 15 2 Square 16 2 Square 17 2 Square 18 2 Circle 4 3 Circle 5 4 Circle 6 5 Circle 7 6 Circle 9 9 Circle 10 9 Circle 11 10 Circle 12 9 Circle 13 9 Circle 15 6 Circle 16 5 Circle 17 4 Circle 18 3 LeftFlipper 9 2 KeyConnect 9 2 32 RightFlipper 11 2 Rotate 11 2 KeyConnect 11 2 32 LeftFlipper 8 7 KeyConnect 8 7 81 Connect 8 7 4 3 Connect 8 7 5 4 Connect 8 7 6 5 Connect 8 7 7 6 Connect 8 7 10 9 Connect 8 7 11 10 Connect 8 7 13 9 RightFlipper 14 7 Rotate 14 7 KeyConnect 14 7 87 Connect 14 7 9 9 Connect 14 7 11 10 Connect 14 7 12 9 Connect 14 7 15 6 Connect 14 7 16 5 Connect 14 7 17 4 Connect 14 7 18 3 KeyConnect Absorber 127 Connect Absorber Absorber
FORMAL SYNTAX
<file> ::= <request>* <request> ::= <command>"\n" <command> ::= <gizmoOp> COORDINATE COORDINATE | Rotate <position> | Delete <position> | Move <position> COORDINATE COORDINATE | Connect <position> <position> | KeyConnect <position> KEYID | Ball FLOAT FLOAT FLOAT FLOAT <gizmoOp> ::= Square | Circle | Triangle | RightFlipper | LeftFlipper <position> ::= COORDINATE COORDINATE | Absorber | OuterWalls COORDINATE represents any integer FLOAT represents any floating point number GizmoBall keywords are case insensitive.
Square XCoord YCoord Circle XCoord YCoord Triangle XCoord YCoord RightFlipper XCoord YCoord LeftFlipper XCoord YCoordCreates the appropriate gizmo at the specified coordinates, in the default orientation. The default orientation for each gizmo is:
Rotate <position>Performs a 90 degree clockwise rotation on the gizmo at the specified position. Note that some gizmos (like the Absorber and the OuterWalls) can not be rotated.
Delete <position>Deletes the gizmo at the specified position. After this operation, this gizmo will no longer exist.
Move <position1> XCoord YCoordMoves the gizmo from <position1> to <XCoord, YCoord>.
Connect <consumer-position> <producer-position>Makes the gizmo at <consumer-position> a consumer of the triggers produced by the gizmo at <producer-position>. That is, every time the ball hits the producer gizmo, the consumer's action will happen. <consumer-position> and a <producer-position> can each be coordinate pairs, "Absorber", or "OuterWalls".
KeyConnect <position> KeyIDMakes the gizmo at <position> a consumer of the trigger produced when the key KeyID is pressed or released.
(1) The intended use of the Geometry library is as follows: Suppose that all the objects in the scene are called "Bouncers". First the timeUntilCollision() methods are called to calculate the time at which the ball will collide with each of the Bouncers. The minimum of all these times (call it "mintime") is the time of the next collision. Next the client must update the position of the ball and all the Bouncers to mintime. At this point the ball and the Bouncer it is about to hit are exactly adjacent to one another. Now the client calls the appropriate reflect() method to calculate the changes to the ball's velocity vector. Finally the client updates the ball's velocity vector, and then repeats the entire process.
(2) The methods here for dealing with line segments do NOT deal with the end-points of the line segment. To properly handle this in your Gizmoball game, you will need to make each of your shapes out of a combination of line segments with 0-radius circles at the end points. For example: if you have two line segments, one between the points <1,1>,<1,2> and the other from <1,1>,<2,1> and a ball is approaching from <0,0> in the <1,1> direction, it will hit the ends of both the line segments at a 45 degree angle and something REALLY WEIRD will happen. But if you put a little tiny (radius 0) circle at <1,1>, then the ball will bounce off the circle in the expected manner.
(3) The Geometry package is dependant on the java.awt.geom package. It uses objects Point2D.Double and Line2D.Double. These types are mutable, so be careful when using them in your code.
public class Angle {
// Overview: This immutable abstract data type represents the
// mathematical notion of an angle.
//
// Abstraction Function: The angle <a> such that cos(a) = cosine and
// sin(a) = sine
//
// Rep. Invariant: cosine^2 + sine^2 = 1
//
// Rep. Rationale: In most of the math we use here we start in
// cartesian coordinates, so calculating sine and cosine is
// relatively efficient (just a sqrt and a division). Finding the
// angle in terms of arcsin and arccos would be very slow. On the
// other hand, adding and subtracting angles that are represented
// this way can be done relatively efficiently using standard
// trig. identities.
// useful constants
static public Angle zero = new Angle(1.0, 0.0);
static public Angle piOverFour = new Angle(Math.sqrt(0.5), Math.sqrt(0.5));
static public Angle piOverTwo = new Angle(0.0, 1.0);
static public Angle Pi = new Angle(-1.0, 0.0);
static public Angle threePiOverTwo = new Angle(0.0, -1.0);
static public Angle twoPi = zero;
// CREATORS:
public Angle()
// effects: initializes this to be the angle with 0 radians
public Angle(double a)
// effects: initializes this to be the angle with <a> radians
public Angle(Angle a)
// effects: initializes this to be a copy of Angle <a>
public Angle(double c, double s)
// effects: initializes this to be the angle with cosine c and sine s
public Angle(double x, double y, double z)
// effects: initializes this to be the angle at the corner of
// x and z for the right triangle (with the corner of
// sides x and y being 90 degree)
// OBSERVERS:
public String toString()
public int hashCode()
public boolean equals(Angle a)
public boolean equals(Object o)
public double cos()
// effects: returns the cosine of this
public double sin()
// effects: returns the sine of this
public double tan()
// effects: returns the tangent of this
public boolean greater(Angle c)
// effects: returns true if and only if <this> is a bigger angle than <c>.
public boolean between(Angle a, Angle b)
// effects: returns true when this angle is contained in the arc swept out
// starting at angle a and ending before angle b.
// PRODUCERS:
public Angle plus(Angle a)
// effects: returns the angle <this> + <a>
public Angle minus(Angle a)
// effects: returns the angle <this> - <a>
}
public class Circle {
/* Overview: This mutable abstract data type represents a
* mathmatical circle in two dimensions. The circle has a center
* and a radius.
*/
// Constructors -----------------------------------
public Circle(double cx, double cy, double r)
/* effects: Creates a Circle at location (cx, cy)
* with radius <r>
*/
public Circle(Point2D.Double center, double r)
/* effects: Creates a Circle at location <center>
* with radius <r>
*/
// Observers --------------------------------------
public Point2D.Double getCenter()
/* effects: Return the center of this circle
*/
public double getRadius()
/* effects: Return the radius of this circle
*/
// Mutators --------------------------------------
public void translate(double dx, double dy)
/* modifies: this
/* effects: this_post is the Circle <this> + (dx, dy)
*/
}
public class Vect
// Overview: This immutable abstract data type represents the
// mathematical notion of a vector in 2-space.
//
// Abstraction Function: The vector in the cartesian plane with
// angle to the horizontal equal to theta and length equal to r.
//
// Rep. Invariant: r >= 0.0
//
// Rep. Rationale: Our Angle rep. can do addition relatively
// inexpensively and sin() and cos() for free, so this rep. makes it
// cheap to move back and forth between polar and cartesian
// coordinates.
// useful constants
static public Vect zero = new Vect(Angle.zero, 0.0);
static public Vect one = new Vect(Angle.zero, 1.0);
// CREATORS:
public Vect(Angle a)
// effects: initializes this to be a unit vector in the direction of <a>.
public Vect(Angle a, double l)
// effects: initializes this to the vector with angle <a> and length <l>.
public Vect(double x, double y)
// effects: initializes this to the vector in Cartesian space with
// coordinates <x,y>.
public Vect(double x1, double y1, double x2, double y2)
// effects: initializes this to the vector in Cartesian space from
// the point <x1,y1> to the point <x2,y2>
// OBSERVERS:
public Angle angle()
// effects: returns the angle of <this> in polar coordinates
public double length()
// effects: returns the length of <this>
public double x()
// effects: returns the horizontal coordinate of <this> in
// Cartesian coordinates
public double y()
// effects: returns the vertical coordinate of <this> in Cartesian
// coordinates
public boolean equals(Vect b)
public boolean equals(Object o)
public String toString()
public int hashCode()
public double distanceSquared(Vect b)
// effects: returns the distance between <this> and <b>
// PRODUCERS:
public Vect plus(Vect b)
// effects: returns the new vector that is the sum of <this> and <b>
public Vect minus(Vect b)
// effects: returns the new vector that is the difference of
// <this> and <b>
public Vect rotateBy(Angle a)
// effects: returns the new vector that is <this> rotated around
// the origin by angle <a>.
public Vect neg()
// effects: returns the new vector that is this rotated by Pi radians
public Vect times(double amt)
// effects: returns the new vector with length scaled by <amt>
public Vect projectOn(Vect b)
// effects: returns a new vector, <c>, that represents the
// projection of <this> onto <b>. That is, the new vector has the
// same angle as <b>, but its length will be such that <this> -
// <c> is perpendicular to <c>.
}
public class Geometry {
public static class NoRealSolution extends Exception { }
public static double minQuadraticSolution(double a,
double b,
double c)
throws NoRealSolution
// effects: Solves the quadratic equation ax^2 + bx + c = 0 and of
// the two solutions x1 and x2, returns the smaller. Unless,
// there is no solution to the equation => throws NoRealSolution.
static public Vect distanceSquared(Point2D.Double p1, Point2D.Double p2, Point2D.Double point)
/* requires: Line from <p1> to <p2> defines a line segment of
* non-zero length.
*
* effects: given the line segment <p1>-<p2> and the <point>,
* this method transforms the coordinates of <point> into
* a vector in the space given by
* <fraction-of-the-way-along-the-line-from <p1>
* to <p2> / perpendicular-distance-from-point-to-line-
* (squared)>.
*/
static public Vect perpendicularPoint(Line2D.Double line,
Vect transform)
/* requires: <line> defines a line segment of non-zero
* length.
*
* effects: given the line segment <line> and a <transform>
* calculated by the distanceSquared() method, returns
* the perpendicular point <x,y> along the line segment.
*/
public static double timeUntilWallCollision(Line2D.Double line,
Circle ball,
Vect velocity)
throws CollisionMissException
/* requires: <line> defines a line segment of non-zero
* length.
*
* effects: given a line segment <line> and a moving
* <ball> at <velocity>, we return the time (with now being
* time 0) at which the ball and the line segment first collide.
* UNLESS <ball> and <line> never collide
* => throws CollisionMissException
*
* NOTE: This method calculates only the point at which the ball
* will collide with the LINE through the given points. It does
* NOT deal correctly with end-point effects. To deal with that
* problem, you should also calculate timeUntilCollision for two
* zero-radius circles at the end-points
*/
public static Vect reflectWall(Line2D.Double line,
Vect velocity)
/* requires: <line> defines a line segment of non-zero length.
*
* effects: given a wall at <line> and a ball directly adjacent
* to the wall between the endpoints. Given that the ball
* hits the wall with relative velocity <velocity>, returns
* the new relative velocity of the ball after it bounces
* off the wall.
*/
static public double distanceSquared(Point2D.Double p1, Point2D.Double p2)
/* effects: returns the distance between the points <x,y> and <a,b>
*/
static public double timeUntilCircleCollision(Circle circle,
Circle ball,
Vect velocity)
throws CollisionMissException
/* requires: the radii of <circle> and <ball> >= 0.0
*
* effects: given a circle <x,y,r1> and a moving ball <a,b,r2>,
* with relative velocity given by <va,vb>, we return the time
* (with now being time 0) at which the ball and the circle
* first collide.
* UNLESS,
* <ball> never collides with <circle>,
* => throws a CollisionMissException
*/
public static Vect reflectCircle(Point2D.Double circlePoint,
Point2D.Double ballPoint,
Vect velocity)
/* requires: the distance from <x,y> to <a,b> is approximately
* equal to the sum of the radii of the circle and ball.
*
* effects: given a circle at <x,y> and a ball which is at point
* <a,b> and moving with relative velocity <velocity>, returns the
* new relative velocity of the ball after it bounces off
* the circle (which stays fixed).
*/
public static Vect rotateAround(Point2D.Double p1, Point2D.Double p2, Angle a)
/* effects: returns a new point with <p1> rotated around <p2>
* by angle a
*/
public static double timeUntilRotatingWallCollision(Point2D.Double p1, Point2D.Double p2,
Point2D.Double center,
double angularVelocity,
double startTime,
Circle ball,
Vect velocity)
throws CollisionMissException, NoCollisionYetException
/* requires: <p1>-<p2> defines a line segment of non-zero
* length. In addition, to avoid numerical errors
* (angularVelocity * startTime) should be in the
* range 0.0->2 PI.
*
* effects: given a line through the line <p1>-<p2>, where
* <p2> is rotating around the point <center>. Assume that the
* line has been rotating with angular velocity <angularVelocity>
* (given in radians per time unit) for an amount of time given by
* <startTime>. Now, given a moving <ball> with velocity relative
* to <center> given by the vector <velocity>. We return the time
* (with now being time 0) at which the ball and the line segment
* first collide.
* UNLESS,
* Ball doesn't collide with wall ever if they stay with their
* current trajectories
* => throws CollisionMissException
* Ball doesn't collide within the next time unit
* => throws NoCollisionYetException.
*
* notes: This method calculates only the point at which the <ball>
* will collide with the LINE through the given points. It does
* NOT deal correctly with end-point effects. To deal with that
* problem, you should also calculate timeUntilCollision for two
* zero-radius circles at the end-points.
*/
public static Vect reflectRotatingWall(Point2D.Double p1, Point2D.Double p2,
Point2D.Double center,
double angularVelocity,
double rotationTime,
Circle ball,
Vect velocity)
/* requires: <p1>-<p2> defines a line segment of non-zero
* length. In addition, to avoid numerical errors
* (angularVelocity * startTime) should be in the
* range 0.0->2 PI.
*
* effects: given a line through the line <p1>-<p2>, where
* <p2> is rotating around the point <center>. Assume that the
* line has been rotating with angular velocity <angularVelocity>
* (given in radians per time unit) for an amount of time given by
* <rotationTime>. Now, given a ball directly adjacent to the wall
* between the end-points, travelling with velocity <velocity>
* relative to <center>, returns the new relative velocity of the
* ball after it bounces off the wall. Because the wall is also
* moving, the ball may have a larger speed after hitting the wall
* than it did before. If the ball does not hit the wall between
* the endpoints then this routine does not change the ball
* velocity.
*/
public static double timeUntilRotatingCircleCollision(Circle circle,
Point2D.Double center,
double angularVelocity,
double startTime,
Circle ball,
Vect velocity)
throws CollisionMissException, NoCollisionYetException
/* requires: the radii >= 0.0. In addition, to avoid numerical
* errors (angularVelocity * startTime) should be in the range
* 0.0->2 PI.
*
* effects: given a <circle>, which is rotating around the
* <center>. Assume that the circle has been rotating with
* <angularVelocity> (given in radians per time unit) for an
* amount of time given by <startTime>. Now, given a moving
* <ball> with <velocity> relative to <center>, we return
* the time (with now being time) at which the <ball> and
* <circle> first collide.
* UNLESS,
* <ball> doesn't collide with <circle> ever if they stay with
* their current trajectories
* => throws CollisionMissException
* <ball> doesn't collide within the next time unit
* => throws NoCollisionYetException.
*/
public static Vect reflectRotatingCircle(Circle circle,
Point2D.Double center,
double angularVelocity,
double rotationTime,
Circle ball,
Vect velocity)
/* requires: the distance from center of <circle> to center of
* <ball> is approximately equal to the sum of the radii of
* the circle and ball. In addition, to avoid numerical
* errors (angularVelocity * rotationTime) should be in the
* range 0.0->2 PI.
*
* effects: given a <circle> which is rotating around the point
* <center>. Assume that the <circle> has been rotating with
* angular velocity <angularVelocity> (given in radians per time
* unit) for an amount of time given by <rotationTime>. Now,
* given a <ball> directly adjacent to the <circle> with
* velocity <velocity> relative to <center>, returns the new
* relative velocity of the <ball> after it bounces off the
* <circle>. Because the <circle> is also moving, the <ball>
* may have a larger speed after hitting the <circle> than it
* did before.
*/
public static Vect reflectEqualMass(Point2D.Double center1,
Vect initialVel,
Point2D.Double center2)
/* requires: the distance from point <x,y> to point <a,b> is
* approximately equal to radius of circle centered at <center1>
* + radius of circle centered at <center2>
*
* effects: given two balls of equal mass at <center1> and <center2>
* with relative velocities <initialVel> and <0,0> returns the
* new relative velocities.
*/
}
public class CollisionMissException extends Exception {
public CollisionMissException()
public CollisionMissException(String s)
}
public class NoCollisionYetException extends Exception {
public NoCollisionYetException()
public NoCollisionYetException(String s)
}
public class OverlapException extends Exception {
public OverlapException()
public OverlapException(String s)
}
Last modified: 2000-Mar-13 15:06:00 EST by rwpinder