package sconeApplet; import java.applet.Applet; import baklava.*; import sconeApplet.*; import java.awt.*; public class SconeApplet extends Applet implements Runnable, GlobalTimerObserver { public Playfield p = null; public Image sconeImages[]; public Image playerImage; public Image bombImage; public Image bulletImage; public Image shieldImage; public Image boomImages[]; public Image starsImage; public Image ufoImage; public Image startImage; public Image endImage; int spacew = 0; int spaceh = 0; int level = 0; int total = 0; int initial = 0; int points = 0; int rows = 0; int cols = 0; int lives = 0; Player player = null; // True if the last edge the scones contacted // was the left edge. boolean lastLeft = true; Thread engine; Label scoreLabel; Label levelLabel; Label livesLabel; public void init() { GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); p = new Playfield(this, 400, 380); p.setShowProgress(true); // Preload some classes now so they won't // interfere with gameplay later. p.setProgressMessage("Loading Code..."); p.progressStart(); try { Class.forName("sconeApplet.Scone"); Class.forName("sconeApplet.Player"); Class.forName("sconeApplet.Bullet"); Class.forName("sconeApplet.Bomb"); Class.forName("sconeApplet.Shield"); Class.forName("sconeApplet.Ufo"); Class.forName("sconeApplet.SplashScreen"); } catch (Exception e) { System.out.println("ERROR: Class Files are Missing!"); } p.progressEnd(); p.setGlobalTimerObserver(this); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.gridwidth = 3; c.gridheight = 1; c.weightx = 1; c.weighty = 1; c.gridx = 0; c.gridy = 0; gridbag.setConstraints(p, c); add(p); scoreLabel = new Label("Score: 000000"); c.fill = GridBagConstraints.NONE; c.gridwidth = 1; c.gridx = 0; c.gridy = 1; c.weightx = 1; c.weighty = 0; gridbag.setConstraints(scoreLabel, c); add(scoreLabel); levelLabel = new Label("Level: 000"); c.fill = GridBagConstraints.NONE; c.gridwidth = 1; c.gridx = 1; c.gridy = 1; c.weightx = 1; c.weighty = 0; gridbag.setConstraints(levelLabel, c); add(levelLabel); livesLabel = new Label("Lives: 0"); c.fill = GridBagConstraints.NONE; c.gridwidth = 1; c.gridx = 2; c.gridy = 1; c.weightx = 1; c.weighty = 0; gridbag.setConstraints(livesLabel, c); add(livesLabel); engine = new Thread(this); engine.start(); } public void start() { p.resume(); } public void stop() { p.suspend(); } public void destroy() { p.stop(); } public void run() { String base = getParameter("imageurl"); if ((base == null) || (base == "")) { base = "http://boutell.com/~boutell/scones/"; } p.setProgressMessage("Loading Images..."); // We don't have to call progressStart for image loading; // that's automatic. ufoImage = p.getImage( base + "ufo.gif"); sconeImages = new Image[2]; sconeImages[0] = p.getImage( base + "scone1.gif"); sconeImages[1] = p.getImage( base + "scone2.gif"); playerImage = p.getImage( base + "player.gif"); bombImage = p.getImage( base + "bomb.gif"); bulletImage = p.getImage( base + "bullet.gif"); shieldImage = p.getImage( base + "shield.gif"); starsImage = p.getImage( base + "stars2.gif"); startImage = p.getImage( base + "start.gif"); endImage = p.getImage( base + "end.gif"); // There are five of these. Let's build the URL up // by adding strings together... boomImages = new Image[5]; int i; for (i = 0; (i < 5); i++) { String url = base + "boom"; url += Integer.toString(i + 1); url += ".gif"; boomImages[i] = p.getImage(url); } // We have to know the size of the images // for the next step, so let the playfield know // it's time to load the rest p.imagesNeededNow(); // Prevent delays in some Java runtimes later by // computing image masks now p.getImageMask(sconeImages[0]); p.getImageMask(sconeImages[1]); p.getImageMask(playerImage); p.getImageMask(bombImage); p.getImageMask(bulletImage); p.getImageMask(shieldImage); for (i = 0; (i < 5); i++) { p.getImageMask(boomImages[i]); } // Now we can use the image size information spacew = sconeImages[0].getWidth(p) * 2; spaceh = sconeImages[0].getHeight(p) * 2; rows = (int) (p.getHeight() / spaceh * 2 / 3); cols = (int) (p.getWidth() / spacew * 2 / 3); initial = rows * cols; new SplashScreen(this, startImage); p.start(); } void startGame() { level = 1; lives = 3; livesLabel.setText("Lives: " + (new Integer(lives)).toString()); levelLabel.setText("Level: " + (new Integer(level)).toString()); startLevel(); } void score(int p) { points += p; scoreLabel.setText("Score: " + (new Integer(points)).toString()); } void startLevel() { // Stop the clock p.suspend(); // Remove any old crud p.goodbyeAll(); p.clearGlobalTimers(); // Figure out how much further down to move the scones int addrows = level; int addpixels = spaceh / 3; if (addrows > 7) { addrows = 7; } total = initial; // Add a background Sprite background = new Sprite(p); // Let baklava know there can be no collisions with this // sprite -- and do it now, before setting the tile, so // baklava won't waste time computing collision tables. background.setBackground(true); background.setTile(starsImage, p.getWidth(), p.getHeight()); background.setLevel(-1); int row, col; for (row = 0; (row < rows); row++) { for (col = 0; (col < cols); col++) { new Scone(this, col * spacew, row * spaceh + addpixels * addrows); } } lastLeft = true; // Build the shields out of chiclets if (level < 5) { int shield; for (shield = 0; (shield < 3); shield++) { int sx = 100 + shield * 100 - 24; int sy = 260; for (row = 0; (row < 4); row++) { for (col = 0; (col < 3); col++) { int x = sx + col * 16; int y = sy + row * 16; new Shield(this, x, y); } } } } try { p.setTimerAll( Class.forName("sconeApplet.Scone"), 0, Scone.timerSpeed); } catch (Exception e) { }; // Set the timer for a UFO setUfoTimer(); // Add the player player = new Player(this); // Resume the clock p.resume(); } public void sconeLost() { total--; score(100); if (total == 0) { level++; levelLabel.setText("Level: " + (new Integer(level)).toString()); startLevel(); } // Send a message to all the scones: change your speed now. try { p.setTimerAll( Class.forName("sconeApplet.Scone"), 0, Scone.timerSpeed); } catch (Exception e) { }; } public void playerLost() { lives--; livesLabel.setText("Lives: " + (new Integer(lives)).toString()); if (lives == 0) { p.goodbyeAll(); // Game over maaaan new SplashScreen(this, endImage); } else { p.goodbyeAll(); startLevel(); } } public void landing() { player.goodbye(); playerLost(); } public int getSconeSpeed() { int mult = level / 3; return (150 / total) * mult + 10; } public void contactLeft() { // A scone has made contact with the left edge. // See if this is just redundant... if (lastLeft) { return; } // It isn't, so turn the whole squadron. lastLeft = true; try { p.setTimerAll(Class.forName("sconeApplet.Scone"), 0, Scone.timerDownRight); } catch (Exception e) { }; } public void contactRight() { // A scone has made contact with the right edge. // See if this is just redundant... if (!lastLeft) { return; } // It isn't, so turn the whole squadron. lastLeft = false; try { p.setTimerAll(Class.forName("sconeApplet.Scone"), 0, Scone.timerDownLeft); } catch (Exception e) { }; } // Depends on total scones left. public int getBombDelay() { return (int) (1000 * (total + 1 + Math.random() * (total + 1))); } // Global timers go here. static public final int timerUfo = 0; public void globalTimer(int timerId) { if (timerId == timerUfo) { // Time for a UFO to appear. new Ufo(this); // Set the timer again. setUfoTimer(); } } void setUfoTimer() { p.setGlobalTimer((int) (1000 * (10 + Math.random() * 5)), timerUfo); } }