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

/* Balón padá z horního okraje panelu různými rychlostni a míří dolů
   pod různými úhly. Od zdí se patřičným způsobem odráží.

   Zasáhne-li pálku, odrazí se vzhůru a zmizí za horním okrajem obrazovky.
   Pokud jej mine, zmizí pod dolním okrajem panelu.

   Po opuštění obrazovky je balón umístěn zpět k hornímu okraji panelu
   a znovu použit.

   Počet vrácených míčků sledujeme pomocí proměnné numRebounds. Když ale
   míček propadne pod podalhu, numRebounds o jedničku snížíme.

   Dosáhne-li proměnná numRebounds hodnoty MAX_BALLS_RETURNED, hra končí.
   Konec hry nastává také v případě, kdy její hodnota klesne na 0.

   Balón reprezentuje několik odlišných obrázků, 
   které se při každém jeho použití mění.

   K tomu se při kontaktu se stěnami nebo s pálkou přehrávají příslušné 
   zvukové klipy.
*/

import java.awt.*;


public class BallSprite extends Sprite
{
  // hodnoty kroků balónu ve směru x a y jsou STEP +/- STEP_OFFSET
  private static final int STEP = 8;
  private static final int STEP_OFFSET = 2;

  private static final String[] ballNames = 
              {"rock1", "orangeRock", "computer", "ball"};   
    // obrázky používané pro náš míček

  // pro ukončení hry je potřeba odpálit následující počet míčků
  private static final int MAX_BALLS_RETURNED = 16; 


  private int nameIndex;  // pro vlobu jména míčku

  private ClipsLoader clipsLoader;   

  private BugPanel bp;
  private BatSprite bat;

  private int numRebounds;


  public BallSprite(int w, int h, ImagesLoader imsLd, ClipsLoader cl,
                                             BugPanel bp, BatSprite b) 
  { 
    super( w/2, 0, w, h, imsLd, ballNames[0]);  
           // míček umístíme doprostřed vrchí části panelu
    clipsLoader = cl;
    this.bp = bp;
    bat = b;

    nameIndex = 0;
    numRebounds = MAX_BALLS_RETURNED/2;  
        // počet odpálených míčků začíná na poloviční hodnotě jejich maxima
    initPosition();
  }


  private void initPosition()
  // inicializuje obrázek, pozici a hodnoty kroků (rychlost) míčku
  { 
    setImage( ballNames[nameIndex]);
    nameIndex = (nameIndex+1)%ballNames.length;

    setPosition( (int)(getPWidth() * Math.random()), 0);   
                                  // někde podél horního okraje

    int step = STEP + getRandRange(STEP_OFFSET);
    int xStep = ((Math.random() < 0.5) ? -step : step); // pohybuj se zleva doprava
    setStep(xStep, STEP + getRandRange(STEP_OFFSET));   // pohybuj se dolů
  }  // konec metody: initPosition()


  private int getRandRange(int x) 
  // generátor náhodných čísel v rozmezí od -x do x
  {   return ((int)(2 * x * Math.random())) - x;  }



  public void updateSprite() 
  {
    hasHitBat();
    goneOffScreen();
    hasHitWall();
    // System.out.println("ball (" + locx + ", " + locy + ")");

    super.updateSprite();
  }  // konec metody: updateSprite()


  private void hasHitBat()
  /* Zasáhne-li míček pálku, odrazí jej zpět.
     Hodnota y-ového kroku se převrátí a míček se posune kousek nahoru,
     aby již neprotínal pálku. 
  */
  {
    Rectangle rect = getMyRectangle();
    if (rect.intersects( bat.getMyRectangle() )) {     // kolize s pálkou?
      clipsLoader.play("hitBat", false);
      Rectangle interRect = rect.intersection(bat.getMyRectangle());
      dy = -dy;       // převrať přírustek míčku ve směru osy y
      locy -= interRect.height;    // posuň míček nahoru
    }
  } // konec metody: hasHitBat()



  private void goneOffScreen()
  /* Reakce na to, když míček opustí horní nebo dolní okraj panelu.
     Upraví proměnnou numRebounds a buď ukončí hru nebo znovupoužije míček. */
  {
    if (((locy+getHeight()) <= 0) && (dy < 0)) { // za horním okrajem a pohybuje se nahoru
      numRebounds++;
      if (numRebounds == MAX_BALLS_RETURNED)
        bp.gameOver();    // hra dokončena
      else
        initPosition();   // sposť míček od nové pozice
    }
    else if ((locy >= getPHeight()) && (dy > 0)) { // míček je pod dolním okrajem a pohybuje se dolů
      numRebounds--;
      if (numRebounds == 0)
        bp.gameOver();
      else
        initPosition();
    }
  }  // konec metody: goneOffScreen()



  private void hasHitWall()
  /* Reakce na to, když míček zasáhne stěnu.
     Změní jeho směr (dx/dy) pouze v případě, kdy letí za okraj.
  */
  {
    if ((locx <= 0) && (dx < 0)) {  // dotýká se levé stěny a pohybuje se vlevo
      clipsLoader.play("hitLeft", false);
      dx = -dx;   // přesun vravo
    }
    else if ((locx+getWidth() >= getPWidth()) && (dx > 0)) {   
		                           // dotýká se pravé stěny a pohybuje se vpravo
      clipsLoader.play("hitRight", false);
      dx = -dx;   // přesun vlevo
    }
  } // konec metody: hasHitWall()



  public void drawBallStats(Graphics g, int x, int y)
  // Volá se ze třídy BugPanel pro vypsání počtu vrácených míčků
  {  g.drawString("Vráceno: " + numRebounds + "/" + MAX_BALLS_RETURNED, x, y);  } 

}  // konec třídy: BallSprite
