import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class AsteroidGame extends Applet { /* This is the program that runs the whole shabang */ //this is the width and height of the veiwing area public final static int WIDTH = 400, HEIGHT = 400, DELAY = 50; public final static double THRUST = 1.0; public final static DPoint STARTING_POINT_SHIP = new DPoint(300.0, 300.0), STARTING_POINT_PURSUER = new DPoint( 20.0, 20.0); private final static Color PURSUER_COLOR = new Color(204,153,204); SpaceShip ship, pursuer; AsteroidField field; ConfigurationSpace cSpace; boolean isInvincible; Graphics g, gb; // main graphics and graphics for buffer Image buffer; // offscreen buffer image Thread gameThread; // thread that repetitively moves asteroids and redraws public void init() // applet initialization done only at startup { cSpace = new ConfigurationSpace(); buffer = createImage(WIDTH,HEIGHT); gb = buffer.getGraphics(); g = this.getGraphics(); MovingPolygon.X_LIMIT = new Integer(WIDTH).doubleValue(); MovingPolygon.Y_LIMIT = new Integer(HEIGHT).doubleValue(); isInvincible = false; reset(); addKeyListener(new KeyHandler()); } public void reset() // initialization for each new level { synchronized(gb) { // clear the buffer gb.setColor(Color.black); gb.fillRect(0,0,WIDTH,HEIGHT); } ship = new SpaceShip(STARTING_POINT_SHIP); pursuer = new SpaceShip(STARTING_POINT_PURSUER); field = new AsteroidField(); while (field.inCollision(ship)) ship.translate(-4.0, 0.0); while (field.inCollision(pursuer)) pursuer.translate(4.0, 0.0); } public void start() // when starting up the applet... { if (gameThread == null) { gameThread = new Thread(new GameRunner()); gameThread.start(); } } public void stop() // when killing the applet... { if (gameThread != null) gameThread.stop(); gameThread = null; } private void drawScreen() { // draw the user controlled ship synchronized(gb) { gb.setColor(Color.cyan); gb.drawPolygon(ship.toPolygon()); } // draw the pursuer ship synchronized(gb) { gb.setColor(PURSUER_COLOR); gb.drawPolygon(pursuer.toPolygon()); } for (int k = 0; k < field.numAsteroids; k++) synchronized(gb) { gb.setColor(new Color(204, 102, 0)); gb.drawPolygon(field.asteroids[k].toPolygon()); } // display the buffer g.drawImage(buffer,0,0,this); // clear the buffer synchronized(gb) { gb.setColor(Color.black); gb.fillRect(0,0,WIDTH,HEIGHT); } } class GameRunner implements Runnable { public void run() { // repetetively executes the drawing and calculating of paths for the asteroid game // until all of the asteroids disappear or the ship is in collision with something. long sleepTime, timer = System.currentTimeMillis(); requestFocus(); while ( field.numAsteroids > 0 && ( (!field.inCollision(ship) && !pursuer.inCollision(ship)) || isInvincible ) ) { drawScreen(); // wait a few milliseconds between screen updates if necessary sleepTime = DELAY + timer - System.currentTimeMillis(); if (sleepTime >= 0) try { Thread.sleep(sleepTime); } catch (InterruptedException e) {} timer = System.currentTimeMillis(); // move everything one time slice and generate new paths, if needed. ship.move(); field.move(); if (cSpace.pathNearlyCompleted()) cSpace.generatePath(pursuer,ship,field); cSpace.followPath(pursuer); pursuer.move(); //checks if pursuer runs into an asteroid int c = field.findCollision(pursuer); if (c != -1) field.impact(field.asteroids[c]); } if (field.numAsteroids > 0) // you lose { gb.setColor(Color.red); gb.drawString("YOU LOSE",160,200); } else // you win { gb.setColor(Color.yellow); gb.drawString("YOU WIN!! Congratulations!",100,200); } drawScreen(); } } class KeyHandler extends KeyAdapter { // recieves and handles keyboard input public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_I: isInvincible = !isInvincible; break; case KeyEvent.VK_UP: ship.fireThrusters(THRUST); break; case KeyEvent.VK_DOWN: ship.fireThrusters(-THRUST); break; case KeyEvent.VK_LEFT: ship.rotateCCW(); break; case KeyEvent.VK_RIGHT: ship.rotateCW(); break; case KeyEvent.VK_SPACE: DPoint impact = ship.fireAt(field); if (impact == null) impact = new DPoint(ship.vertices[0].x + new Integer(WIDTH/4).doubleValue()*Math.cos(ship.rotation), ship.vertices[0].y + new Integer(WIDTH/4).doubleValue()*Math.sin(ship.rotation)); synchronized(gb) { // draw the laser beam gb.setColor(Color.green); gb.drawLine(new Double(impact.x).intValue(), new Double(impact.y).intValue(), new Double(ship.vertices[0].x).intValue(), new Double(ship.vertices[0].y).intValue()); } } } } }