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

/* Tato třída má na starosti zobrazování přehledu, který
   obsahuje neměnný obrázek bludiště, sprite, jenž se
   pohybuje a mění směr, a občasné zobrazení
   varovné hlášky oznamující, že hráč vrazil do překážky.

   Sprite se dostat až za hranici zobrazované oblasti,
   neboť 3D-oblast zahrnuje širokou podlahu, která pokračuje
   i mimo bludiště.
*/

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


public class BirdsEye extends JPanel
{
  private static final int PWIDTH = 256;   // velikost panelu
  private static final int PHEIGHT = 256; 

  private static final int NUM_DIRS = 4;
  // tyto směry jdou, viděno shora, proti směru hodinových ručiček
  private static final int FORWARD = 0;
  private static final int LEFT = 1;
  private static final int BACK = 2;
  private static final int RIGHT = 3;

  private static final String BANG_MSG = "BUCH!";
       // varovná zpráva, že hráč narazil do překážky


  private MazeManager mm;

  private Image mazeIm;    // pro obrázek bludiště
  private Image userIm;    // pro šipku představující uživatele
  private Image arrowIms[];   // všechny možné šipky
  private int arrowWidth, arrowHeight;
  private Point moves[];

  private Point currPosn;     // aktuální pozice hráče v obrázku
  private int step;           // vzdálenost, o kterou se hráč posune v rámci obrázku
  private int compass;        // aktuální směr (značky kompasu)

  private boolean showBang;   // true, pokud se hráč pokouší hlavou prorazit zeď
  private Font msgFont;



  public BirdsEye(MazeManager mazeMan)
  {
    mm = mazeMan;
    setBackground(Color.white);
    setPreferredSize( new Dimension(PWIDTH, PHEIGHT));
    msgFont = new Font("SansSerif", Font.BOLD, 24);

    mazeIm = mm.getMazeImage();   // získej obrázek bludiště
    initMoves();
    loadArrows();
    initPosition();
    repaint();
  } // konec konstruktoru: BirdsEye()


  private void initMoves()
  /* Poskytuje pohyb ve 4 směrech. Sprite na začátku směřuje dolů (viděno shora),
     což bude směr dopředu. Pohyb dolů (tedy dopředu) znamená zvýšení y-ové hodnoty.

     Směry LEFT, RIGHT, BACK jsou vztaženy v počátečnímu směru FORWARD.
  */
  {
    moves = new Point[NUM_DIRS];
    step = mm.getImageStep();
    moves[FORWARD] = new Point(0, step);  // pohyb dolů na obrazovce
    moves[LEFT] = new Point(step, 0);     // vpravo
    moves[BACK] = new Point(0, -step);    // nahoru
    moves[RIGHT] = new Point(-step, 0);   // vlevo
  }  // konec metody: initMoves()



  private void loadArrows()
  /* Šipky preprezentují čtyři směry, ve kterých se může
     sprite pohybovat. */
  {
    arrowIms = new Image[NUM_DIRS];

    ImageIcon imIcon = new ImageIcon("images/arrowFwd.gif");
    arrowIms[FORWARD] = imIcon.getImage();
    arrowWidth = imIcon.getIconWidth();
    arrowHeight = imIcon.getIconHeight();

    arrowIms[LEFT] = new ImageIcon("images/arrowLeft.gif").getImage();
    arrowIms[BACK] = new ImageIcon("images/arrowBack.gif").getImage();
    arrowIms[RIGHT] = new ImageIcon("images/arrowRight.gif").getImage();
  } // konec metody: loadArrows()


  private void initPosition()
  /* Počáteční pozicí je startovní pozice získaná od správce bludiště a
     výchozí směr, kterým je FORWARD (vpřed - tedy dolů na obrazovce). */
  {
    currPosn = mm.getImageStartPosn();
    compass = FORWARD;
    userIm = arrowIms[FORWARD];    
        // sprite je na začátku na obrazovce otočen dolů 
    showBang = false;
  } // konec metody: initPosition()

  
  public void setMove(int dir)
  /* dir = 0-3 (FORWARD, LEFT, BACK, or RIGHT)
     Skutečný směr závisí na kombinaci aktuální hodnoty kompasu a
     parametru dir. */
  {
    int actualHd = (compass + dir) % NUM_DIRS;
    Point move = moves[actualHd];
    currPosn.x += move.x;
    currPosn.y += move.y;
    repaint();
  } // konec metody: setMove()


  public void setRotation(int dir)
  /* Rotations affect the compass heading, which will then 
     affect future movements. dir is LEFT or RIGHT. */
  { 
    compass = (compass + dir) % NUM_DIRS;
    userIm = arrowIms[compass];
    repaint();
  } // konec metody: setRotation()


  public void bangAlert()
  // Vyžádá si překreslení, takže se zobrazení zpráva o nárazu do překážky
  { showBang = true; 
    repaint();
  }


  public void paintComponent(Graphics g)
  /* Vykreslí obrázek bludiště, poté hráče a nakonec, je-li
     nastavena, zprávu o nárazu do překážky. */
  { 
    super.paintComponent(g);   // nejdříve vykresli standardní věci 
    g.drawImage(mazeIm, 0, 0, null);   // poté bludiště

    int xPos = currPosn.x + step/2 - arrowWidth/2;
    int yPos = currPosn.y + step/2 - arrowHeight/2;
    g.drawImage(userIm, xPos, yPos, null);    // pak hráče

    if (showBang) {    // a nakonec zprávu o nárazu do překážky
      g.setColor(Color.red);
      g.setFont(msgFont);
      g.drawString(BANG_MSG, PWIDTH/2, PHEIGHT/2);
      showBang = false;
    }
  }  // konec metody: paintComponent()


} // konec třídy: BirdsEye