Mike Elms
*/

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.awt.geom.*;

public class Game extends JFrame {
   private GamePanel gp;       
   private JTextField jtfBox;  
   
   public Game() { 
      makeGUI();
      pack();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setResizable(false);
      setVisible(true);
   }  


   private void makeGUI() {
      Container c = getContentPane();   

      gp = new GamePanel(this);
      c.add(gp, "Center");

      JPanel ctrls = new JPanel();   
      ctrls.setLayout( new BoxLayout(ctrls, BoxLayout.X_AXIS));

      jtfBox = new JTextField("Boxes used: 0");
      jtfBox.setEditable(false);
      ctrls.add(jtfBox);

      c.add(ctrls, "South");
   }

   public void setBoxNumber(int no) { jtfBox.setText("Boxes used: " + no); }

   public static void main(String args[]) { new Game(); }
} 

class GamePanel extends JPanel implements Runnable
{
   private static final int PWIDTH = 500;   
   private static final int PHEIGHT = 400; 

   private Thread animator;          
   private boolean running = false;   
 
   private Game gameTop;
   private GameObject obs;  
   
   private Graphics dbg; 
   private Image dbImage = null;

   public GamePanel(Game game) {
      gameTop = game;

      setBackground(Color.white);
      setPreferredSize( new Dimension(PWIDTH, PHEIGHT));

      setFocusable(true);
      requestFocus();   

      obs = new GameObject(gameTop);

      addMouseListener( new MouseAdapter() {
         public void mousePressed(MouseEvent e)
            { testPress(e.getX(), e.getY()); }
      });
   }

   public void addNotify() { 
      super.addNotify();  
      startGame();      
   }

   private void startGame() { 
      animator = new Thread(this);
      animator.start();
   } 
    
   private void testPress(int x, int y) {
      obs.add(x,y);
   } 

   public void run() {
      running = true;
      while(running) {
         gameTopUpdate();
         gameTopRender();
         paintScreen();
      }
   }

   private void gameTopUpdate() { System.out.println("gameTopUpdate()"); }  


   private void gameTopRender() {
      if (dbImage == null){
         dbImage = createImage(PWIDTH, PHEIGHT);
         if (dbImage == null) {
            System.out.println("dbImage is null");
            return;
          }
      else
         dbg = dbImage.getGraphics();
      }

      dbg.setColor(Color.white);
      dbg.fillRect (0, 0, PWIDTH, PHEIGHT);
      obs.draw(dbg);
   } 
  
   private void paintScreen() { 
      Graphics g;
      try {
         g = this.getGraphics();
         if ((g != null) && (dbImage != null))
            g.drawImage(dbImage, 0, 0, null);
            g.dispose();
         }
      catch (Exception e) { System.out.println("Graphics context error: " + e); }
   }  
} 

class GameObject {
   private static final int OBJECT_LENGTH = 12;

   private ArrayList objects;   
   private Game gameTop;

   public GameObject(Game game) { 
      objects = new ArrayList();
      gameTop = game; 
   }

   synchronized public void add(int x, int y) {
      objects.add( new Rectangle(x,y, OBJECT_LENGTH, OBJECT_LENGTH)); 
      gameTop.setBoxNumber( objects.size() );  
   }

   synchronized public void draw(Graphics g) {
      Rectangle myObject;
      g.setColor(Color.blue);
      for(int i=0; i < objects.size(); i++) {
         myObject = (Rectangle) objects.get(i);      
         g.fillOval( myObject.x, myObject.y, myObject.width, myObject.height);
      }
   }  

   synchronized public int getNumGameObject() { return objects.size(); }
}