001    package breakout;
002    
003    import java.util.*;
004    
005    /** World controls Breakout's clock, and manages the different phases
006      * of calculation that occur during each unit of time. Once World has been
007      * started up, a tick proceeds as follows: <OL>
008      * 
009      *     <li>Call <code>update()</code> on the list of all BreakoutComponents 
010      *             obtained from Board.
011      *     <li>Call <code>resolveBounces(Iterator it)</code> on the list of all
012      *             Rebounding components obtained from Board.
013      *     <li>Call <code>diedWhileRebounding()</code> on the list of all
014      *             Rebounding components to clear out any that died during the
015      *             rebound phase.
016      *     <li>Decide if the game meets a win/lose condition or not.
017      *     <li>Redraw the board and sleep until time for the next batch of calculations.
018      *             </ol>
019    **/
020    public class World implements Runnable {
021            /** Time to sleep at the end of each tick **/
022            public static final int TICK_LENGTH = 50;
023    
024            private Board board;
025            private BreakoutUI ui;
026            private Thread spirit;
027            private boolean going;
028            
029            /** Creates a new World with the specified Board and BreakoutUI. **/
030            public World(Board aBoard, BreakoutUI bui) {
031                    this.board=aBoard;
032                    this.ui = bui;
033            }
034            
035            /** Starts the game, and disables the autolayout "add" method in Board.
036            **/
037            public void start() {
038                this.spirit = new Thread(this);
039                this.going=true;
040                this.board.disableLayout();
041                this.ui.getBoardPanel().transifyCursor();
042                
043                this.spirit.start();
044            }
045            /** Stops the game. **/
046            public void stop() {
047                this.ui.getBoardPanel().deTransifyCursor();
048                this.going=false;
049            }
050            
051            /** Runs continuously while game is in progress. **/
052            public void run() {
053                while(this.going) {
054                    try {
055                        /* update phase */
056                        Iterator it = this.board.getAllComponents();
057                        while(it.hasNext()) {
058                            BreakoutComponent bc = (BreakoutComponent)(it.next());
059                            bc.update();
060                        }
061                        /* rebound phase */
062                        it = this.board.getReboundingComponents();
063                        while(it.hasNext()) {
064                            Rebounding r = (Rebounding)(it.next());
065                            r.resolveBounces(this.board.getAllComponents());
066                        }
067                        /* clear dead rebounders */
068                        it = this.board.getReboundingComponents();
069                        while(it.hasNext()) {
070                            Rebounding r = (Rebounding)(it.next());
071                            if(r.diedWhileRebounding()) {
072                                it.remove();
073                                this.board.removeReboundingElement((BreakoutComponent)r);
074                            }
075                        }
076                        /* win/lose maintenance phase */
077                        if(!this.board.hasBricksLeft()) {
078                            this.ui.win();
079                        } else if(!this.board.hasBallInPlay()) {
080                            this.ui.lose();
081                        }
082                        /* update view; sleep */
083                        this.ui.getBoardPanel().repaint();
084                       // System.out.println("finish");
085                        Thread.sleep(World.TICK_LENGTH);
086                    } catch(InterruptedException ie) { 
087                        System.err.println("World: sleep() interrupted: "+ie.getMessage());
088                    }
089                }
090            }
091            
092            /** Gets the Board associated with this World. **/
093            public Board getBoard() {
094                return this.board;
095            }
096    }
097