home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-12-14 | 11.6 KB | 533 lines |
-
- import java.awt.*;
- import java.awt.event.*;
- import java.applet.Applet;
- import java.awt.image.*;
-
- /**
- * A class that describes a target "invader"
- * This hold a single invader
- */
- class Invader {
-
- /*
- * this invader's position and velocity
- */
- double x, y, dx, dy;
-
- /*
- * this invader's missile position and velocity
- * only one missile allowed per invader
- */
- int mx, my, mdy;
-
- /*
- * The images for an invader
- */
- Image img[] = new Image[4];
-
- /*
- * inplay is true if this invader has not been killed
- */
- boolean inplay;
-
- /*
- * fired is set to true when this invader fires a missile
- */
- boolean fired = false;
-
- /*
- * state is used to cycle through the four images
- * of this invader
- */
- double state;
-
- /*
- * value is the score value; it depends on the speed
- */
- int value;
-
- /*
- * Initialize position and speed for this invader
- */
- void random (int speed, int w, int h) {
-
- x = 10 + (w-20)*Math.random ();
- y = 10 + ((h>>1)-20)*Math.random ();
- dx = (speed>>1) - speed*Math.random ();
- dy = (speed>>1) - speed*Math.random ();
- inplay = true;
- state = 3 * Math.random ();
- fired = false;
- mdy = 20;
- value = speed * 10;
- }
-
- /*
- * Calculate new invader and missile position
- * Also fires a missile at random
- * @param w panel width
- * @param h panel height
- */
- void compute (int w, int h) {
-
- if (x <= 0 || x > w) dx = -dx;
- if (y <= 0 || y > h>>1) dy = -dy;
- if (my > h-20) fired = false;
- if (fired) my += mdy;
- else my = 0;
- if (inplay && !fired && Math.random () > 0.99) {
- fired = true;
- mx = (int) x; my = (int) y+25;
- }
- x += dx; y += dy;
- }
-
- /*
- * paint invader and missile (if it has been fired)
- * @param g - destination graphics object
- * @param obs - imageobserver associated
- * with this graphics context
- */
- public void paint (Graphics g, ImageObserver obs) {
-
- int whichImage;
-
- if (inplay) {
- whichImage = (int) state;
- g.drawImage (img[whichImage & 0x3], (int) x-25,
- (int) y-25, obs);
- state += .25;
- }
- if (fired) {
- g.setColor (Color.green);
- g.drawLine ((int) mx, (int) my, (int) mx, (int) my-10);
- }
- }
-
- /*
- * Tests whether the player's missile has hit this invader
- * Returns true if invader is hit
- * @param pmx - player's missile x position
- * @param pmy - player's missile y position
- */
- boolean killer (int pmx, int pmy) {
-
- int deltaX, deltaY;
-
- if (!inplay) return false;
- deltaX = (int) Math.abs (x-pmx);
- deltaY = (int) Math.abs (y-pmy);
- if (deltaX < 20 && deltaY < 20) {
- inplay = false;
- return true;
- }
- return false;
- }
- }
-
- /**
- * A class to describe the player, very similar to Invader
- * except in reverse
- */
- class Player {
-
- /*
- * position of the player
- */
- int x, y=-100;
-
- /*
- * position of the player's missile
- */
- int mx, my, mdy = -20;
-
- /*
- * two different player images
- */
- Image img1, img2;
-
- /*
- * fired is true if player has fired a missile
- * inplay is true if the game is not over
- */
- boolean fired = false, inplay=true;
-
- /*
- * called when a player fires a missile
- */
- void fire () {
-
- if (fired || !inplay) return;
- mx = x; my = y;
- fired = true;
- }
-
- /*
- * Calculate next missile position
- */
- void compute () {
-
- if (my < 0) fired = false;
- if (fired) my += mdy;
- else my = y;
- }
-
- /**
- * Paint player and missile
- * @param g - destination graphics object
- * @param obs - image observer
- */
- public void paint (Graphics g, ImageObserver obs) {
-
- if (fired) {
- if (inplay) g.drawImage (img2, x-25, y, obs);
- g.setColor (Color.white);
- g.drawLine (mx, my, mx, my+10);
- } else if (inplay) g.drawImage (img1, x-25, y, obs);
- }
-
- /**
- * Returns true if the player has been killed
- * @param bmx, bmy - position of enemy missile
- */
- boolean killer (int bmx, int bmy) {
-
- int dx, dy;
-
- if (!inplay) return false;
- dx = (int) Math.abs (x-bmx);
- dy = (int) Math.abs (y-bmy);
- if (dx < 20 && dy < 20) {
- return true;
- }
- return false;
- }
- }
-
- /*
- * much of the game logic is here
- */
- class Playfield extends Panel implements Runnable, MouseListener, MouseMotionListener
- {
-
- static final int PLAYER_HIT = 1;
- static final int INVADER_HIT = 2;
-
- InvaderApp invaderApp;
-
- /*
- * the number of invaders in play
- */
- int NInvaders=0;
-
- /*
- * the maximum number of invaders possible
- */
- final int MaxInvaders = 32;
-
- /*
- * array of invaders
- */
- Invader invaders[] = new Invader[MaxInvaders];
- Player player;
-
- /*
- * offscreen image for double-buffering
- */
- Image offscreen;
-
- /*
- * dimension of offscreen graphics image
- */
- Dimension psize;
-
- /*
- * graphics object associated with offscreen image
- */
- Graphics offgraphics;
-
- /*
- * game action thread
- */
- Thread theThread;
-
- /*
- * the playfield background color
- */
- Color bgcolor = new Color (51, 0, 153);
- int score, playerLives, playLevel;
- Font font;
-
- /**
- * constructor saves instance of the applet
- * @param invaderApp - instance of the applet
- */
- public Playfield (InvaderApp invaderApp) {
-
- this.invaderApp = invaderApp;
- addMouseListener(this);
- addMouseMotionListener(this);
-
- }
-
- /*
- * game action thread
- */
- public void run() {
-
- psize = getSize();
- offscreen = createImage (psize.width, psize.height);
- offgraphics = offscreen.getGraphics ();
- font = new Font ("TimesRoman", Font.BOLD, 18);
- offgraphics.setFont (font);
-
- while (true) {
- compute ();
- repaint ();
- try {
- Thread.sleep(25);
- } catch (InterruptedException e) { }
- }
- }
-
- /*
- * calculate new positions for all objects
- */
- synchronized void compute () {
-
- for (int i=0; i<NInvaders; i+=1) {
- invaders[i].compute (psize.width, psize.height);
- if (invaders[i].killer (player.mx, player.my)) {
- invaderApp.hit (INVADER_HIT);
- player.fired = false;
- score += invaders[i].value;
- }
- if (player.killer (invaders[i].mx, invaders[i].my)) {
- invaderApp.hit (PLAYER_HIT);
- invaders[i].fired = false;
- playerLives -= 1;
- if (playerLives < 1) player.inplay = false;
- }
- }
- player.compute ();
- }
-
- /**
- * override default update
- * draw into offscreen image and then copy it to the screen
- * @param g - destination graphics object
- */
- public synchronized void update(Graphics g) {
-
- offgraphics.setColor (bgcolor);
- offgraphics.fillRect (0, 0, psize.width, psize.height);
-
- for (int i = 0 ; i < NInvaders ; i++)
- if (invaders[i].inplay) invaders[i].paint (offgraphics, this);
- player.paint (offgraphics, this);
-
- offgraphics.setColor (Color.green);
- offgraphics.drawString ("Score", 10, 20);
- offgraphics.drawString (Integer.toString (score), 60, 20);
- offgraphics.drawString ("Level", psize.width>>1, 20);
- offgraphics.drawString (Integer.toString (playLevel),
- (psize.width>>1)+50, 20);
- offgraphics.drawString ("Lives", psize.width-80, 20);
- offgraphics.drawString (Integer.toString (playerLives),
- psize.width-30, 20);
- if (playerLives < 1) offgraphics.drawString ("Game Over",
- (psize.width>>1)-30, psize.height>>1);
- g.drawImage (offscreen, 0, 0, null);
- }
-
-
- /*
- * Start the game thread
- */
- public void start() {
-
- theThread = new Thread (this);
- theThread.start ();
- }
-
- /*
- * Stop the game thread
- */
- public void stop() {
-
- if (theThread != null)
- theThread = null;
- }
- public void mouseClicked(MouseEvent e){}
- public void mouseEntered(MouseEvent e){}
- public void mouseExited(MouseEvent e){}
-
- public void mouseReleased(MouseEvent e){}
-
- public void mouseMoved(MouseEvent e)
- {
- int x =e.getX();
- int y =e.getY();
- player.x = x;
- player.y = psize.height-45;
- if (player.x < 20) player.x = 20;
- if (player.x > psize.width-20) player.x = psize.width-20;
- }
-
-
- public void mousePressed(MouseEvent e)
- {
- player.fire ();
- }
-
- public void mouseDragged(MouseEvent e)
- {
- }
-
- }
-
- /*
- * the applet class
- */
- ///////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////
- public class InvaderApp extends Applet implements ActionListener
- {
-
- /*
- * the playfield instance
- */
- Playfield panel;
-
- Button btnNewGame;
-
- /*
- * temporary storage for images
- */
- Image img[] = new Image[4];
-
- /*
- * the speed of the game
- * the number of invaders in this round
- */
- int speed, NInvadersInPlay;
-
- /*
- * Called when the applet is loaded
-
- * Load the images
- */
- public void init() {
-
- int i;
- MediaTracker tracker = new MediaTracker (this);
-
- setLayout(new BorderLayout());
-
- panel = new Playfield (this);
- add("Center", panel);
- Panel p = new Panel();
- add("South", p);
- btnNewGame = new Button("New Game");
- p.add(btnNewGame);
- btnNewGame.addActionListener(this);
-
-
- showStatus ("Getting Invader images...");
- for (i=0; i<4; i+=1) {
- img[i] = getImage (getDocumentBase(), "T"+(i+1)+".gif");
- tracker.addImage (img[i], 0);
- }
-
- try {
- tracker.waitForID(0);
- } catch (InterruptedException e) { }
-
- for (i=0; i<panel.MaxInvaders; i+=1) {
- panel.invaders[i] = new Invader ();
- panel.invaders[i].inplay = false;
- panel.invaders[i].img[0] = img[0];
- panel.invaders[i].img[1] = img[1];
- panel.invaders[i].img[2] = img[2];
- panel.invaders[i].img[3] = img[3];
- }
- panel.player = new Player ();
-
- showStatus ("Getting player images...");
- panel.player.img1 = getImage (getDocumentBase(),"Player1.gif");
- panel.player.img2 = getImage (getDocumentBase(),"Player2.gif");
-
- tracker.addImage (panel.player.img1, 1);
- tracker.addImage (panel.player.img2, 1);
- try {
- tracker.waitForID (1);
- } catch (InterruptedException e) { }
- showStatus ("Ready to play!");
- }
-
- /*
- * Start the action thread
- */
- public void start() {
-
- panel.start();
- }
-
- /*
- * Stop the action thread
- */
- public void stop() {
-
- panel.stop();
- }
-
- public void actionPerformed(ActionEvent ev)
- {
- speed = 10;
- panel.player.inplay = true;
- panel.playerLives = 3;
- panel.score = 0;
- panel.playLevel = 1;
- NInvadersInPlay = 2 * panel.playLevel + 1;
- panel.NInvaders = NInvadersInPlay;
- for (int i=0; i<panel.NInvaders; i+=1)
- panel.invaders[i].random (speed,
- panel.psize.width, panel.psize.height);
-
- play (getCodeBase(), "gong.au");
- if (NInvadersInPlay >= panel.MaxInvaders)
- NInvadersInPlay = panel.MaxInvaders;
- }
-
- /**
- * Play the appropriate sound when something is hit
- * @param which - which sound to play
- */
- public void hit (int which) {
-
- switch (which) {
- case Playfield.INVADER_HIT:
- NInvadersInPlay -= 1;
- if (NInvadersInPlay < 1) {
- play (getCodeBase(), "gong.au");
- panel.playLevel += 1;
- NInvadersInPlay = 2 * panel.playLevel + 1;
- speed += 4;
- panel.NInvaders = NInvadersInPlay;
- for (int i=0; i<panel.NInvaders; i+=1)
- panel.invaders[i].random (speed,
- panel.psize.width, panel.psize.height);
- } else {
- play (getCodeBase(), "drip.au");
- }
- break;
-
- case Playfield.PLAYER_HIT:
- play (getCodeBase(), "doh2.au");
- break;
- }
- }
- }
-