scg/ch09/RescueMission

From FANG

Jump to: navigation, search

001 package scg.ch09;
002 
003 import java.util.ArrayList;
004 
005 import fang2.core.Game;
006 import fang2.sprites.RectangleSprite;
007 import fang2.sprites.StringSprite;
008 
009 /**
010  * A "space invaders" clone-like game. The goal is to rescue the
011  * swimmers in the water before they reach the edge of the water. This
012  * game is both a game and a level. When the player clears a level, the
013  * game will advance to the next level. The next level is a new copy of
014  this game (so setup and advance will be called automatically) with a
015  * different swimmer speed.
016  */
017 public class RescueMission
018   extends Game {
019   // Named Constants --------------------------------------------
020   /** number of rows and columns in the game */
021   public static final int ROWS = 4;
022   public static final int COLUMNS = 6;
023 
024   /** add to level for fast swimmer's score */
025   public static final int FASTSWIMMER_BASE_SCORE = 9;
026 
027   /** how much should the swimmers speed up on each new level */
028   public static final double LEVEL_SPEEDUP = 1.10;
029 
030   /** default speeds for the moving objects */
031   public static final double RESCUER_DX = 1.0;
032   public static final double RESCUER_DY = 0.0;
033   public static final double RING_DX = 0.0;
034   public static final double RING_DY = -0.3;
035   public static final double SWIMMER_DX = 0.2;
036   public static final double SWIMMER_DY = 0.0;
037 
038   // Object Fields ----------------------------------------------
039   /** the fast swimmer (across the top) for this game; reused */
040   private FastSwimmer fastSwimmer;
041 
042   /** the starting score of this game */
043   private final int initialScore;
044 
045   /** What level number is this? */
046   private final int level;
047 
048   /** the scale of the swimmers (and everything else) */
049   private double objectScale;
050 
051   /** the rescuer who will save the people */
052   private Rescuer rescuer;
053 
054   /** the rescuer's tool with which to rescue the characters */
055   private RescueRing ring;
056 
057   /** a sprite to display the current score */
058   private StringSprite scoreSprite;
059 
060   /** Initial speed for all the regular swimmers */
061   private final double swimmerDX;
062   private final double swimmerDY;
063 
064   /** 2-dimensional container of Swimmer's */
065   private ArrayList<ArrayList<Swimmer>> swimmers;
066 
067   /** The water background */
068   private RectangleSprite water;
069   // Constructors -----------------------------------------------
070 
071   /**
072    * Create the first level in the game: level 1, score starts at 0,
073    * speed is default
074    */
075   public RescueMission() {
076     this(10, SWIMMER_DX, SWIMMER_DY);
077   }
078 
079   /**
080    * Create a new level in the game with the given speed
081    *
082    @param  initialScore  the starting score for this level
083    @param  swimmerDX     horizontal component of swimmer velocity for
084    *                       this level
085    @param  swimmerDY     vertical component of swimmer velocity for
086    *                       this level
087    */
088   public RescueMission(int level, int initialScore, double swimmerDX,
089     double swimmerDY{
090     this.scoreSprite = null;
091     this.level = level;
092     this.swimmerDX = swimmerDX;
093     this.swimmerDY = swimmerDY;
094     this.initialScore = initialScore;
095   }
096 
097   // Methods ----------------------------------------------------
098   /**
099    * Advance to the next frame.
100    *
101    @param  dT  seconds since the last frame
102    */
103   @Override
104   public void advance(double dT{
105     moveEverything(dT);
106     bounceEverything();
107     rescueIfPossible();
108     if (checkIsLevelOver()) {
109       addGame(new RescueMission(level + 1, getScore(),
110           swimmerDX * LEVEL_SPEEDUP, swimmerDY * LEVEL_SPEEDUP));
111       finishGame();
112     } else if (checkIsGameOver()) {
113       addGame(new EndOfGame(getScore()));
114       finishGame();
115     }
116   }
117 
118   /**
119    Set the score. {@link Game#setScore(int)} is built-in to {@link
120    * Game}this method passes the new score up to the parent class's
121    * method. Then it also updates the display of the score on the
122    * screen.
123    *
124    @param  score  the new score value
125    */
126   @Override
127   public void setScore(int score{
128     super.setScore(score);
129     // if the scoreSprite not yet used, create and store value
130     if (scoreSprite == null{
131       scoreSprite = new StringSprite();
132       scoreSprite.setScale(0.10);
133       scoreSprite.rightJustify();
134       scoreSprite.topJustify();
135       scoreSprite.setLocation(1.00.0);
136       scoreSprite.setColor(getColor("gray"));
137       addSprite(scoreSprite);
138     }
139     scoreSprite.setText(Integer.toString(getScore()));
140   }
141 
142   /**
143    * Setup the rescue game: create victims and the rescuer.
144    */
145   @Override
146   public void setup() {
147     final double victimRowScale = 0.5 / ROWS;
148     final double victimColumnScale = 0.7 / COLUMNS;
149 
150     // set the scale to make everything about the same size
151     objectScale = Math.min(victimRowScale, victimColumnScale);
152 
153     setupWater();
154     setupSwimmers();
155     setupRescuer();
156     setupFastSwimmer();
157     setScore(initialScore);// display the score
158   }
159 
160   /**
161    * Bounce all sprites: use each sprite's bounceOffEdges method to have
162    * it do whatever it should do.
163    */
164   private void bounceEverything() {
165     fastSwimmer.bounceOffEdges();
166     rescuer.bounceOffEdges();
167     ring.bounceOffEdges();
168     for (int row = 0; row != ROWS; ++row{
169       for (int column = 0; column != COLUMNS; ++column{
170         Swimmer curr = swimmers.get(row).get(column);
171         if (curr != null{
172           curr.bounceOffEdges();
173         }
174       }
175     }
176     Swimmer.clearBumpTheWall();
177   }
178 
179   /**
180    @return  true if the game is over (swimmers reach bottom); false
181    *          otherwise
182    */
183   private boolean checkIsGameOver() {
184     return ((getLowestSwimmer() != null&&
185         (getLowestSwimmer().getMaxY() >= water.getMaxY()));
186   }
187 
188   /**
189    @return  true if no unrescued swimmers; false otherwise
190    */
191   private boolean checkIsLevelOver() {
192     return (remainingSwimmerCount() == 0);
193   }
194 
195   /**
196    * Get the left-most swimmer in the lowest row of swimmers. Works by
197    * running across the rows from bottom to top, returning a reference
198    * to the first non-null Swimmer.
199    *
200    @return  reference to the lowest non-null swimmer, left-most in its
201    *          row (if there are more than one in the row); null if there
202    *          are no Swimmers remaining
203    */
204   private Swimmer getLowestSwimmer() {
205     Swimmer lowest = null;
206     for (int row = 0((lowest == null&& (row != ROWS))++row{
207       for (int column = 0((lowest == null&& (column != COLUMNS));
208           ++column{
209         Swimmer curr = swimmers.get(row).get(column);
210         if (curr != null{
211           lowest = curr;
212         }
213       }
214     }
215     return lowest;
216   }
217 
218   /**
219    * Move all the moving objects on the screen. Moving objects are the
220    * Swimmers, the Rescuer, the RescueRing, and the FastSwimmer. Note
221    * that none of these (except Swimmer's in the array) will be null so
222    * we just call advance on each and they move according to their own
223    * state and rules.
224    *
225    @param  dT  seconds since last frame
226    */
227   private void moveEverything(double dT{
228     fastSwimmer.advance(dT);
229     rescuer.advance(dT);
230     ring.advance(dT);
231     for (int row = 0; row != ROWS; ++row{
232       for (int column = 0; column != COLUMNS; ++column{
233         Swimmer curr = swimmers.get(row).get(column);
234         if (curr != null{
235           curr.advance(dT);
236         }
237       }
238     }
239   }
240 
241   /**
242    * Determine the number of swimmers remaining to be rescued. This is
243    * the same as counting the number of entries in swimmers which are
244    * non-null. This is a counting problem.
245    *
246    @return  the number of swimmers awaiting rescue
247    */
248   private int remainingSwimmerCount() {
249     int numberOfSwimmers = 0;
250     for (int row = 0; row != ROWS; ++row{
251       for (int column = 0; column != COLUMNS; ++column{
252         Swimmer curr = swimmers.get(row).get(column);
253         if (curr != null{
254           ++numberOfSwimmers;
255         }
256       }
257     }
258     return numberOfSwimmers;
259   }
260 
261   /**
262    * Rescue the fast swimmer.
263    */
264   private void rescueFastSwimmer() {
265     setScore(getScore() + fastSwimmer.getScore());
266     fastSwimmer.startWaiting();
267     ring.startReady();
268   }
269 
270   /**
271    * Check if any swimmer is rescued.
272    */
273   private void rescueIfPossible() {
274     if (ring.isFlying()) {
275       for (int row = 0; row != ROWS; ++row{
276         for (int column = 0; column != COLUMNS; ++column{
277           Swimmer curr = swimmers.get(row).get(column);
278           if (ring.isRescuing(curr)) {
279             rescueSwimmer(row, column);
280           }
281         }
282       }
283     }
284     if (fastSwimmer.isSwimming() && ring.isRescuing(fastSwimmer)) {
285       rescueFastSwimmer();
286     }
287   }
288 
289   /**
290    * Rescue the Swimmer at the given position in the array. Removes the
291    * sprite from the game screen and sets the spot where it was in the
292    * list of lists to null.
293    *
294    @param  row     row in which rescued Swimmer resides
295    @param  column  column in which the rescued Swimmer resides
296    */
297   private void rescueSwimmer(int row, int column{
298     Swimmer curr = swimmers.get(row).get(column);
299     setScore(getScore() + curr.getScore());
300     removeSprite(curr);
301     swimmers.get(row).set(column, null);
302     ring.startReady();
303   }
304 
305   /**
306    * Initialize the fast swimmer. This is the one which periodically
307    * moves across the top of the screen and is worth a lot of points
308    */
309   private void setupFastSwimmer() {
310     final double fastSwimmerDX = * swimmerDX;
311     final double fastSwimmerDY = * swimmerDY;
312     fastSwimmer = new FastSwimmer(FASTSWIMMER_BASE_SCORE + level,
313         fastSwimmerDX, fastSwimmerDY);
314     fastSwimmer.setColor(getColor("SCG Red"));
315     fastSwimmer.setScale(objectScale);
316     addSprite(fastSwimmer);
317   }
318 
319   /**
320    * Construct the rescuer. Adds the rope, the rescuer, and the ring to
321    * the screen. Note the order: rope first so that when it connects the
322    * midpoints of the two other sprites it is below them, appearing to
323    * come out of them at an appropriate angle.
324    */
325   private void setupRescuer() {
326     rescuer = new Rescuer(RESCUER_DX, RESCUER_DY, RING_DX, RING_DY);
327     rescuer.setColor(getColor("yellow green"));
328     rescuer.setScale(objectScale);
329     rescuer.setLocation(0.80.9);
330 
331     ring = rescuer.getRescueRing();
332 
333     addSprite(ring.getRope());
334     addSprite(rescuer);
335     addSprite(ring);
336   }
337 
338   /**
339    * Populate the the victims ArrayList. victims is an ArrayList of
340    * ArrayLists; create the container for containers then, for each row,
341    * create a container for Victim objects. Thus there is one call to
342    new before the outer loop (will be called once) and one call to new
343    * inside the outer loop (will be called once per row); these calls
344    * are new ArrayList calls. Then, inside the inner loop, a new Victim
345    * is created and added to the current row.
346    */
347   private void setupSwimmers() {
348     final double swimmerOffset = objectScale / 2.0;
349     final double lowestRowY = swimmerOffset + (ROWS * objectScale);
350     swimmers = new ArrayList<ArrayList<Swimmer>>();
351     for (int row = 0; row != ROWS; ++row{
352       ArrayList<Swimmer> currentRow = new ArrayList<Swimmer>();
353       double rowY = lowestRowY - (row * objectScale);
354       int rowScore = row + 1;// higher row = higher score
355       for (int column = 0; column != COLUMNS; ++column{
356         Swimmer current = new Swimmer(rowScore, swimmerDX, swimmerDY);
357         current.setScale(objectScale);
358         current.setLocation(swimmerOffset + (column * objectScale),
359           rowY);
360         addSprite(current);
361         currentRow.add(current);
362       }
363       swimmers.add(currentRow);
364     }
365   }
366 
367   /**
368    * Setup the water.
369    */
370   private void setupWater() {
371     water = new RectangleSprite(1.00.9);
372     water.setColor(getColor("cyan"));
373     water.setLocation(0.50.45);
374     addSprite(water);
375   }
376 }
377 
378 //Uploaded on Mon Mar 29 21:41:46 EDT 2010


Download/View scg/ch09/RescueMission.java





Views
Personal tools
Add to 
del.icio.usAdd to 
diggAdd to 
FacebookAdd to 
favoritesAdd to 
GoogleAdd to 
MySpaceAdd to 
PrintAdd to 
SlashdotAdd to 
StumbleUponAdd to 
Twitter

Games
Games