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