 /* 'mrABO.cpp' */

 /* Komplementarny plik nagłówka */
#include "mrABO.h"

 /* Konstruktor domyślny */
mrABO::mrABO (void)
{
 m_pkAnimations      = NULL;
 m_pkTexture         = NULL;
 m_iCurrentAnimation = 0;
 m_iXPosition        = 0;
 m_iYPosition        = 0;
 m_iWidth            = 0;
 m_iHeight           = 0;
 m_fAngle            = 0;
 m_fRadius           = 0;
}

 /* Destruktor domyślny */
mrABO::~mrABO (void)
{
 if (NULL != m_pkAnimations)
 {
  delete [] m_pkAnimations;
  m_pkAnimations     = NULL;
 }
 if (NULL != m_pkTexture)
 {
  delete m_pkTexture;
  m_pkTexture        = NULL;
 }
 m_iCurrentAnimation = 0;
 m_iXPosition        = 0;
 m_iYPosition        = 0;
 m_iWidth            = 0;
 m_iHeight           = 0;
 m_fAngle            = 0;
 m_fRadius           = 0;
}

 /* Utwórz ABO */
void mrABO::Create (mrUInt32 iAnimations, mrAnimation * pkAnimations)
{
 m_pkAnimations = new mrAnimation [iAnimations];

 mrUInt32 iAnimation;

 for (iAnimation = 0; iAnimation < iAnimations; iAnimation ++)
 {
  SetAnimation (iAnimation, &pkAnimations [iAnimation]);
 }
}

 /* Ustaw animację ABO */
void mrABO::SetAnimation (mrUInt32 iAnimation, mrAnimation * pkAnimation)
{
 memcpy (&m_pkAnimations [iAnimation], pkAnimation, sizeof (mrAnimation));
 m_pkAnimations [iAnimation].SetCurrentFrame (0);
}

 /* Załaduj ABO z pliku */
void mrABO::LoadFromFile (LPSTR lpszFilename)
{
 fstream      kABO;

 kABO.open (lpszFilename, ios::in);

 if (kABO.is_open ())
 {
   /* Pobierz nazwę i typ tekstury */
  mrInt8 aTextureName [256];
  kABO >> aTextureName;
  mrUInt32 iTextureType;
  kABO >> iTextureType;

   /* Załaduj obraz z teskturą */
  mrRGBAImage kTempImage;

  if (1 == iTextureType)
  {
   kTempImage.LoadFromBitmap (aTextureName);
  }
  if (2 == iTextureType)
  {
   kTempImage.LoadFromTarga (aTextureName);
  }

   /* Odczytaj informację o kluczowaniu kolorów */
  mrUInt32 iRed;
  mrUInt32 iGreen;
  mrUInt32 iBlue;
  kABO >> iRed;
  kABO >> iGreen;
  kABO >> iBlue;

  kTempImage.SetColorKey ((mrUInt8)iRed, (mrUInt8)iGreen, 
                          (mrUInt8)iBlue);
  
   /* Utwórz teksturę */
  m_pkTexture = new mrTexture ();
  m_pkTexture->Create (&kTempImage);

   /* Odczytaj informacje o zbiorze szablonów */
  mrUInt32 iCellWidth;
  mrUInt32 iCellHeight;
  kABO >> iCellWidth;
  kABO >> iCellHeight;

   /* Utwórz szablon */
  mrTemplateSet kTempTemplateSet;
  kTempTemplateSet.Create (m_pkTexture, kTempImage.GetWidth (), 
                           kTempImage.GetHeight (), iCellWidth, 
                           iCellHeight);

   /* Odczytaj liczbę animacji */
  mrUInt32 iNumberOfAnimations;
  kABO >> iNumberOfAnimations;

  mrAnimation * pkTempAnimations;
  pkTempAnimations = new mrAnimation [iNumberOfAnimations];

  mrUInt32 iAnimation;

   /* Odczytaj liczbę kadrów dla każdej animacji */
  for (iAnimation = 0; iAnimation < iNumberOfAnimations; iAnimation++)
  {
   mrUInt32 iNumberOfFrames;
   kABO >> iNumberOfFrames;

   mrCellID * pkFramePosition;
   pkFramePosition = new mrCellID [iNumberOfFrames];

   mrUInt32 iPosition;

    /* Dla każdego kadru odczytaj jego animację */
   for (iPosition = 0; iPosition < iNumberOfFrames; iPosition++)
   {
    kABO >> pkFramePosition [iPosition].m_iX;
    kABO >> pkFramePosition [iPosition].m_iY;
   }

    /* Utwórz animację */
   pkTempAnimations [iAnimation].Create (&kTempTemplateSet , 
                                         iNumberOfFrames, 
                                         pkFramePosition);
   delete [] pkFramePosition;
  }

   /* Utwórz ABO */
  Create (iNumberOfAnimations, pkTempAnimations);

  delete [] pkTempAnimations;

  kABO.close ();
 }
}

 /* Renderuj ABO */
mrError32 mrABO::Render (void)
{
 RECT kRect;

  /* Prześlij pozycję i szerokość jako RECT */
 kRect.left   = m_iXPosition;
 kRect.top    = m_iYPosition;
 kRect.right  = m_iWidth;
 kRect.bottom = m_iHeight;

 return m_pkAnimations [m_iCurrentAnimation].Render (kRect, m_iColor, 
                                                     m_fAngle);
}

 /* Aktualizuj animację ABO */
void mrABO::Update (void)
{
 m_pkAnimations [m_iCurrentAnimation].Update ();
}

void mrABO::SetCurrentAnimation (mrUInt32 iAnimation)
{
 m_iCurrentAnimation = iAnimation;
}

 /* Zwraca bieżącą animację ABO */
mrUInt32 mrABO::GetCurrentAnimation (void)
{
 return m_iCurrentAnimation;
}

 /* Sprawdza czy dwa obiekty ABO kolidują z sobą */
mrBool32 mrABO::Collide (mrABO & rkABO, mrUInt32 iUseSphere)
{
  /* Zastosowanie metody okręgów opisujących */
 if (iUseSphere)
 {
   /* Pobiera odległość od jednego ABO do drugiego */
  mrReal32 fXDelta = (mrReal32)m_iXPosition - (mrReal32)rkABO.GetXPosition ();
  mrReal32 fYDelta = (mrReal32)m_iYPosition - (mrReal32)rkABO.GetYPosition ();

  mrReal32 fDistance;
  fDistance = (mrReal32) sqrt (fXDelta * fXDelta + fYDelta * fYDelta);

  mrReal32 fRadius1, fRadius2;
 
    /* Pobierz promień każdego ABO */
  if (m_fRadius != 0)
  {
   fRadius1 = m_fRadius;
  }
  else
  {
   fRadius1 = (mrReal32) sqrt ( ((m_iWidth / 2) * (m_iWidth / 2)) + 
                                ((m_iHeight / 2) * (m_iHeight / 2)));
  }
  if (rkABO.GetRadius () != 0)
  {
   fRadius2 = rkABO.GetRadius ();
  }
  else
  {
   fRadius2 = (mrReal32) sqrt ( 
               ((rkABO.GetWidth () / 2) * (rkABO.GetWidth () / 2)) + 
               ((rkABO.GetHeight () / 2) * (rkABO.GetHeight () / 2)));
  }

   /* Jeżeli odległość jest mniejsza, niż suma promieni, zwraca mrFalse */
  if (fDistance > (fRadius1 + fRadius2))
  {
   return mrFalse;
  }
  else
  {
   return mrTrue;
  }
 }
 else
 {
   /* Prostokąty opisujące */
  mrInt32 iX0;
  mrInt32 iY0;
  mrInt32 iX1;
  mrInt32 iY1;

  iX0 = m_iXPosition - m_iWidth / 2;
  iY0 = m_iYPosition - m_iHeight / 2;
  iX1 = m_iXPosition + m_iWidth / 2;
  iY1 = m_iYPosition + m_iHeight / 2;

   /* Sprawdź wszystkie wierzchołki, czy zawierają punkt */
  if (rkABO.ContainsPoint (iX0, iY0))
  {
   return mrTrue;
  }
  if (rkABO.ContainsPoint (iX0, iY1))
  {
   return mrTrue;
  }
  if (rkABO.ContainsPoint (iX1, iY1))
  {
   return mrTrue;
  }
  if (rkABO.ContainsPoint (iX1, iY0))
  {
   return mrTrue;
  }
  
   /* Jeżeli żaden punkt nie był zawarty w środku zwraca mrFalse */
  return mrFalse;
 }
}

 /* Sprawdza czy punkt znajduje się w obrębie prostokąta */
mrBool32 mrABO::ContainsPoint (mrInt32 iX, mrInt32 iY)
{
  /* Prostokąt opisujący */
 mrInt32 iX0;
 mrInt32 iY0;
 mrInt32 iX1;
 mrInt32 iY1;

 iX0 = m_iXPosition - m_iWidth / 2;
 iY0 = m_iYPosition - m_iHeight / 2;
 iX1 = m_iXPosition + m_iWidth / 2;
 iY1 = m_iYPosition + m_iHeight / 2;

  /* Sprawdza czy punkt należy do prostokąta */
 if ((iX >= iX0) && (iX <= iX1))
 {
  if ((iY >= iY0) && (iY <= iY1))
  {
   return mrTrue;
  }
 }
 return mrFalse;
}

 /* Ustawia pozycję ABO */
void mrABO::SetPosition (mrUInt32 iX, mrUInt32 iY)
{
 m_iXPosition = iX;
 m_iYPosition = iY;
}

 /* Ustawia rozmiar ABO */
void mrABO::SetSize (mrUInt32 iWidth, mrUInt32 iHeight)
{
 m_iWidth  = iWidth;
 m_iHeight = iHeight;
}

 /* Ustawia kolor ABO */
void mrABO::SetColor (mrUInt8 iAlpha, mrUInt8 iRed, mrUInt8 iGreen, 
                      mrUInt8 iBlue)
{
 m_iColor = D3DCOLOR_ARGB (iAlpha, iRed, iGreen, iBlue);
}

 /* Ustawia promień ABO */
void mrABO::SetRadius (mrReal32 fRadius)
{
 m_fRadius = fRadius;
}

 /* Obraca ABO */
void mrABO::Rotate (mrReal32 fAngle, mrUInt32 iAccumulate)
{
 if (iAccumulate)
 {
  m_fAngle += fAngle;
 }
 else
 {
  m_fAngle = fAngle;
 }
}

 /* Zwraca poziomą pozycję ABO */
mrUInt32 mrABO::GetXPosition (void)
{
 return m_iXPosition;
}

 /* Zwraca pionową pozycję ABO */
mrUInt32 mrABO::GetYPosition (void)
{
 return m_iYPosition;
}

 /* Zwraca wysokość ABO */
mrUInt32 mrABO::GetHeight (void)
{
 return m_iHeight;
}

 /* Zwraca szerokość ABO */
mrUInt32 mrABO::GetWidth (void)
{
 return m_iWidth;
}

 /* Zwraca kolor ABO */
mrUInt32 mrABO::GetColor (void)
{
 return m_iColor;
}

 /* Zwraca kierunek ABO */
mrReal32 mrABO::GetDirection (void)
{
 return m_fAngle;
}

 /* Zwraca promień kolizyjny ABO */
mrReal32 mrABO::GetRadius (void)
{
 return m_fRadius;
}
