Sub Destroyer


Instructions:  1. Click on the panel to start game.  2. Use arrow keys to move destroyer.
3. Hit SPACE to drop explosive.  4. Click outside the panel to pause game.

 

Complete Source Code

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class SubDestroyer {


   private static SubDestroyerListener listener;
   private static SubDestroyerPanel myPanel;
   private static JFrame myFrame;
   private static Destroyer destroyer;
   private static Explosive explosive;
   private static Submarine submarine;
   private static int successes, failures, successRate;
   private static int bombDelay, subDelay;

   public static class SubDestroyerPanel extends JPanel {

      Color skyColor = new Color(200,200,255);
      Color seaColor = new Color(0,0,255);
      Font timesRoman = new Font("TimesRoman", Font.PLAIN, 16);
      Font courier = new Font("Courier", Font.PLAIN, 14);

      public void paintComponent(Graphics g) {

         super.paintComponent(g);

         g.setColor(skyColor);
         g.fillRect(0,0,600,150);
         g.setColor(seaColor);
         g.fillRect(0,150,600,450);

         explosive.draw(g);
         destroyer.draw(g);
         submarine.draw(g);

         g.setColor(Color.WHITE);
         g.setFont(timesRoman);
         g.drawString("\u00A9", 190, 560);
         g.setFont(courier);
         g.drawString("2011 by Dilip Muthukrishnan", 210, 560);

         g.setColor(Color.BLACK);
         g.setFont(courier);
         g.drawString("Successes = " + Integer.toString(successes),10,50);
         g.drawString("Failures = " + Integer.toString(failures),10,70);
         if (successes + failures != 0) successRate = 100*successes/(successes+failures);
         g.drawString("Success Rate = " + Integer.toString(successRate) + "%",10,90);

         g.drawString("Bomb delay = " + Integer.toString(bombDelay) + " ms",10,110);
         g.drawRect(165,98,15,15);
         g.drawString("<",168,110);
         g.drawRect(185,98,15,15);
         g.drawString(">",188,110);

         g.drawString("Sub delay = " + Integer.toString(subDelay) + " ms",10,130);
         g.drawRect(165,118,15,15);
         g.drawString("<",168,130);
         g.drawRect(185,118,15,15);
         g.drawString(">",188,130);

         if (hasFocus()) {

            g.setColor(Color.BLACK);
            g.setFont(timesRoman);
            g.drawString("Game in progress",10,20);

         }

         else {

            g.setColor(Color.BLACK);
            g.setFont(timesRoman);
            g.drawString("Game paused",10,20);

         }

      }

   }

   public static class SubDestroyerListener implements MouseListener, KeyListener,
                                                       ActionListener, FocusListener {

      public void mousePressed(MouseEvent e) {

         myPanel.requestFocus();

         if (e.getX()>165 && e.getX()<180 && e.getY()>98 && e.getY()<113 && bombDelay>1) {

            bombDelay--;
            explosive.timer.setDelay(bombDelay);
            myPanel.repaint();

         }

         if (e.getX()>185 && e.getX()<200 && e.getY()>98 && e.getY()<113 && bombDelay<100) {

            bombDelay++;
            explosive.timer.setDelay(bombDelay);
            myPanel.repaint();

         }

         if (e.getX()>165 && e.getX()<180 && e.getY()>118 && e.getY()<133 && subDelay>1) {

            subDelay--;
            submarine.timer2.setDelay(subDelay);
            myPanel.repaint();

         }

         if (e.getX()>185 && e.getX()<200 && e.getY()>118 && e.getY()<133 && subDelay<100) {

            subDelay++;
            submarine.timer2.setDelay(subDelay);
            myPanel.repaint();

         }

      }

      public void mouseReleased(MouseEvent e) {}
      public void mouseClicked(MouseEvent e) {}
      public void mouseEntered(MouseEvent e) {}
      public void mouseExited(MouseEvent e) {}

      public void keyPressed(KeyEvent e) {

         if (e.getKeyCode() == KeyEvent.VK_LEFT && destroyer.x > -50 && !submarine.hit) {

            destroyer.x -= 5;
            if (!explosive.falling) explosive.x -= 5;
            myPanel.repaint();

         }

         if (e.getKeyCode() == KeyEvent.VK_RIGHT && destroyer.x < 550 && !submarine.hit) {

            destroyer.x += 5;
            if (!explosive.falling) explosive.x += 5;
            myPanel.repaint();

         }

         if (e.getKeyCode() == KeyEvent.VK_SPACE && !explosive.falling && !submarine.hit) {

            explosive.fire();

         }

      }

      public void keyReleased(KeyEvent e) {}
      public void keyTyped(KeyEvent e) {}

      public void actionPerformed(ActionEvent e) {

         if (explosive.falling && myPanel.hasFocus()) {

            explosive.motion();

            if (explosive.falling && explosive.y == 470 && explosive.x+25 >= submarine.x
                                                        && explosive.x <= submarine.x+95) {

               explosive.targetFound = true;
               submarine.explode();
               successes++;

            }

            if (!explosive.falling) explosive = new Explosive(destroyer.x + 35,bombDelay);

            myPanel.repaint();

         }

         if (submarine.hit && myPanel.hasFocus()) {

            submarine.explosion();
            if (!submarine.hit) submarine = new Submarine(submarine.x,subDelay);
            myPanel.repaint();

         }

         if (submarine.moving && myPanel.hasFocus()) {

            submarine.motion();
            myPanel.repaint();

         }

      }

      public void focusGained(FocusEvent e) {

         myPanel.repaint();

      }

      public void focusLost(FocusEvent e) {

         myPanel.repaint();

      }

   }

   public static class Destroyer {

      int x;

      public Destroyer() {

         x = 250;

      }

      public void draw(Graphics g) {

         g.setColor(Color.DARK_GRAY);
         g.fillRect(x,125,100,25);
         g.setColor(Color.BLACK);
         g.fillArc(x,125,100,50,0,-180);

      }

   }

   public static class Explosive {

      Timer timer;
      int x, y, delay;
      Boolean falling, targetFound;

      public Explosive(int x, int delay) {

         this.x = x;
         y = 160;
         this.delay = delay;
         timer = new Timer(delay,listener);
         falling = false;
         targetFound = false;

      }

      public void draw(Graphics g) {

         g.setColor(Color.GREEN);
         g.fillOval(x,y,30,30);

      }

      public void fire() {

         falling = true;
         timer.start();

      }

      public void motion() {

         if (y == 599) failures++;
         if (y < 600 && !targetFound) y++;

         else {

            falling = false;
            targetFound = false;
            timer.stop();

         }

      }

   }

   public static class Submarine {

      Timer timer1;
      Timer timer2;
      int x, newX, r1, r2, delay;
      Boolean hit, moving;
      Color color;

      public Submarine(int x, int delay) {

         this.x = x;
         this.delay = delay;
         newX = (int) (500*Math.random());
         hit = false;
         moving = true;
         color = new Color(0,25,0);
         timer1 = new Timer(10,listener);
         timer2 = new Timer(delay,listener);
         r1 = 0;
         r2 = 0;
         timer2.start();

      }

      public void draw(Graphics g) {

         if (!hit) {

            g.setColor(color);
            g.fillOval(x,500,100,20);
            g.fillRect(x+45,490,10,12);
            g.setColor(Color.WHITE);
            for (int i = 0; i < 5; i++) g.fillOval(x+23+(12*i),507,7,7);
            g.setColor(Color.ORANGE);

         }

         else {

            g.setColor(Color.ORANGE);
            g.fillOval(x+38-r1,508-r1,25+2*r1,5+2*r1);

            if (r1 > 15) {

               g.setColor(Color.RED);
               g.fillOval(x+38-r2,508-r2,25+2*r2,5+2*r2);

            }

         }

      }

      public void motion() {

         if (newX == x) newX = (int) (500*Math.random());
         if (newX > x) x++;
         if (newX < x) x--;

      }

      public void explode() {

         hit = true;
         moving = false;
         timer2.stop();
         timer1.start();

      }

      public void explosion() {

         if (r1 < 50) {

            if (r1 > 15) r2++;
            r1++;

         }

         else {

            hit = false;
            x = (int) (500*Math.random());
            timer1.stop();
            timer2.start();
            moving = true;

         }

      }

   }

   public static void main(String[] args) {

      listener = new SubDestroyerListener();
      myPanel = new SubDestroyerPanel();
      myFrame = new JFrame("Sub Destroyer");
      destroyer = new Destroyer();
      explosive = new Explosive(285,1);
      submarine = new Submarine(250,10);
      successes = 0;
      failures = 0;
      successRate = 0;
      bombDelay = 1;
      subDelay = 10;

      myPanel.setBackground(Color.WHITE);
      myPanel.addMouseListener(listener);
      myPanel.addKeyListener(listener);
      myPanel.addFocusListener(listener);

      myFrame.add(myPanel);
      myFrame.setSize(600,600);
      myFrame.setLocation(100,100);
      myFrame.setResizable(false);
      myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      myFrame.setVisible(true);

   }


}