
// WormChase.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th

/* Červík se pohybuje přes obrazovku a uživatel musí
   klepnout (stisknout) na jeho hlavu.

   Pokud ji uživatel mine, přidá se na obrazovku modrá
   kostička (pokud neklepnul na tělo červíka).

   Červík se přes tuto kostičku nemůže pohybovat, takže 
   přidaná překážka může usnadnit lov.

   Červík začíná na nulové délce a roste až do své
   maximální délky, která mu zůstane.

   Na konci se na obrazovce zobrazí dosažený počet bodů,
   vypočítáný z počtu kostiček a uplynulého času. Méně kostiček
   a kratší čas znamená vyšší skóre.

   -------------
   
   'Téměř' přes celou obrazovku, protože titulková lišta a dekorace (okraje) 
   okna typu JFrame jsou stále viditelné, stejně jako např. panel úloh operačního
   systému a textová pole pod panelem JPanel.
  
   Obrazovka zahrnuje dvě textová pole pro zobrazení aktuálního času
   a počtu kostiček. Průměrné hodnoty FPS/UPS se vykreslují do herního
   panelu.   
   
   Pozastavení, opětovné spuštení a ukončení je řízeno přes naslouchací metody 
   hlavního okna.

   Jakýkoliv pohyb okna je anulován a okno je vráceno zpět do své původní
   polohy.

   Používá časovač knihovny Java 3D: J3DTimer.getValue()
     *  nanosekundy místo millisekund

   Průměrné hodnoty FPS / UPS
		     20		50	    80		100
   Win 98:         20/20       49/50       75/83       86/100
   Win 2000:       20/20       20/50       20/83       20/100
   Win XP (1):     20/20       50/50       82/83       87/100
   Win XP (2):     20/20       50/50       75/83       75/100

   Umístěn v adresáři /WormAFS

*/

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


public class WormChase extends JFrame implements WindowListener
{
  private static int DEFAULT_FPS = 80;

  private WormPanel wp;
  private JTextField jtfBox;   // zobrazí počet dosud použitých krabiček
  private JTextField jtfTime;  // zobrazí čas dosud strávený ve hře

  private int pWidth, pHeight;   // rozměry panelu


  public WormChase(long period)
  { super("The Worm Chase");

    makeGUI();

    pack();   // první (GUI dosud neobsahuje panel JPanel) 
    setResizable(false);   // velikosti prvků se mohou změnit, nelze-li měnit jejich velikost
    calcSizes();
    setResizable(true);

    Container c = getContentPane();
    wp = new WormPanel(this, period, pWidth, pHeight);
    c.add(wp, "Center");
    pack();  // druhé, po přidání panelu JPanel

    addWindowListener( this );

    addComponentListener( new ComponentAdapter() {
      public void componentMoved(ComponentEvent e) 
      /* Volá se z naslouchacího objektu typu Component při 
         pohybu okna. Vrátí jej zpět do původní pozice. */
      {  setLocation(0,0);  }
    });

    setResizable(false);
    setVisible(true);
  }  // konec konstruktoru: WormChase()


  private void makeGUI()
  // Vytvoří GUI bez vykreslovací oblasti panelu JPanel
  {
    Container c = getContentPane();    // použije implicitní BorderLayout

    JPanel ctrls = new JPanel();   // řádek s textovými poli
    ctrls.setLayout( new BoxLayout(ctrls, BoxLayout.X_AXIS));

    jtfBox = new JTextField("Použitých krabiček: 0");
    jtfBox.setEditable(false);
    ctrls.add(jtfBox);

    jtfTime = new JTextField("Celkový čas: 0 sekund");
    jtfTime.setEditable(false);
    ctrls.add(jtfTime);

    c.add(ctrls, "South");
  }  // konec metody: metody: makeGUI()


  public void setBoxNumber(int no)
  {  jtfBox.setText("Použitých krabiček: " + no);  }

  public void setTimeSpent(int t)
  {  jtfTime.setText("Celkový čas: " + t + " sekund");  }


  private void calcSizes()
  /* Vypočítá velikost kreslícího panelu, který má být přes celou obrazovku,
     ovšem ponechávaje prostor pro titulní lištu a dekorace okna a 
     další prvky OS a textová pole pod panelem JPanel.
  */
  {
    GraphicsConfiguration gc = getGraphicsConfiguration();
	Rectangle screenRect = gc.getBounds();
    // System.out.println("Velikost obrazovky: " + screenRect);

    Toolkit tk = Toolkit.getDefaultToolkit();
    Insets desktopInsets = tk.getScreenInsets(gc);
    // System.out.println("OS Insets: " + desktopInsets);

    Insets frameInsets = getInsets();     // only works after a pack() call
    // System.out.println("JFrame Insets: " + frameInsets);

    Dimension tfDim = jtfBox.getPreferredSize();   // size of text field
    // System.out.println("Box TF Size: " + tfDim );
    // System.out.println("Time TF Size: " + jtfTime.getPreferredSize() );  


    pWidth = screenRect.width - (desktopInsets.left + desktopInsets.right)
                              - (frameInsets.left + frameInsets.right);

    pHeight = screenRect.height - (desktopInsets.top + desktopInsets.bottom) 
                                - (frameInsets.top + frameInsets.bottom) 
                                - tfDim.height;

    // System.out.println("pWidth: " + pWidth + "; pHeight: " + pHeight);
  }  // konec metody: calcSizes()


  // ----------------- metody implementující rozhraní WindowListener -------------

  public void windowActivated(WindowEvent e) 
  { wp.resumeGame();  }

  public void windowDeactivated(WindowEvent e) 
  {  wp.pauseGame();  }


  public void windowDeiconified(WindowEvent e) 
  {  wp.resumeGame();  }

  public void windowIconified(WindowEvent e) 
  {  wp.pauseGame(); }

  public void windowClosing(WindowEvent e)
  {  wp.stopGame();  }

  public void windowClosed(WindowEvent e) {}
  public void windowOpened(WindowEvent e) {}


  // ----------------------------------------------------

  public static void main(String args[])
  {  
    int fps = DEFAULT_FPS;
    if (args.length != 0)
      fps = Integer.parseInt(args[0]);

    long period = (long) 1000.0/fps;
    System.out.println("fps: " + fps + "; period: " + period + " ms");

    new WormChase(period*1000000L);    // ms --> nanosekundy 
  }

} // konec třídy: WormChase


