Commits

Anonymous committed c8ccec6

Maybe the last commit...

Comments (0)

Files changed (13)

src/Game/Ball.java

         ballNode.setLocalTranslation(location);
         ball = new RigidBodyControl(new SphereCollisionShape(radius));
         ballNode.addControl(ball);
-        handler.attachNodeToRoot(ballNode);
-        handler.attachPhysicsControl(ball);
+        handler.setVisible(ballNode);
+        handler.enablePhysics(ball);
     }
 
-    public Vector3f getPhysicsLocation() {
+    public Vector3f getCurrentPosition() {
         return ball.getPhysicsLocation();
     }
 
-    public void setPhysicsLocation(Vector3f vector3f) {
+    public void moveTo(Vector3f vector3f) {
         ball.setPhysicsLocation(vector3f);
     }
 
         ball.clearForces();
         ball.setLinearVelocity(Vector3f.ZERO);
     }
-
-    public void pause() {
-        ball.setKinematic(true);
-        ball.setKinematicSpatial(true);
-    }
-
-    public void resume() {
-        ball.setKinematic(false);
-        ball.setKinematicSpatial(false);
-    }
 }

src/Game/DFS.java

     final private int W = 8;
 
     private ArrayList<Integer> directions;
-    private float unit;
+    private float unitLength;
 
     public DFS(int level) {
         directions = new ArrayList<Integer>();
 
         height = 1 + level * 2;
         width = 3 + level * 2;
-        unit = 1f / width;
+        unitLength = 1f / width;
 
         grid = new Cell[height][width];
         for (int i = 0; i < height; i++) {
             for (int j = 0; j < width; j++) {
                 grid[i][j] = new Cell(j, i, width, height);
-                grid[i][j].setSideLength(unit * 2);
+                grid[i][j].setSideLength(unitLength * 2);
 //                The index of the central cell is i = level, j = level + 1
                 grid[i][j].setScreenCoord(i, j, level, level + 1);
             }
     }
 
     /**
-     * Calculates the difference in x-coordinate to an adjacent cell in the
+     * Calculates the difference in x-coordinate to the adjacent cell in the
      * specified direction.
      *
      * @param direction The relative direction of the adjacent cell.
      * @return The difference in x-coordinate.
      */
-    private int DX(int direction) {
+    private int dX(int direction) {
         if (E == direction) {
             return 1;
         } else if (W == direction) {
     }
 
     /**
-     * Calculates the difference in y-coordinate to an adjacent cell in the
+     * Calculates the difference in y-coordinate to the adjacent cell in the
      * specified direction.
      *
      * @param direction The relative direction of the adjacent cell.
      * @return The difference in y-coordinate.
      */
-    private int DY(int direction) {
+    private int dY(int direction) {
         if (N == direction) {
             return -1;
         } else if (S == direction) {
      * @param direction an arbitrary direction
      * @return the opposite direction
      */
-    private int Opposite(int direction) {
+    private int opposite(int direction) {
         if (E == direction) {
             return W;
         } else if (W == direction) {
         } else if (S == direction) {
             return N;
         } else {
-//          These code will never be executed.
+//          This code should not be executed.
             return 0;
         }
     }
     public void visitFrom(int cx, int cy) {
         Collections.shuffle(directions);
         for (Integer direction : directions) {
-            int nx = cx + DX(direction);
-            int ny = cy + DY(direction);
-            if ((nx >= 0)
-                    && (nx <= width - 1)
-                    && (ny >= 0)
-                    && (ny <= height - 1)
-                    && (grid[ny][nx].isNotVisited())) {
+            int nx = cx + dX(direction);
+            int ny = cy + dY(direction);
+            if ((nx >= 0) &&
+                    (nx <= width - 1) &&
+                    (ny >= 0) &&
+                    (ny <= height - 1) &&
+                    (grid[ny][nx].isNotVisited())) {
                 grid[cy][cx].visit(direction);
-                grid[ny][nx].visit(Opposite(direction));
+                grid[ny][nx].visit(opposite(direction));
                 visitFrom(nx, ny);
             }
         }
     }
 
     /**
-     * Adds the locations of horizontal walls and vertical walls in a random
-     * maze to the ArrayList.
+     * Adds the locations of horizontal walls and vertical walls in the maze
+     * to the ArrayList.
      *
      * @param vWallLocations The ArrayList of locations of vertical walls.
      * @param hWallLocations The ArrayList of locations of horizontal walls.
                             new Vector3f(
                                     currentCell.getX(),
                                     0.2f,
-                                    currentCell.getY() - unit));
+                                    currentCell.getY() - unitLength));
                 }
 
                 if (currentCell.hasEastWall()) {
                     vWallLocations.add(
                             new Vector3f(
-                                    currentCell.getX() + unit,
+                                    currentCell.getX() + unitLength,
                                     0.2f,
                                     currentCell.getY()));
                 }
                             new Vector3f(
                                     currentCell.getX(),
                                     0.2f,
-                                    currentCell.getY() + unit));
+                                    currentCell.getY() + unitLength));
                 }
                 if (currentCell.hasWestWall()) {
                     vWallLocations.add(
                             new Vector3f(
-                                    currentCell.getX() - unit,
+                                    currentCell.getX() - unitLength,
                                     0.2f,
                                     currentCell.getY()));
                 }
         return height;
     }
 
-    public float getUnit() {
-        return unit;
+    public float getUnitLength() {
+        return unitLength;
     }
 }

src/Game/EndPoint.java

         super(handler);
     }
 
+
     /**
      * Note:
      * The ball collides with the end point if the distance between their
      */
     @Override
     public boolean collideWith(Ball ball) {
-        return location.distance(ball.getPhysicsLocation()) < threshold;
+        return location.distance(ball.getCurrentPosition()) < threshold;
     }
 }

src/Game/Handler.java

     public void rotateBoard(float yaw, float roll, float pitch);
 
     /**
-     * Attaches a node to the game, so that the node is visible.
+     * Makes a node visible on the screen.
      *
      * @param node
      */
-    public void attachNodeToRoot(Node node);
+    public void setVisible(Node node);
 
     /**
-     * Attaches the controller of the rigid body to the game, so that the
-     * movements of the rigid body obey physics the law of physics.
+     * Makes the movement of a rigid body obey physics the law of physics.
      *
      * @param rigidBody
      */
-    public void attachPhysicsControl(RigidBodyControl rigidBody);
+    public void enablePhysics(RigidBodyControl rigidBody);
 
     /**
-     * Add a box to the base of the board.
+     * Adds a box to the base of the board.
      *
      * @param boxShape
      * @param location The location where the box should be attached.
      */
-    public void addShapeToBase(BoxCollisionShape boxShape,
-                               Vector3f location);
+    public void addToBase(BoxCollisionShape boxShape,
+                          Vector3f location);
 
     /**
-     * Add a cylinder to the base of the board.
+     * Adds a cylinder to the base of the board.
      *
      * @param cylinderShape
      * @param location      The location where the cylinder should be attached.
 
     public void resetBall();
 
-    public void changeMap();
+    public void restartLevel();
 
     public void stopGame();
 
+    public void quitGame();
+
+
     public float getBoardThickness();
 }

src/Game/Hole.java

 /**
- * @author Zunyi Liu, u4499582
+ * @author Zunyi Liu
  * @since 29/09/11
  */
 
  */
 
 public class Hole extends RigidBody {
-    CylinderCollisionShape cylinderCollisionShape;
+    private CylinderCollisionShape cylinderCollisionShape;
     private float radius;
 
     protected float threshold;
      *         ball is too small.
      */
     public boolean collideWith(Ball ball) {
-        return location.distance(ball.getPhysicsLocation()) < threshold
+        return location.distance(ball.getCurrentPosition()) < threshold
                 && ball.getLinearVelocity() < 1;
     }
 }

src/Game/Key.java

 /**
- * @author Zunyi Liu, u4499582
+ * @author Zunyi Liu
  * @since 29/09/11
  */
 
             if (name.equals("Reset") && !pressed) {
                 handler.resetBall();
             } else if (name.equals("Quit") && !pressed) {
-                handler.stopGame();
+                handler.quitGame();
             } else if (name.equals("Change") && !pressed) {
-                handler.changeMap();
+                handler.restartLevel();
             }
         }
     };
         inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_UP));
         inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_DOWN));
 
-//        Vim-style mappings
-        inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_H));
-        inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_L));
-        inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_K));
-        inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_J));
-
         inputManager.addMapping("Reset", new KeyTrigger(KeyInput.KEY_R));
         inputManager.addMapping("Quit", new KeyTrigger(KeyInput.KEY_Q));
         inputManager.addMapping("Change", new KeyTrigger(KeyInput.KEY_C));

src/Game/Labyrinth.java

 
     private RigidBodyControl board;
     private Ball ball;
+    private Ball ball2;
     private Node boardNode;
     private CompoundCollisionShape base;
     private ArrayList<Hole> holes;
         score = new Score(handler);
         initWorld();
         setupKeys();
-    }
 
-    /**
-     * Creates the necessary callback functions.
-     */
-    private void initHandler() {
-        handler = new Handler() {
-            public void rotateBoard(float yaw, float roll, float pitch) {
-                if (!isLost) {
-                    boardNode.rotate(yaw * pref.sensitivity,
-                            roll * pref.sensitivity,
-                            pitch * pref.sensitivity);
-                }
-            }
-
-            public void attachNodeToRoot(Node node) {
-                rootNode.attachChild(node);
-            }
-
-            public void attachPhysicsControl(RigidBodyControl rigidBody) {
-                bulletAppState.getPhysicsSpace().add(rigidBody);
-            }
-
-            public void addShapeToBase(BoxCollisionShape boxShape,
-                                       Vector3f location) {
-                base.addChildShape(boxShape, location);
-            }
-
-            public void addToBase(CylinderCollisionShape cylinderShape,
-                                  Vector3f location) {
-                base.addChildShape(cylinderShape, location);
-            }
-
-            public float getBallRadius() {
-                return ball.getRadius();
-            }
-
-            public void resetBall() {
-                if (isLost) {
-                    time = 0;
-                    isLost = false;
-                }
-                reset();
-
-            }
-
-            public void changeMap() {
-                pref.init();
-                reset();
-            }
-
-            public void stopGame() {
-                isLost = true;
-                ball.pause();
-            }
-
-            public float getBoardThickness() {
-                return pref.boardHeight;
-            }
-        };
+        //        Forces JVM to do GC once.
+        System.gc();
     }
 
     /**
 
         boardNode.addControl(board);
 
-        handler.attachNodeToRoot(boardNode);
-        handler.attachPhysicsControl(board);
+        handler.setVisible(boardNode);
+        handler.enablePhysics(board);
     }
 
     /**
         for (Vector3f centre : pref.holeCentres) {
             Hole hole = new Hole(handler);
             hole.setLocation(centre);
-            hole.setRadius(pref.getUnit() * 0.5f);
+            hole.setRadius(pref.getUnitLength() * 0.5f);
             hole.attach();
             holes.add(hole);
         }
     private void initEnd() {
         end = new EndPoint(handler);
         end.setLocation(pref.endPosition);
-        end.setRadius(pref.getUnit() * 0.9f);
+        end.setRadius(pref.getUnitLength() * 0.9f);
         end.attach();
     }
 
          * you that is possible.
          * -- Meitian Huang
          */
-        Ball ball2 = new Ball(handler);
+        ball2 = new Ball(handler);
         ball2.setLocation(
                 pref.ballPosition.negate().add(new Vector3f(0, 0.4f, 0)));
         ball2.setRadius(pref.ballRadius * 2);
             time += tpf;
             if (end.collideWith(ball)) {
                 score.increaseScore(timeLeft);
-                score.reduceScore((int) time / 10);
                 pref.increaseLevel();
                 pref.init();
                 time = 0;
 
             for (Hole hole : holes) {
                 if (hole.collideWith(ball)) {
-                    score.reduceScore();
+                    score.reduceScore(10);
                     reset();
                 }
             }
 
-            timeLeft = (pref.level * 15 - (int) time);
+            timeLeft = (pref.level * 20 - (int) time);
             if (timeLeft < 0) {
                 isLost = true;
             }
         }
-
         updateText();
     }
 
      */
     private void updateText() {
         if (isLost) {
-            bitmapText.setText("You lose!");
+            bitmapText.setText("You lose! Press 'R' to restart.");
         } else {
             bitmapText.setText("Level:  " + pref.level + "\t"
                     + "Time Left:    " + timeLeft + "\t"
                     + score.toString());
         }
         bitmapText.setLocalTranslation(
-                (1280 - bitmapText.getLineWidth()) / 2,
+                (800 - bitmapText.getLineWidth()) / 2,
                 bitmapText.getLineHeight(),
                 0);
     }
         initHoles();
         initEnd();
 
-        ball.setPhysicsLocation(pref.ballPosition);
-        ball.resume();
+        ball.moveTo(pref.ballPosition);
         ball.zeroVelocity();
+
+        ball2.moveTo(pref.ballPosition.negate().add(new Vector3f(0, 0.4f, 0)));
+
+        //        Forces JVM to do GC once.
+        System.gc();
+    }
+
+    /**
+     * Creates the necessary callback functions.
+     */
+    private void initHandler() {
+        handler = new Handler() {
+            public void rotateBoard(float yaw, float roll, float pitch) {
+                if (!isLost) {
+                    boardNode.rotate(yaw * pref.sensitivity,
+                            roll * pref.sensitivity,
+                            pitch * pref.sensitivity);
+                }
+            }
+
+            public void setVisible(Node node) {
+                rootNode.attachChild(node);
+            }
+
+            public void enablePhysics(RigidBodyControl rigidBody) {
+                bulletAppState.getPhysicsSpace().add(rigidBody);
+            }
+
+            public void addToBase(BoxCollisionShape boxShape,
+                                  Vector3f location) {
+                base.addChildShape(boxShape, location);
+            }
+
+            public void addToBase(CylinderCollisionShape cylinderShape,
+                                  Vector3f location) {
+                base.addChildShape(cylinderShape, location);
+            }
+
+            public float getBallRadius() {
+                return ball.getRadius();
+            }
+
+            public void resetBall() {
+                if (isLost) {
+                    score.halve();
+                    time = 0;
+                    isLost = false;
+                }
+                reset();
+
+            }
+
+            public void restartLevel() {
+                pref.init();
+                reset();
+            }
+
+            public void stopGame() {
+                isLost = true;
+            }
+
+            public void quitGame() {
+                stop();
+            }
+
+            public float getBoardThickness() {
+                return pref.boardHeight;
+            }
+        };
     }
 }

src/Game/Pref.java

 /**
- * @author Yiwei Xu
+ * @author Meitian Huang
  * @since 29/09/11
  */
 
     protected Vector3f endPosition;
 
     private DFS dfs;
-    protected final boolean bugMe = true;
 
     public Pref() {
         level = 1;
 
         randomiseBallLocation();
         generateHoles();
+
+//        Forces JVM to do GC once.
+        System.gc();
     }
 
     private void generateHoles() {
     /**
      * Generates a random maze and stores the information of walls.
      */
-    public void generateWalls() {
+    private void generateWalls() {
         vWallLocations = new ArrayList<Vector3f>();
         hWallLocations = new ArrayList<Vector3f>();
 
         dfs.fill(vWallLocations, hWallLocations);
 
         Vector3f vWallDimension =
-                new Vector3f(boardHeight, 0.2f, dfs.getUnit());
+                new Vector3f(boardHeight, 0.2f, dfs.getUnitLength());
         Vector3f hWallDimension =
-                new Vector3f(dfs.getUnit(), 0.2f, boardHeight);
+                new Vector3f(dfs.getUnitLength(), 0.2f, boardHeight);
 
         vWallShape = new BoxCollisionShape(vWallDimension);
         hWallShape = new BoxCollisionShape(hWallDimension);
 
     /**
      * Tests if two vectors are overlapping on the board
+     * <p/>
+     * Note:
+     * == does not work for floats.
+     * e.g. 1.0f + 2.0f == 3.0f  is false.
      *
      * @param vectorA The first vector
      * @param vectorB The second vector
      * @return True if two vectors are overlapping
      */
-    public boolean equalVector(Vector3f vectorA, Vector3f vectorB) {
+    private boolean equalVector(Vector3f vectorA, Vector3f vectorB) {
         return Math.abs(vectorA.getX() - vectorB.getX()) < epsilon &&
                 Math.abs(vectorB.getZ() - vectorB.getZ()) < epsilon;
     }
 
-    public float getUnit() {
-        return dfs.getUnit();
+    public float getUnitLength() {
+        return dfs.getUnitLength();
     }
 }
 
 ## What Does It Do
 
-> A ball, rolling within a maze needs to get to their destination at the other end, while avoiding holes. When the ball falls into a hole it is returned to
-the beginning of the maze. The player cannot directly control the ball. Instead, the player must alter the angle of the maze floor, tilting it using the up, down, left and right arrow keys. The ball obeys the laws of physics
-and will roll due to gravitational pull and accelerate until it hits the wall. The ball will stop rolling when it hits the wall.
-
-### Notes
+> A ball, rolling within a maze needs to get to their destination at the other
+end, while avoiding holes. When the ball falls into a hole it is returned to
+the beginning of the maze. The player cannot directly control the ball.
+Instead, the player must alter the angle of the maze floor, tilting it using
+the up, down, left and right arrow keys. The ball obeys the laws of physics
+and will roll due to gravitational pull and accelerate until it hits the wall.
+The ball will stop rolling when it hits the wall.
+
+## Rules
 1. You may see more than one cyliner. The largest one is the end. 
-2. You may see more than one ball. Remember: your goal is to make the smallest ball fall into the end. 
+2. You may see more than one ball. Your goal is to make the smallest ball fall into the end.
+3. You must win in (level * 20) seconds.
+4. The score is initially 10.
+5. If the score is less than 0 or the time is up, the game
+is stopped.
+6. You can restart the stopped game, but your socre will
+be halved.
+6. If you fall into a hole, the score is reduced by 10.
+7. If you win, the remaining time (in seconds) will add to
+your score.
+
 
 ## How to Run
 The main class is under src/Game/Starter.java.
 ## Requirements
 In order to run this program, you need to have at least:
 
-1. OpenGL 1.0
-2. Java 6
-3. Imagination!
+* OpenGL 1.0
+* Java 6
+* Imagination!
 
 
 ## License
 This program is under the BSD license. 
 
-This program uses a game engine called jMonkeyEngine <http://jmonkeyengine.org/>, which is completely
+This program uses a game engine called jMonkeyEngine <http://jmonkeyengine.org/>
+, which is completely
 open-source under the BSD license.
 
-For more information, see LICENSE.
+For more information, see LICENSE.

src/Game/README.html

 <!doctype html>
 <html>
 <head>
-    <meta charset="utf-8">
-    <style>
-        h1,
-        h2,
-        h3,
-        h4,
-        h5,
-        h6,
-        p,
-        blockquote {
-            margin: 0;
-            padding: 0;
-        }
-
-        body {
-            font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
-            font-size: 13px;
-            line-height: 18px;
-            color: #737373;
-            margin: 10px 10px 10px 20px;
-        }
-
-        a {
-            color: #0069d6;
-        }
-
-        a:hover {
-            color: #0050a3;
-            text-decoration: none;
-        }
-
-        a img {
-            border: none;
-        }
-
-        p {
-            margin-bottom: 9px;
-        }
-
-        h1,
-        h2,
-        h3,
-        h4,
-        h5,
-        h6 {
-            color: #404040;
-            line-height: 36px;
-        }
-
-        h1 {
-            margin-bottom: 18px;
-            font-size: 30px;
-        }
-
-        h2 {
-            font-size: 24px;
-        }
-
-        h3 {
-            font-size: 18px;
-        }
-
-        h4 {
-            font-size: 16px;
-        }
-
-        h5 {
-            font-size: 14px;
-        }
-
-        h6 {
-            font-size: 13px;
-        }
-
-        hr {
-            margin: 0 0 19px;
-            border: 0;
-            border-bottom: 1px solid #aaa;
-        }
-
-        blockquote {
-            padding: 13px 13px 21px 15px;
-            margin-bottom: 18px;
-            font-family: georgia, serif;
-            font-style: italic;
-        }
-
-        blockquote:before {
-            content: "\201C";
-            font-size: 40px;
-            margin-left: -10px;
-            font-family: georgia, serif;
-            color: #eee;
-        }
-
-        blockquote p {
-            font-size: 14px;
-            font-weight: 300;
-            line-height: 18px;
-            margin-bottom: 0;
-            font-style: italic;
-        }
-
-        code, pre {
-            padding: 0 3px 2px;
-            font-family: Monaco, Andale Mono, Courier New, monospace;
-            -webkit-border-radius: 3px;
-            -moz-border-radius: 3px;
-            border-radius: 3px;
-        }
-
-        code {
-            background-color: #fee9cc;
-            color: rgba(0, 0, 0, 0.75);
-            padding: 1px 3px;
-            font-size: 12px;
-        }
-
-        pre {
-            display: block;
-            padding: 14px;
-            margin: 0 0 18px;
-            line-height: 16px;
-            font-size: 11px;
-            border: 1px dashed #ccc;
-            border: 1px dashed rgba(0, 0, 0, 0.15);
-            -webkit-border-radius: 3px;
-            -moz-border-radius: 3px;
-            border-radius: 3px;
-            white-space: pre;
-            white-space: pre-wrap;
-            word-wrap: break-word;
-        }
-
-        pre code {
-            background-color: #fdfdfd;
-            color: #737373;
-            font-size: 11px;
-        }
-
-        @media screen and (min-width: 768px) {
-            body {
-                width: 748px;
-                margin: 10px auto;
-            }
-        }
-    </style>
-    <title>README.html</title>
+<meta charset="utf-8">
+<style>
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote {
+    margin: 0;
+    padding: 0;
+}
+body {
+    font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
+    font-size: 13px;
+    line-height: 18px;
+    color: #737373;
+    margin: 10px 10px 10px 20px;
+}
+a {
+    color: #0069d6;
+}
+a:hover {
+    color: #0050a3;
+    text-decoration: none;
+}
+a img {
+    border: none;
+}
+p {
+    margin-bottom: 9px;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+    color: #404040;
+    line-height: 36px;
+}
+h1 {
+    margin-bottom: 18px;
+    font-size: 30px;
+}
+h2 {
+    font-size: 24px;
+}
+h3 {
+    font-size: 18px;
+}
+h4 {
+    font-size: 16px;
+}
+h5 {
+    font-size: 14px;
+}
+h6 {
+    font-size: 13px;
+}
+hr {
+    margin: 0 0 19px;
+    border: 0;
+    border-bottom: 1px solid #aaa;
+}
+blockquote {
+    padding: 13px 13px 21px 15px;
+    margin-bottom: 18px;
+    font-family:georgia,serif;
+    font-style: italic;
+}
+blockquote:before {
+    content:"\201C";
+    font-size:40px;
+    margin-left:-10px;
+    font-family:georgia,serif;
+    color:#eee;
+}
+blockquote p {
+    font-size: 14px;
+    font-weight: 300;
+    line-height: 18px;
+    margin-bottom: 0;
+    font-style: italic;
+}
+code, pre {
+    padding: 0 3px 2px;
+    font-family: Monaco, Andale Mono, Courier New, monospace;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+    border-radius: 3px;
+}
+code {
+    background-color: #fee9cc;
+    color: rgba(0, 0, 0, 0.75);
+    padding: 1px 3px;
+    font-size: 12px;
+}
+pre {
+    display: block;
+    padding: 14px;
+    margin: 0 0 18px;
+    line-height: 16px;
+    font-size: 11px;
+    border: 1px dashed #ccc;
+    border: 1px dashed rgba(0, 0, 0, 0.15);
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+    border-radius: 3px;
+    white-space: pre;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+}
+pre code {
+    background-color: #fdfdfd;
+    color:#737373;
+    font-size: 11px;
+}
+@media screen and (min-width: 768px) {
+    body {
+        width: 748px;
+        margin:10px auto;
+    }
+}
+</style>
+<title>README.html</title>
 </head>
 <body>
 <h1>Yet Another 3D Java Game</h1>
 
-<p><img src="java.gif" alt="image"/></p>
+<p><img src="java.gif" alt="image" /></p>
 
 <h2>Contributors</h2>
 
-<p>Meitian Huang u4700480</p>
+<p>Meitian Huang   u4700480</p>
 
-<p>Zunyi Liu u4499582</p>
+<p>Zunyi Liu       u4499582</p>
 
-<p>Yiwei Xu u4834608</p>
+<p>Yiwei Xu        u4834608</p>
 
 <h2>What Does It Do</h2>
 
-<blockquote><p>A ball, rolling within a maze needs to get to their destination
-    at the other end, while avoiding holes. When the ball falls into a hole it
-    is returned to
-    the beginning of the maze. The player cannot directly control the ball.
-    Instead, the player must alter the angle of the maze floor, tilting it using
-    the up, down, left and right arrow keys. The ball obeys the laws of physics
-    and will roll due to gravitational pull and accelerate until it hits the
-    wall. The ball will stop rolling when it hits the wall.</p></blockquote>
+<blockquote><p>A ball, rolling within a maze needs to get to their destination at the other
+end, while avoiding holes. When the ball falls into a hole it is returned to
+the beginning of the maze. The player cannot directly control the ball.
+Instead, the player must alter the angle of the maze floor, tilting it using
+the up, down, left and right arrow keys. The ball obeys the laws of physics
+and will roll due to gravitational pull and accelerate until it hits the wall.
+The ball will stop rolling when it hits the wall.</p></blockquote>
 
-<h3>Notes</h3>
+<h2>Rules</h2>
 
 <ol>
-    <li>You may see more than one cyliner. The largest one is the end.</li>
-    <li>You may see more than one ball. Remember: your goal is to make the
-        smallest ball fall into the end.
-    </li>
+<li>You may see more than one cyliner. The largest one is the end.</li>
+<li>You may see more than one ball. Your goal is to make the smallest ball fall into the end.</li>
+<li>You must win in (level * 20) seconds.</li>
+<li>The score is initially 10.</li>
+<li>If the score is less than 0 or the time is up, the game
+is stopped.</li>
+<li>You can restart the stopped game, but your socre will
+be halved.</li>
+<li>If you fall into a hole, the score is reduced by 10.</li>
+<li>If you win, the remaining time (in seconds) will add to
+your score.</li>
 </ol>
 
 
 <h2>How to Run</h2>
 
 <p>The main class is under src/Game/Starter.java.
-    <em>The rest is left as an exercise for the reader.</em></p>
+<em>The rest is left as an exercise for the reader.</em></p>
 
 <h2>Requirements</h2>
 
 <p>In order to run this program, you need to have at least:</p>
 
-<ol>
-    <li>OpenGL 1.0</li>
-    <li>Java 6</li>
-    <li>Imagination!</li>
-</ol>
+<ul>
+<li>OpenGL 1.0</li>
+<li>Java 6</li>
+<li>Imagination!</li>
+</ul>
 
 
 <h2>License</h2>
 
 <p>This program is under the BSD license.</p>
 
-<p>This program uses a game engine called jMonkeyEngine <a
-        href="http://jmonkeyengine.org/">http://jmonkeyengine.org/</a>, which is
-    completely
-    open-source under the BSD license.</p>
+<p>This program uses a game engine called jMonkeyEngine <a href="http://jmonkeyengine.org/">http://jmonkeyengine.org/</a>
+, which is completely
+open-source under the BSD license.</p>
 
 <p>For more information, see LICENSE.</p>
 </body>
-</html>
+</html>

src/Game/Score.java

 /**
- * @author Meitian Huang
+ * @author Yiwei Xu
  * @since 13/10/11
  */
 package Game;
     }
 
     /**
-     * Reduces the score by 1 and terminates the game if the score is less
-     * than 0.
-     */
-    public void reduceScore() {
-        if ((score -= 10) < 0) {
-            System.out.println("Less than zero");
-            handler.stopGame();
-        }
-    }
-
-    /**
      * Reduces the score by n and terminates the game if the score is less
      * than 0.
      *
      */
     public void reduceScore(int n) {
         if ((score -= n) < 0) {
+            score = 0;
             handler.stopGame();
         }
     }
         score += n;
     }
 
+    public void halve() {
+        score /= 2;
+    }
+
     @Override
     public String toString() {
         return "Score: " + Integer.toString(score);

src/Game/Starter.java

 /**
- * @author Meitian Huang, u4700480
+ * @author Meitian Huang
  * @since 29/09/11
  */
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-
 public class Starter {
     public static void main(String[] args) {
 
 
         AppSettings settings = new AppSettings(true);
         settings.setTitle("Labyrinth");
-//        Uses whatever version of OpenGL to render.
+
+//        Uses any available version of OpenGL.
         settings.setRenderer(AppSettings.LWJGL_OPENGL_ANY);
+
 //        Disables audio renderer...
         settings.setAudioRenderer(null);
+
         settings.setSettingsDialogImage("Game/java.gif");
-        settings.setFullscreen(true);
-        settings.setResolution(1280, 800);
+        settings.setResolution(800, 600);
 
-        Labyrinth app = new Labyrinth();
-        app.setSettings(settings);
-        app.start();
+        Labyrinth game = new Labyrinth();
+        game.setSettings(settings);
+        game.start();
     }
 }

src/Game/Wall.java

 
     @Override
     public void attach() {
-        handler.addShapeToBase(wall, location);
+        handler.addToBase(wall, location);
     }
 }