James Falkner
CS248, Autumn 1999-2000 Project 4

----------------------------------------------------------------------
Game notes:

Title: Spherelings 2000

Money shot: spherelings.jpg (shows main game board and toolbox)

----------------------------------------------------------------------
Objective: Score points by completing as many levels as possible
before running out of playing balls.  To complete a level, the ball
must travel the length of the field and strike the far wall on the
bullseye.  Objects can be placed in the field to deflect the ball in
order to steer it to the target.  A variety of tools can be chosen
from the toolkit and placed in the field.  The tools can then be
rotated, translated, and their properties modified to affect the balls
trajectory.


----------------------------------------------------------------------
Cool stuff I spent a lot of time on (for the grader!):
1. The permuting trampoline
2. The save/load game and level editor
3. sounds (worked great on x86 solaris, not so great on sparc)
4. on-screen control panel and UI controls
5. quake-like fan
6. collision detection/fan effect

----------------------------------------------------------------------
Starting the game:

You must have the c++ libraries in your LD_LIBRARY_PATH or otherwise
have access to them.  Of course, the GL libs must also be available
spherelings [options]

options:

switches:
 -s : turn on sound
 -n : skip splash screen
 -l : run Spherelings 2000 Level Editor

texture options:
 -f <texture file>: floor texture (in raw PPM format)
 -w <wall file>: wall texture
 -a <fan file> : fan texture
 -b <trampoline file> : trampoline texture

----------------------------------------------------------------------
Quick summary of keys and buttons available during game:

G  abort round when ball get stuck or you get fed up
g  tests level (level editor only)
r  toggle automatic camera rotation when ball is in play
s  toggle sound on/off
<  zoom out
>  zoom in
l  toggle OpenGL lighting
b  toggle OpenGL blending
a  toggle axes visualization
t  toggle OpenGL textures
x  rotate selected object 2 degrees around x axis
y  rotate selected object 2 degrees around y axis
z  rotate selected object 2 degrees around z axis
X  rotate selected object 10 degrees around x axis
Y  rotate selected object 10 degrees around y axis
Z  rotate selected object 10 degrees around z axis
<arrow keys> moves the selected object in the X-Z plane.
PGUP moves the selected object up (e.g. up the Y axis)
PGDN moves the selected object down (e.g. down the Y axis)
+  select next object in field
-  select previous object in field
ESC exits game

----------------------------------------------------------------------
Control panel:

<<           browse previous tool
PLACE        Places current tool into field
REMOVE       Removes selected object from field
>>           browse next tool
QUIT         Exits game
CHASE        Toggles camera chase mode
GO!          Begins round, places ball into play.

----------------------------------------------------------------------
Viewing the field:

Pressing the mouse button in the field and dragging the mouse rotates the
view around the center of the field.  You can press the < and > keys to
zoom in and out. You can use this to line up objects or view the effects
from different angles. You can also press the CHASE button on the control
panel to toggle ballChase view, which causes the camera viewpoint to follow
the ball when GO is pressed (see below).

----------------------------------------------------------------------
Placing and selecting objects:

In the control panel, you can browse the tools by pressing the < and >
buttons.  The selected tool appears in the window.  Each object has
different properties, which can be modified by typing in parameters at
the top of the control panel.  Once configured, you can place it into
the field by pressing PLACE.  The object will appear in the playing
field.  You can then select objects in the field by clicking the mouse
button without moving the mouse.  

You can move the objects with the mouse by holding the CTRL button
down while clicking the object, and dragging it to a new
position. Alternatively, you can use the arrow keys to move the
object.  Dragging the object with the mouse or using the arrow keys
only moves the object parallel to the floor of the field.  You can
raise/lower the object by pressing PGUP and PGDN while the object is
selected (has a red bounding box around it).  

You can rotate the objects around their axes by either holding SHIFT
down while dragging the object, or by pressing the x, y, or z keys.
Each press rotates the object 2 degrees around that axis.  Pressing X,
Y, or Z rotates the object 10 degrees around each respective axis. The
red bounding box around the object indicates its orientation.

You can remove an object from the field by clicking on it, and pressing
the REMOVE button on the control panel.

Objects that are present at the start of a level are immobile, and thus
cannot be moved or rotated, they are part of the level.  You must work
with them, or avoid them.

----------------------------------------------------------------------
Objects available:

Trampoline (Box): When the ball hits this, it rebounds off according to
the balls direction, and the orientation of the trampoline.  If the
trampoline has >1.0 springyness, the ball will leave the trampoline at
a greater velocity than initally. Springyness > 2.0 is not usually effective,
it launches the ball very high.

Fan: The fan blows objects that enter its cone of influence, proportional
to its RPMs.  An RPMs of about 2000-3000 usually produce good effects.

Sphere:  You can place another sphere of arbitrary size into the field.
The playball will rebound off the sphere, as well as be affected by the
stationary sphere's gravitational field (proportional to its size). A size
of > 10 is usually not very effective.

Black Hole: The black hole has a strong gravitational field that sucks all
mobile objects into its event horizon.  If the playball comes in contact with
the event horizon, you lose that round.  You can, however use black holes
effectively to deflect the ball, as long as its not too strong.  Values
> 5.0 are usually too strong to be effective.

----------------------------------------------------------------------
Playing the game:

The game starts on level 0, with 10 balls, and a score of 0.  Each
time you hit the target, you get 10 points and retain all your balls,
and move to the next level. Each level has 0 or more fixed objects
that you can either use to your advantage or avoid. Each time you move
to the next level, the target is moved to a new, random location on
the back wall.  Each time the ball strikes the far wall WITHOUT
hitting the target, you get 0 points and lose a ball, and the target
stays where it is so that you can reconfigure the objects to correct
the ball's trajectory.  When all balls are exhausted, the game is
over.

You first place any combination of objects into the field, and
rotate/translate the objects to the desired configuration.  When you
are ready, press GO on the control panel and the ball drops into the
field with a small initial horizontal velocity.  In the absence of
objects, the ball rolls along the ground.  If the ball hits the back wall,
the round is over and score is calculated.  If the ball gets 'stuck' in 
an orbit or otherwise does not strike the back wall, you can press G to
abort the round (equivelant to missing the target).  If you hit the target,
you get points, and advance to the next level.

----------------------------------------------------------------------
Level Editor:

The level editor allows you to create a complex board, and save it for
later use during a game.  The level editor starts with a blank board.
You place desired objects into the field until you are satisfied.  You
can press 'g' to test the board, which drops the ball into the field
to simulate a real game.  You can add/remove objects as desired, no
objects are fixed in the level editor. These keys are available in the
control panel during level editing:

SAVE    Saves current board. Prompts for filename
LOAD    Loads previously built board.  Prompts for filename.

----------------------------------------------------------------------
Building the program:

To build you need gcc, and the GL/GLU/GLUT libraries.  You also need the PUI
libraries available at http://www.woodsoup.org/projs/plib

To build on Solaris 2.x, the included Makefile will build all objects
and link with the GL libraries and PUI libraries.  Minor modification
of the Makefile may be required to point to the plib libraries.  A
Solaris/Sparc executable is included with the submission, statically
linked with the PUI libraries, but dynamically linked with the openGL
libraries.

----------------------------------------------------------------------
Optional features from the assignment requirements:

The optional things I did:

1. On-screen control panel: The control panel in the 2nd window
acts as the control panel, controlling game operation and user
interaction. I used the PUI library for the user interaction, and the
same object code used during gameplay to animate the objects in the
control panel.

2. Collision Detection: I implemented it with sphere-sphere and sphere-plane
collision detection (see main.cc).  The ball rebounds off other objects,
which are represented as planes or spheres, and also rebounds off the game
room walls.  Correct rebound trajectory is calculated for all cases, as well
as calculating correct resultant elasticity of the collision, based on
properties of the objects involved (mass, direction, springyness, etc).

3. Simulated Dynamics:  Each object has an associated position, velocity,
and acceleration.  Gravity affects all mobile objects, and all moving
objects are affected by the gravitational field of other objects.  In
addition, some objects (like the Fan, or the BlackHole) can affect the
moving objects by more than just their gravitational attraction (e.g.
the fan "blows" moving objects away from it). 

*Also*, when the ball collides with the trampoline (a.k.a. the Box),
the trampoline permutes up and down much like a real trampoline would
when one jumps on it, and the ball rebounds correctly according to the
orientation of the trampoline.

4. Advanced image-based techniques:

The 'target' at the end of the field is billboarded onto a 2D polygon,
to make it appear to be rounded.  The corners of the polygon are 
transparent.

5. Sound.  I used the SL library included with the PUI library to generate
sound effects during the game, such as when you win/lose, or click on buttons.

6. Game-level editor: Running the program with the -l switch puts the
game into level-editor mode.  You can save/load the boards, which are
serialized/deserialized into text files, one line per object, and can be
re-created later.  This is how I created each level for the main game mode.
Each object can express its state in a single line of text.  Each line is
then written to a file, along with a count of objects and a title.  Then
when loading the file later, each line is sucked out of the text file, and
used to re-create the object.

----------------------------------------------------------------------
Game content sources

The sounds were stolen from Quake, as well as /usr/demo/SOUND on solaris
installations.

Most textures came from textureland, an old website with many free
textures for use when building websites.
http://www.meat.com/textureland. I created the logo "texture", using
the lemmings character from the original lemmings PC game.  I also
created the target texture.

All 3D models were either generated by my hand from GL primitives, or
GLU quadrics objects (the spheres).

The collision detection code is all mine, and the vector collision
algorithms came from my Calculus book.

The .ppm image loading code was stolen from xsupport.

Many of the papers at http://www.cs.unc.edu/~dm/collision.html were
read for collision detection, but ultimately I did a pretty simple
approximation.