import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;

public class Bricks implements ActionListener,ItemListener,MouseMotionListener
{
  public static final int WIDTH_SMALL = 305;
  public static final int HEIGHT_SMALL = 250;
  public static final int WIDTH_MEDIUM = 500;
  public static final int HEIGHT_MEDIUM = 375;
  public static final int WIDTH_LARGE = 1000;
  public static final int HEIGHT_LARGE = 800;
  int width = WIDTH_SMALL;
  int height = HEIGHT_SMALL;
  int speed = 3;
  int firetag = 0;
  int score = 0;
  int time = 0;
  int x=0;
  JFrame frame = new JFrame("打砖块");
  JMenuBar bar = new JMenuBar();
  JMenu menu1 = new JMenu("File");
  JMenu menu2 = new JMenu("Option");
  JMenu menu3 = new JMenu("Help");
  JMenu submenu1 = new JMenu("Size");
  JMenu submenu2 = new JMenu("Speed");
  JMenuItem mi0 = new JMenuItem("发球",KeyEvent.VK_F2);
  JMenuItem mi1 = new JMenuItem("New Game",KeyEvent.VK_N);
  JMenuItem mi2 = new JMenuItem("Exit",KeyEvent.VK_E);
  JMenuItem mi10 = new JMenuItem("Pause",KeyEvent.VK_P);
  JMenuItem mi11 = new JMenuItem("Restart",KeyEvent.VK_R);
  JRadioButtonMenuItem mi3 = new JRadioButtonMenuItem("Large");
  JRadioButtonMenuItem mi4 = new JRadioButtonMenuItem("Medium");
  JRadioButtonMenuItem mi5 = new JRadioButtonMenuItem("Small",true);
  JMenuItem mi6 = new JMenuItem("Accelerate",KeyEvent.VK_A);
  JMenuItem mi7 = new JMenuItem("Decelerate",KeyEvent.VK_D);
  JMenuItem mi8 = new JMenuItem("Fire Ball",KeyEvent.VK_F);
  JMenuItem mi9 = new JMenuItem("Information",KeyEvent.VK_I);
  MyPanel panel = new MyPanel();
  JPanel scoreboard = new JPanel();
  JLabel label1 = new JLabel("score:"+score);
  JLabel label2 = new JLabel("time:"+time);
  Timer timer2 = new Timer();

  public static void main(String args[])
  {
    Bricks bricks = new Bricks();
    bricks.go();
  }
  
  public void scoreBoard()
  {
    TimerTask task = new TimerTask()
    {
      public void run(){
        label1.setText("score:"+panel.getScore());
        label2.setText("time:"+panel.getTime());
        if (panel.getWinState() == 1)
        {
          this.cancel();
        }
      }
    };
    timer2.schedule(task,10,10);
  }
  
  public void go()
  {
    
    //建菜单
    mi3.setMnemonic(KeyEvent.VK_L);
    mi4.setMnemonic(KeyEvent.VK_M);
    mi5.setMnemonic(KeyEvent.VK_S);
    ButtonGroup group = new ButtonGroup();
    group.add(mi3);
    group.add(mi4);
    group.add(mi5);
    bar.add(menu1);
    bar.add(menu2);
    bar.add(menu3);
    menu1.add(mi0);
    menu1.add(mi1);
    menu1.add(mi10);
    menu1.add(mi11);
    menu1.add(mi2);
    menu2.add(submenu1);
    menu2.add(submenu2);
    menu2.addSeparator();
    menu2.add(mi8);
    menu3.add(mi9);
    submenu1.add(mi3);
    submenu1.add(mi4);
    submenu1.add(mi5);
    submenu2.add(mi6);
    submenu2.add(mi7);
    mi0.addActionListener(this);
    mi1.addActionListener(this);
    mi2.addActionListener(this);
    mi3.addItemListener(this);
    mi4.addItemListener(this);
    mi5.addItemListener(this);
    mi6.addActionListener(this);
    mi7.addActionListener(this);
    mi8.addActionListener(this);
    mi9.addActionListener(this);
    mi10.addActionListener(this);
    mi11.addActionListener(this);
    frame.setJMenuBar(bar);
    frame.add(panel,BorderLayout.CENTER);
    frame.add(scoreboard,BorderLayout.SOUTH);
    scoreboard.add(label1);
    scoreboard.add(label2);
    mi11.setEnabled(false);
    mi10.setEnabled(false);
    
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(width,height);
    frame.setVisible(true);
  }
  
  public void actionPerformed(ActionEvent e)
  {
    if(e.getActionCommand() == "Exit")
    {
      System.exit(0);
    }
    if(e.getActionCommand() == "Fire Ball")
    {
      if (firetag == 0)
      {
        firetag = 1;
      }
      if (firetag == 1)
      {
        firetag = 0;
      }
      panel.setFire(firetag);
    }
    if(e.getActionCommand() == "Accelerate")
    {
      speed += 1;
      if (speed == 5)
      {
        mi6.setEnabled(false);
      }
      mi7.setEnabled(true);
    }
    if(e.getActionCommand() == "Decelerate")
    {
      speed -= 1;
      if (speed == 1)
      {
        mi7.setEnabled(false);
      }
      mi6.setEnabled(true);
    }
    if(e.getActionCommand() =="发球")
    {
      panel.addMouseMotionListener(this);
      double xco = Math.random();
      while ((int)(4*(xco-0.5)) == 0)
      {
        xco = Math.random();
      }
      panel.setAngle(xco);
      panel.ballFlyOut(speed);
      mi10.setEnabled(true);
      this.scoreBoard();
    }
    if(e.getActionCommand() =="New Game")
    {
      panel.removeMouseMotionListener(this);
      panel.initiate();
      panel.repaint();
      label1.setText("score:"+0);
      label2.setText("time:"+0);
    }
    if (e.getActionCommand() == "Pause")
    {
      panel.pause();
      mi11.setEnabled(true);
      mi10.setEnabled(false);
    }
    if (e.getActionCommand() == "Restart")
    {
      panel.restart();
      mi10.setEnabled(true);
      mi11.setEnabled(false);
    }
  }
  
  public void mouseDragged(MouseEvent e)
  {
  }
  public void mouseMoved(MouseEvent e)
  {
    panel.setX(e.getX());
    panel.repaint();
  }
  
  public void itemStateChanged(ItemEvent e)
  {
    JMenuItem anItem = (JMenuItem)e.getSource();
    if (anItem == mi5)
    {
      width = WIDTH_SMALL;
      height = HEIGHT_SMALL;
    }
    if (anItem == mi4)
    {
      width = WIDTH_MEDIUM;
      height = HEIGHT_MEDIUM;
    }
    if (anItem == mi3)
    {
      width = WIDTH_LARGE;
      height = HEIGHT_LARGE;
    }
    frame.setSize(width,height);
    panel.setSiza(width);
  }
}

class MyPanel extends JPanel
{
  int size = 1;
  Graphics graphics;
  int matrix[][] = new int [3][6];
  int x = 125;
  int ballx = 150;
  int bally = 150;
  Timer timer = new Timer("Timer1",false);
  int orientationp = 1;
  int orientationv = 1;
  int firetag = 0;
  double angle = 0;
  JLabel labelOver = new JLabel("");
  int score = 0;
  int time = 0;
  int winState = 0;
  int winMark = 1;
  
  MyPanel()
  {
    //this.addMouseListener();
    super();
    for (int i=0;i<3;i++)
    {
      for (int j=0;j<6;j++)
      { 
        matrix[i][j]=1;
      }
    }
    add(labelOver);
  }
  
  public void initiate()
  {
    //timer.cancel();
    x = 125;
    ballx = 150;
    bally = 150;
    for (int i=0;i<3;i++)
    {
      for (int j=0;j<6;j++)
      { 
        matrix[i][j]=1;
      }
    }
    score = 0;
    time = 0;
    timer = new Timer("Timer1",false);
    labelOver.setText("");
    winState = 0;
    winMark = 1;
  }
  
  public void setSiza(int a)
  {
    if (a == Bricks.WIDTH_SMALL)
    {
      size = 1;
      this.paint(graphics);
    }
    if (a == Bricks.WIDTH_MEDIUM)
    {
      size = 2;
      x = 200;
      ballx = 245;
      bally = 275;
      repaint();
      time = 0;
      score = 0;
    }
    if (a == Bricks.WIDTH_LARGE)
    {
      size = 3;
      //this.paint(graphics);
    }
  }
  
  public void paint(Graphics g)
  {
    super.paint(g);
    if (size == 1)
    {
      g.drawRect(x,160,60,10);
      g.drawOval(ballx,bally,10,10);
      for (int i=0;i<3;i++)
      {
        for (int j=0;j<6;j++)
        {
          if (matrix[i][j] == 1)
          {
            g.drawRect(50*j+3,15*i+3,50,15);
          }
        }
      }
      if (size == 2)
      {
        g.drawRect(x,285,60,10);
        g.drawOval(ballx,bally,10,10);
      }
      /*g.drawRect(3,3,50,15);
      g.drawRect(53,3,50,15);
      g.drawRect(103,3,50,15);
      g.drawRect(153,3,50,15);
      g.drawRect(203,3,50,15);
      g.drawRect(253,3,50,15);
      g.drawRect(3,18,50,15);
      g.drawRect(53,18,50,15);
      g.drawRect(103,18,50,15);
      g.drawRect(153,18,50,15);
      g.drawRect(203,18,50,15);
      g.drawRect(253,18,50,15);
      g.drawRect(3,33,50,15);
      g.drawRect(53,33,50,15);
      g.drawRect(103,33,50,15);
      g.drawRect(153,33,50,15);
      g.drawRect(203,33,50,15);
      g.drawRect(253,33,50,15);*/
    }
  }
  
  public void ballFlyOut(int speed)
  {
    long delay = 50/speed;
    TimerTask task = new TimerTask()
    {
      public void run()
      {
        time = time + 1;
        if ((ballx > 295) || (ballx < 5))
        {
          orientationp = -orientationp;
        }
        if (bally < 3)
        {
          orientationv = -1;
        }
        if (touchTheGround())
        {
          orientationv = 1;
        }
        else
        {
          ballx = ballx+(int)(4*(angle-0.5)*orientationp);
          bally = bally-1*orientationv;
          repaint();
          touchTheBricks();
          if (winMark == 0)
          {
            labelOver.setText("You Win!");
            timer.cancel();
          }
        }
        if (bally>180)
        {
          labelOver.setText("Game Over!");
          timer.cancel();
          winState = 1;
        }
      }
    };
    timer.schedule(task,delay,delay);
  }
  
  public boolean touchTheGround()
  {
    if ((ballx < x+65) && (ballx > x-5) && (bally < 152) 
          && (bally > 148) && (orientationv == -1))
    {
      angle = angle+(ballx-(x+30))/20+Math.random()/10;
      if (angle > 1)
      {
        angle = 1;
      }
      if (angle < 0)
      {
        angle = 0;
      }
      return true;
    }
    else
    {
      return false;
    }
  }
  
  public void touchTheBricks()
  {
    winMark = 0;
    for (int i=0;i<3;i++)
    {
      for (int j=0;j<6;j++)
      {
        if (matrix[i][j] == 1)
        {
          winMark = 1;
          if ((bally < i*15+19) && (ballx > 50*j) && 
              (ballx < 50*j+50) && (bally > i*15+16))
          {
            orientationv = -1;
            matrix[i][j] = 0;
            score += 5;
            if (firetag == 1)
            {
              if (i > 0)
              {
                matrix[i-1][j] = 0;
              }
              if (j > 0)
              {
                matrix[i][j-1] = 0;
              }
              if (j < 6)
              {
                matrix[i][j+1] = 0;
              }
            }
            break;
          }
          if ((bally < i*15+15) && (ballx > 50*j-6) && 
              (ballx < 50*j+56))
          {
            orientationp = -orientationp;
            matrix[i][j] = 0;
            if (firetag == 1)
            {
              if (i > 0)
              {
                matrix[i-1][j] = 0;
              }
              if (j > 0)
              {
                matrix[i][j-1] = 0;
              }
              if (j < 6)
              {
                matrix[i][j+1] = 0;
              }
            }
            break;
          }
        }
      }
    }
  }
  
  public void pause()
  {
    try
    {
      timer.wait(0);
    }
    catch (Exception e)
    {
      System.out.println(e);
    }
  }
  public void restart()
  {
    timer.notify();
  }
  //传数据
  public void setX(int xco)
  {
    x = xco-30;
  }
  public void setFire(int f)
  {
    firetag = f;
  }
  public void setAngle(double a)
  {
    angle = a;
  }
  public int getTime()
  {
    return time;
  }
  public int getScore()
  {
    return score;
  }
  public int getWinState()
  {
    return winState;
  }
}