| 6.170 | Laboratory in
Software Engineering Spring 2004 Final Project: Gizmoball Due: See Schedule |
Quick links:
Contents:
The advantage of Gizmoball over a traditional pinball machine is that Gizmoball allows users to construct their own machine layout by placing gizmos (such as bumpers, flippers, and absorbers) on the playing field. These machine layouts may also form complicated "Rube Goldberg" contraptions that are intended to be watched rather than played. (If you don't know what a Rube Goldberg machine is, see http://www.anl.gov/OPA/rube/index.html or http://www.rube-goldberg.com/). As an optional extension (after you have designed, documented, implemented, and tested all required functionality), you may create new varieties of gizmos that can be placed on a playing field.
Gizmoball has a graphical user interface with two modes, building mode and running mode.
In building mode, a user can:
![]() |
|
![]() |
![]() |
![]() |
|
The picture above illustrates the most important features of Gizmoball.
The purple bar across the bottom of the playing area is the absorber gizmo. When a ball enters the absorber, the ball stops moving and is held in the absorber's lower right-hand corner. The absorber gizmo's action is to shoot a ball it is holding (if any) straight up in the direction of the top of the playing area. Connecting the absorber to itself allows the game to loop continually: every time a ball enters the absorber, it is immediately shot out again.
The menu at the top of the window allows the user to save or load game configurations and to run or stop the game. In the animation, a game is in progress: the ball is the small blue circle which started in the lower right-hand corner. The ball bounces off the red, green, and blue bumpers, and is hit by the yellow flippers.
| Stage | Due date (subject to change) |
% of project grade | Graded on |
|---|---|---|---|
| Preliminary design | 4/13/2004 |
|
Have you identified the issues? |
| Weekly meetings with TA | 4/7/2004 - 5/7/2004 |
|
Did all of the team members participate constructively? |
| Preliminary Release | 4/27/2004 |
|
Is it a good design? Is the required functionality present? |
| Design Critique | 5/11/2004 |
|
Are the tradeoffs & alternatives thoroughly analyzed? |
| Implementation & test | 5/11/2004 |
|
Does it work? Have you demonstrated that it works? |
Each stage of this assignment should be handed in electronically and/or as hardcopy to your TA by 4:30 PM on its due date. All of the source and compiled code should be put online on 5/11/2004, in your team project directory.
The final report is due by 4:30 pm on 5/11/2004. Because of end of term constraints, late assignments will not be accepted.
The preliminary design must be submitted electronically by 4:30pm on the due date.
You should express your preliminary design in under 15 pages. Your document will be a subset of that described in the Documenting a Software System handout. It will include a revised specification, a design, and an implementation overview (possibly including code object model(s) and a module dependency diagram). You do not need to include information about your validation strategy.
The revised specification, design, and implementation overview must discuss, among other issues:
The preliminary design should also include a project plan, which lists milestones for the team and allocation of tasks to each team member. A milestone is what you expect to be done by some date, such as a tested module or a working feature -- an achievement that is objective, easy to evaluate, and significant. There must be at least two milestones in the project between the preliminary design and the final deadline. The division of labor should be equitable. (It is most useful to combine the milestones and the task allocation into a single table with "task", "who", and "when" columns, rather than making the milestones and task allocation into two separate documents which cannot be easily related.)
The preliminary design will be graded for clarity of expression and for whether you have thought rigorously about the problem, identified the major issues and challenges, and proposed a design that makes sense.
The final design is due two weeks before the final project due date. At this point, you should have found all major mistakes in your design. Therefore the final design will be graded on whether it is a good design, in addition to clarity of expression.
In order to demo what you had completed by the preliminary release deadline, even if the demo is slightly later and you have made modifications in the meanwhile, you must retain a copy of your code as it existed before the deadline. You can create a snapshot of your source and/or compiled code by using a jar file. Then, you can run the demo by placing the jarfile in your classpath, or by making the jar itself executable.
It is acceptable for you to run up to four separate Java programs to demonstrate the following four features:
Follow these steps to create the tag:
Later, if you wish to go back to the tagged version, run cvs update -r preliminary-release. This will put that revision in your workspace. You will not be able to commit from that workspace. If you wish to go back to the main trunk, run cvs update -A.
You should email your TA with the following information:
Your ta will run "cvs -d <your cvs root> co -r preliminary-release <your module>" and then follow your instructions to test the demo.
Put your code online in your team project directory. You do not need to turn in a printout of your code. In general, your group must turn in code that you wrote yourself. Therefore, you are generally not allowed to use third-party Java libraries. If you have some code that you found and you are unsure of whether or not you can use it, please see your TA. The following jars are automatically allowed, so you do not have to ask your TA if you can use them:
| javadoc6170.jar | javadoclet for 6.170 style tags |
| junit.jar | JUnit test suite |
| TableLayout.jar | library to aid in doing complex layouts |
| xercesImpl.jar, xml-apis.jar | libraries for XML parsing (consult your TA if you plan to use a different XML library) |
| swt.jar, jface.jar, runtime.jar | libraries for the SWT GUI toolkit (SWT is an alternative GUI toolkit to Swing. SWT will be allowed, but it is not recommended.) |
The final report includes a section on Design Changes. Detail what changes you have made to the design that was submitted on 4/27/2004. Be precise. 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.
For demonstrations (as described immediately below), you must also make a jar file of your implementation named /mit/6.170/groups/seMMN/final.jar. This file must be runnable and must include all of your code in both source and compiled form.
The final implementation and report are due by 4:30 pm on 5/11/2004. Because of end of term constraints, LATE ASSIGNMENTS WILL NOT BE ACCEPTED.
Judging will be done initially by the TAs and final judgments will be made by the lecturers. One project can win multiple prizes. Winners will be announced at the last class on 5/13/2004.
Animations in Java are quite challenging. You will use the
java.awt and javax.swing packages to
construct your graphical user interface (GUI). We have provided you
with a demonstration program in
Example.java
that shows how to animate the movement of a ball bouncing around the
window. It also demonstrates how to get your program to listen to user
events, such as clicking on a toolbar button, pressing a key or
dragging
the mouse. All members of your group should be able to compile and
execute this demo GUI.
We have also provided you with a library of physics routines (see Appendix 3) 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.
You should acquire background knowledge about Swing before attempting to code your GUI. You can see Sun's Swing tutorial (particularly the quick tour, overview, and painting sections). For further examples you may also consult the Manning book available online.
Do not try to use the realtime clock in
order to determine timing information. Instead, arrange to receive a
timer event every 1/framesPerSecond and proceed to do the simulation
and screen updates in response to this event. If you get behind and
time slows down, so be it. A simple way to set this up is do use the
javax.swing.Timer
class, as in the example GUI. Using
this approach will
simplify the implementation of your code and will also avoid the need
to deal with synchronization issues in a multi-threaded program.
If you are using Swing and wish to paint your own component, as you
will need to do in order to actually draw the board, gizmos, and ball,
you should extend
javax.swing.JComponent
and implement your own paint routines.
In order to do this you will need to override the
paint
method of your JComponent
to paint the board. The painting is done by calling methods on the
supplied
java.awt.Graphics
object. Unless you explicitly
turn it off, Swing components are automatically double-buffered to
reduce flicker. If you do not understand this, do not worry about it.
In addition to Graphics Java has an alternative graphics
context
java.awt.Graphics2D
which provides more
sophisticated capabilities than the traditional Graphics
object. Note that the calls your components receive to
paint(Graphics) will always have a
Graphics2D passed as the argument, so if you want to work
with Graphics2D, you may simply cast the
Graphics object. You may implement Gizmoball using
either style of graphics, but here are some
differences which you might want to consider:
Graphics object works in terms of integer
values
for pixels allowing you to more directly control which pixels are
updated. Graphics2D, on the other hand, accepts floating
point
values to define geometric shapes to be rendered and performs the
rasterization itself. This is somewhat more automatic, but also makes
it more difficult to directly set individual pixels. Graphics2D class also allows AffineTransforms
to be applied to it. (An affine
transform is a geometric transform that preserves parallel lines.) In order to respond to mouse and keyboard actions from the user you
will want to create and install
MouseListener,
MouseMotionListener, and
KeyListener
all of which can be found in the
java.awt.event
package.
Information about Java keycodes can be found in the documentation for
java.awt.event.KeyEvent.
The specifications for handling keyboard input in Gizmoball require that an object connected to a key is triggered when that key is pressed or released. This provides behavior similar to that of a real pinball game: hitting the button causes the flipper to swing upward and releasing the button causes the flipper to return to its rest position.
The Java specifications for
java.awt.event.KeyEvent
describe three types of key events, KEY_PRESSED,
KEY_TYPED, and KEY_RELEASED. The
documentation suggests that KEY_PRESSED events occur when
a key is actually depressed by the user and KEY_RELEASED
events occur when the key is released. It would therefore seem
reasonable to trigger when receiving a KEY_PRESSED or
KEY_RELEASED event for a given key bound to a gizmo.
Unfortunately, most Java runtime environments fire
multiple KEY_PRESSED and in some cases multiple
KEY_RELEASED events when the user has only pressed the
key once. Additionally, in some environments you may never receive
the KEY_RELEASED events for an upstroke. This is because
the behavior of KEY_PRESSED and KEY_RELEASED
is system dependent. The behavior occurs through an interaction with
the operating system's handling of key repeats that occur when you
hold down a key for a period of time.
On Windows, Java will produce multiple KEY_PRESSED
events as the key is held down and only one KEY_RELEASED
when the key is actually released. For example, holding down the 'A'
key will generate these events:
PRESSED 'A'
PRESSED 'A'
...
RELEASED 'A'
KEY_PRESSED and
KEY_RELEASED are received as the key is held down:
PRESSED 'A'
RELEASED 'A'
PRESSED 'A'
RELEASED 'A'
...
PRESSED 'A'
RELEASED 'A'
If you want to explore the behavior of your in your environment,
you can use the KeypressTest
class provided by the staff. The application will dump all keyboard
events to the console for inspection.
The source code is available at
KeypressTest.java
You should feel free to handle this nuance of the Java API as you
see fit. One easy solution is to shut off the operating system's
automatic
key press repeat mechanism and thereby cause the KEY_PRESSED
and KEY_RELEASED events to more closely correspond to the
actual actions of the user.
xset -r" to shut off
autorepeat. To re-enable autorepeat use "xset r" Accessibility Options applet.
On the Keyboard tab select the Settings...
button for FilterKeys.
Select Ignore quick keystrokes and slow down the repear rate.
Select the Settings... button next to that option.
Make sure No keyboard repeat is selected.
Slide the SlowKeys slider to Short (0.00).
Press OK twice.
Check Use FilterKeys and press OK. To enable and disable
these changes, simply check or uncheck the UseFilterKeys
checkbox. An alternative solution
is to take advantage of a special key listener
decorator provided by the staff. The class is available in compiled
form in the gb-lib.jar file as
staffui.MagicKeyListener. Refer to the
documentation for
MagicKeyListener or use the
provided source
code as your own starting point.
To learn more about jar files, review the jar tool manual from Sun.
As a quick reference, here are a few sample uses of the jar command:
To create gizmo.jar from classes in packages gizmo and ball:
jar cvf gizmo.jar gizmo ballTo list the contents of the jar file, use:
jar tf gizmo.jarTo create a runnable gizmo.jar
jar cvfm gizmo.jar JarMainManifest gizmo ballIn the example above, the file JarMainManifest should contain a single line which names the entry point:
Main-Class: gizmo.StartGizmoballTo run the application using the jar file, use:
java -jar gizmo.jarImportant: Note that, when using the -jar option to run an application, the CLASSPATH variable and the -cp command line switch are ignored. Therefore, to include the physics library in an application stored in a runnable jar, you will have to extract the .class files from our jar, and include them in your own. You can extract a jar file into the current directory this way:
jar xvf /mit/6.170/lib/gb-lib.jar
Using a Makefile, as described the section above, can simplify and automate the creation of jar files. Given the complexity and maintenance issues involved with merging the physics class files in with your application, we recommend the use of a Makefile to automate the process.
Your implementation must support two modes of execution: building and running. In building mode, the user can add gizmos to the playing area and can modify the existing ones. In running mode, a ball moves around the playing area and interacts with the gizmos.
To describe dimensions in the playing area, we define L be the basic distance unit, equal to the edge length of a square bumper. Corresponding to standard usage in the graphics community, the origin is in the UPPER left-hand corner with coordinates increasing to the right and DOWN.
The playing area must be at least 20 L wide by 20 L high. That is, 400 square bumpers could be placed on the playing area without overlapping. The upper left corner is (0,0) and the lower right corner is (20,20). When we say a gizmo is at a particular location, that means that the gizmo's origin is at that location. The origin of each of the standard gizmos is the upper left-hand corner of its bounding box, so the location furthest from the origin at which a gizmo may be placed is (19,19) on a 20L x 20L board. The origin of a ball is at its center.
During building mode, Gizmos should "snap" to a 1 L by 1 L grid. That is, a user may only place gizmos at locations (0,0), (0,1), (0,2), and so on.
During running mode the animation grid may be no coarser than 0.05 L by 0.05 L. Suppose that the ball is at (1,1) and is moving in the (1,0) direction -- that is, left to right -- at a rate of .05L per frame redraw. Then the ball should be displayed at least in positions (1,1), (1.05,1), (1.10,1), and can be displayed at more positions if you wish the animation to be smoother. Rotating flippers can be animated somewhat more coarsely; see the precise description of flippers below. If the ball is moving faster than the animation grid size per frame redraw, it need not be redrawn in each animation grid position.
In building mode the user can:
In running mode, the user can:
In running mode, Gizmoball should:
There are seven standard gizmos that must be supported: bumpers (square, circular, and triangular), flippers (left and right), absorbers, and outer walls.
A coefficient of reflection of 1.0 means that the energy of the ball leaving the bumper is equal to the energy with which it hit the bumper, but the ball is traveling in a different direction. As an extension, you may support bumpers with coefficients above or below 1.0 as well.
A square shape with edge length 1L
Trigger: generated whenever the ball hits it
Action: none required
Coefficient of reflection: 1.0
A circular shape with diameter 1L
Trigger: generated whenever the ball hits it
Action: none required
Coefficient of reflection: 1.0
A right-triangular shape with sides of length 1L and hypotenuse of
length Sqrt(2)L
Trigger: generated whenever the ball hits it
Action: none required
Coefficient of reflection: 1.0
Flippers are required to come in two different varieties, left flippers and right flippers. A left flipper begins its rotation in a counter-clockwise and a right flipper begins its rotation in a clockwise direction.
During run mode, a flipper should never extend outside its bounding box. In edit mode the flipper should not be permitted to be placed in any way which would cause the flipper to extend outside of its bounding box during run mode, or would cause the flipper's bounding box to overlap with (the bounding box of) another gizmo.
The below pictures show flipper placements for various initial rotations. In run-mode, when a flipper is first triggered, it sweeps 90° in the direction indicated by the arrows. If triggered again, the flipper sweeps back 90° to the initial position.
In the pictures, the shape and design of the flippers are for illustrative purpose only -- your final design may differ.

Flipper initial placements and initial directions of rotation.
As with the three standard bumpers, a flipper generates a trigger whenever the ball hits it.
When a flipper's action is triggered, the flipper rotates at a constant angular velocity of 1080 degrees per second to a position 90 degrees away from its starting position. When its action is triggered a second time, the flipper rotates back to its original position at an angular velocity of 1080 degrees per second.
If its action is triggered while the flipper is rotating, the exact behavior is at your discretion. Here are some suggestions, but you are not limited to these options:
The standard coefficient of reflection for a flipper is 0.95. However, when computing the behavior of a ball bouncing off the flipper, you must account for the linear velocity of the part of the flipper that contacts the ball; therefore the ball may leave the flipper with a higher energy than it had when it reached it.
When a ball hits an absorber, the absorber stops the ball and holds it (unmoving) in the bottom right-hand corner of the absorber. The ball's center is .25L from the bottom of the absorber and .25L from the right side of the absorber.
If the absorber is holding a ball, then the action of an absorber, when it is triggered, is to shoot the ball straight upwards in the direction of the top of the playing area. By default, the initial velocity of the ball should be 50L/sec. (With the default gravity and the default values for friction, the value of 50L/sec gives the ball enough energy to lightly collide with the top wall, if the bottom of the absorber is at y=20L.) If the absorber is not holding the ball, or if the previously ejected ball has not yet left the absorber, then the absorber takes no action when it receives a trigger signal.
Absorbers cannot be rotated.
A Gizmoball game supports exactly one set of outer walls. The user cannot move, delete, or rotate the outer walls. The outer walls lie just outside the playing area:
It is not required that the user be able to use the GUI to connect the trigger produced by the outer walls with any of the other gizmos. However, the standard file format does support this kind of connection.
But before Xerces can create these Java objects, it makes sure that the file it is reading in validates against an XML Schema. An XML Schema is a file written in XML that defines the desired format for other XML files. In ps6.reader, you can find several examples of schemas, each of which has a .xsd file extension. These schemas define the formats for the .xml files found in each Traffick database.
We provide you with an XML Schema gb_level.xsd that defines the text format for a level of gizmoball that your application must be able to load and save to. Any XML file that does not validate against the schema should be rejected by your application, and an appropriate error message should be displayed to the user.
If you are new to XML, then you may first want to read the w3schools tutorial on XML. Before writing the code that validates and reads in a gizmoball level file, we recommend that you look at ps6.reader.TraffickReader for an example of how to validate an XML file against a schema in Java, and how to use it to create Java objects from the XML. Thus, we also recommend that you include xercesImpl.jar and xml-apis.jar in your project as we have in Problem Set 6. Finally, take note of the convenience methods in ps6.reader.TraffickReader named getXXXFromAttribute() as well as the class ps6.reader.NodeElementIterator. These will help you discard unnecessary information returned to you by Xerces.
The API for Xerces is located at http://xml.apache.org/xerces2-j/javadocs/api/index.html, but a good example of the parser in action is available at http://xml.apache.org/~edwingo/jaxp-ri-1.2.0-fcs/docs/samples.html.
The following is an example of a very simple gizmoball level file:
<board>
<ball name="Ball" x="1.8" y="4.5" xVelocity="-3.4" yVelocity="-2.3" />
<gizmos>
<squareBumper name="Square" x="0" y="2" />
<circleBumper name="Circle" x="4" y="3" />
<triangleBumper name="Tri" x="1" y="1" orientation="270" />
<leftFlipper name="FlipL" x="10" y="7" orientation="0" />
<rightFlipper name="FlipR" x="12" y="7" orientation="0" />
<absorber name="Abs" x="0" y="19" width="20" height="1" />
</gizmos>
<connections>
<connect sourceGizmo="Square" targetGizmo="FlipL" />
<keyConnect key="81" keyDirection="up" targetGizmo="Abs" />
</connections>
</board>
The ball tag specifies the initial 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. For example:
<ball name="Ball" x="1.8" y="4.5" xVelocity="-3.4" yVelocity="-2.3" />places a ball with name Ball, center at (1.8,4.5), and an initial velocity of 3.4L per second to the left and 2.3L per second upward.
Each gizmo has a name and a location (x and y coordinates) where it will be placed. The triangleBumper and the flippers all require an orientation. This orientation can be "0", "90", "180", or "270" degrees, and refers to the clockwise rotation of the gizmo.
Triggers can be connected to actions with the connect tag. In the example above, FlipL's action will be triggered whenever the ball hits the bumper named Square.
The keyConnect tag specifies that the action of a gizmo is associated with a particular key being pressed or released. For example:
<keyConnect key="81" keyDirection="up" targetGizmo="Abs" />specifies that the gizmo named "Abs" should be activated whenever the space bar key is released ("32" is the decimal number that represents a space in ascii). Type man ascii and scroll down to the "Decimal" section to view all the mappings from decimal numbers to ascii characters).
Because you might also want to allow the outer walls to trigger various actions, the special identifier "OuterWalls" is reserved for it:
<connect sourceGizmo="OuterWalls" targetGizmo="GIZ" />This command would cause the ball hitting any of the outer walls trigger the action of the gizmo named by "GIZ".
The main board tag can optionally take arguments for gravity and friction. If the board was described with:
<board gravity="16.0" friction1="0.0" friction2="0.0">the gravity in the game would be reduced to only 16L/sec2 and all effects of friction would be removed.
Here are the contents of the gizmoball file for the example shown at the beginning of this document. It specifies a triangular bumper in the upper right-hand corner, a bunch of circular and square bumpers, and a few flippers. The actions of the upper flippers are triggered by the "space" (ascii 32) key, the actions of the lower flippers are triggered by the "q" (ascii 81) and "w" (ascii 87) keys, and also by hitting some of the circular bumpers. The action of the absorber is triggered both by the "delete" key (ascii 127) and also by the absorber itself! This allows the game to run continuously. Every time the ball hits the absorber, the absorber immediately shoots the ball back upwards again.
<board>
<ball name="Ball" x="1.0" y="11.0" xVelocity="0.0" yVelocity="0.0" />
<gizmos>
<squareBumper name="S02" x="0" y="2" />
<squareBumper name="S12" x="1" y="2" />
<squareBumper name="S22" x="2" y="2" />
<squareBumper name="S32" x="3" y="2" />
<squareBumper name="S42" x="4" y="2" />
<squareBumper name="S52" x="5" y="2" />
<squareBumper name="S62" x="6" y="2" />
<squareBumper name="S72" x="7" y="2" />
<squareBumper name="S82" x="8" y="2" />
<squareBumper name="S132" x="13" y="2" />
<squareBumper name="S142" x="14" y="2" />
<squareBumper name="S152" x="15" y="2" />
<squareBumper name="S162" x="16" y="2" />
<squareBumper name="S172" x="17" y="2" />
<squareBumper name="S182" x="18" y="2" />
<circleBumper name="C43" x="4" y="3" />
<circleBumper name="C54" x="5" y="4" />
<circleBumper name="C65" x="6" y="5" />
<circleBumper name="C76" x="7" y="6" />
<circleBumper name="C99" x="9" y="9" />
<circleBumper name="C109" x="10" y="9" />
<circleBumper name="C1110" x="11" y="10" />
<circleBumper name="C129" x="12" y="9" />
<circleBumper name="C139" x="13" y="9" />
<circleBumper name="C156" x="15" y="6" />
<circleBumper name="C165" x="16" y="5" />
<circleBumper name="C174" x="17" y="4" />
<circleBumper name="C183" x="18" y="3" />
<triangleBumper name="T" x="19" y="0" orientation="90" />
<triangleBumper name="T2" x="1" y="1" orientation="0" />
<leftFlipper name="LF92" x="9" y="2" orientation="0" />
<rightFlipper name="RF112" x="11" y="2" orientation="0" />
<leftFlipper name="LF87" x="8" y="7" orientation="0" />
<rightFlipper name="RF137" x="13" y="7" orientation="0" />
<absorber name="A" x="0" y="19" width="20" height="1" />
</gizmos>
<connections>
<connect sourceGizmo="C43" targetGizmo="LF87" />
<connect sourceGizmo="C54" targetGizmo="LF87" />
<connect sourceGizmo="C65" targetGizmo="LF87" />
<connect sourceGizmo="C76" targetGizmo="LF87" />
<connect sourceGizmo="C109" targetGizmo="LF87" />
<connect sourceGizmo="C1110" targetGizmo="LF87" />
<connect sourceGizmo="C139" targetGizmo="LF87" />
<connect sourceGizmo="C99" targetGizmo="RF137" />
<connect sourceGizmo="C1110" targetGizmo="RF137" />
<connect sourceGizmo="C129" targetGizmo="RF137" />
<connect sourceGizmo="C156" targetGizmo="RF137" />
<connect sourceGizmo="C165" targetGizmo="RF137" />
<connect sourceGizmo="C174" targetGizmo="RF137" />
<connect sourceGizmo="C183" targetGizmo="RF137" />
<connect sourceGizmo="A" targetGizmo="A" />
<keyConnect key="32" keyDirection="down" targetGizmo="LF92" />
<keyConnect key="32" keyDirection="up" targetGizmo="LF92" />
<keyConnect key="32" keyDirection="down" targetGizmo="RF112" />
<keyConnect key="32" keyDirection="up" targetGizmo="RF112" />
<keyConnect key="87" keyDirection="down" targetGizmo="RF137" />
<keyConnect key="87" keyDirection="up" targetGizmo="RF137" />
<keyConnect key="127" keyDirection="down" targetGizmo="A" />
<keyConnect key="81" keyDirection="down" targetGizmo="LF87" />
<keyConnect key="81" keyDirection="up" targetGizmo="LF87" />
</connections>
</board>
<board gravity="FLOAT" friction1="FLOAT" friction2="FLOAT">
<ball name="STRING" x="FLOAT" y="FLOAT" xVelocity="FLOAT" yVelocity="FLOAT" />
<gizmos />
<squareBumper name="STRING" x="INTEGER" y="INTEGER" />
<circleBumper name="STRING" x="INTEGER" y="INTEGER" />
<triangleBumper name="STRING" x="INTEGER" y="INTEGER" orientation="0|90|180|270" />
<rightFlipper name="STRING" x="INTEGER" y="INTEGER" orientation="0|90|180|270" />
<leftFlipper name="STRING" x="INTEGER" y="INTEGER" orientation="0|90|180|270" />
<absorber name="STRING" x="INTEGER" y="INTEGER" width="INTEGER" height="INTEGER" />
<connections />
<connect sourceGizmo="STRING" targetGizmo="STRING" />
<keyConnect key="INTEGER" keyDirection="down" targetGizmo="STRING" />
<keyConnect key="INTEGER" keyDirection="up" targetGizmo="STRING" />
The formal definition of the file format can be found in the schema gb_level.xsd. Basically, the schema defines which elements it expects to see in an XML file and notes where the format may be extended. (These extension points are denoted by either <xs:any> or <anyAttribute>.) You don't have to understand the schema unless you want to extend it to support any new Gizmoball features you've designed. If you want to extend the schema, the XML Schema Tutorial will be helpful.
The provided physics library consists of
immutable abstract data types such as
Angle, Vect, LineSegment,
and
Circle,
as well as a class
Geometry
that contains static
methods to model the physics of elastic collisions between balls and
other circles and line segments. You are welcome to use or not use
this code as you please, and to modify it to meet your needs.
Documentation for the physics package can be found in
gb-doc.
Byte-compiled .class files are stored in
/mit/6.170/lib/gb-lib.jar, which should automatically be on
your classpath.
Source for the physics library can be found in /mit/6.170/www/psets/gb/gb-given/. While this source is provided in the event that you wish to examine or modify it, we strongly discourage you from modifying it. In the past, students who have not used the physics library as-is have had poor results on their projects. Most groups will not need to copy the source code to their own directories, add it to their CVS repositories, or compile it, but will just use the gb-lib.jar file and examine the specifications.