#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include "Timer.h"

#include "Partikel.h"

// MFC - Assists in finding memory leaks:
#ifdef MFC_DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#pragma warning( disable : 4996 )

/****************************************************************************/
/** \brief Konstruktor
    \param zone zoneNr, bzw zoneID
    \param action RESPAWN_AT_EMITTER, NO_RESPAWN, RESPAWN_REFLECTON ...
*****************************************************************************/
Partikel::Partikel(int zone, int action)
{
m_zone     = zone;
m_action   = action;

m_pos.set(0,0,0);  
m_velocity.set(0,0,0);
m_force.set(0,0,0);
m_frames = 0;

m_status  = IS_OFF;
m_ONtime  = 0; 
m_ONstart = 0; 
m_OFFtime = 0; 
m_OFFstart= 0;

m_ROLLtime  = 0; 
m_ROLLstart = 0;

m_spriteCount  = 0;
m_currSpriteID = 0;
m_sprite = 0;

m_isFading = false;
}

/****************************************************************************/
/** \brief Destruktor
*****************************************************************************/
Partikel::~Partikel()
{

}

/****************************************************************************/
/** \brief Setter fuer die Bewegungsparameter
    \param startpos Startposition
    \param velocity  Startgeschwindigkeit
    \param force  Kraft (z.B. Gravitationskraft)
*****************************************************************************/
void Partikel::setMotion(Vec& startpos, Vec& velocity, Vec& force)
{
m_emitterPos.set(startpos);
Object2D::setPos(startpos);

m_useSpeed = false;
m_velocity.set(velocity);
m_force.set(force);
}

/****************************************************************************/
/** \brief Setter fuer die Bewegungsparameter
    \param startpos   Startposition
    \param randomMin  Startposition
    \param randomMax  Startgeschwindigkeit
    \param speed      Startgeschwindigkeit
    \param force      Kraft (z.B. Gravitationskraft)
*****************************************************************************/
void Partikel::setMotion(Vec& startpos, Vec& randomMin, Vec& randomMax, float speed, Vec& force)
{
m_emitterPos.set(startpos);
Object2D::setPos(startpos);

m_randomMin.set(randomMin);
m_randomMax.set(randomMax);

m_speed = speed;

m_useSpeed = true;
calcVelocity();

m_force.set(force);
}

/****************************************************************************/
/** \brief Berechnet die Bewegung
*****************************************************************************/
void Partikel::calcVelocity(void)
{
   float x = m_randomMax.m_x - m_randomMin.m_x;
   float y = m_randomMax.m_y - m_randomMin.m_y;
   float z = m_randomMax.m_z - m_randomMin.m_z;
   
   m_velocity.m_x = m_randomMin.m_x + (float)(rand() % (int)x);
   m_velocity.m_y = m_randomMin.m_y + (float)(rand() % (int)y);
   m_velocity.m_z = m_randomMin.m_z + (float)(rand() % (int)z);

   m_velocity.normalize();
   m_velocity.mul(m_speed); 
}

/****************************************************************************/
/** \brief Getter fuer die AKTIVE Zeit
    \return zeit in millisec.
*****************************************************************************/
float Partikel::getONtime()
{
if (m_ONtime == 0)
   return 0;

unsigned long tnow = getMSTimer();
if (m_ONstart == 0)
   m_ONstart = tnow;

unsigned long tdiff = tnow - m_ONstart;

float erg = (float)tdiff / (float)m_ONtime;

return (erg);
}

/****************************************************************************/
/** \brief Liefert der Refreshstatus
    \return status
*****************************************************************************/
int Partikel::refreshStatus(void)
{
if (m_status == IS_DEAD)
   return (IS_DEAD);

unsigned long tnow = getMSTimer();
unsigned long tdiff;

if (m_OFFstart == 0)
   m_OFFstart = tnow;

if (m_status == IS_OFF)
   {
   tdiff = tnow - m_OFFstart;
   if (tdiff > m_OFFtime)
      {
      m_ONstart = tnow;
      m_status = IS_ON;
      return (SWITCH_ON);
      }
   }

if (m_ONtime == 0)
  return (m_status);

if (m_ONstart == 0)
   m_ONstart = tnow;

if (m_status == IS_ON)
   {
   tdiff = tnow - m_ONstart;
   if (tdiff > m_ONtime)
      {
      m_OFFstart = tnow;
      m_status = IS_OFF;
      return (SWITCH_OFF);
      }
   }

return (m_status);
}

/****************************************************************************/
/** \brief Animiert dieses Partikel
*****************************************************************************/
void Partikel::animate(void)
{
int stat = refreshStatus();
float t = 0;

switch (stat)
   {
   case IS_DEAD:
   break;

   case IS_OFF:
   break;

   case IS_ON:
   //                     1
   // x(t) = x0 + v0*f - --- g*t*t
   //                     2 

   t = m_frames++; // (float)(tnow - m_lifestart);
   m_startPosOrg.m_x = m_emitterPos.m_x + m_velocity.m_x * t - (0.5f * m_force.m_x * t * t);
   m_startPosOrg.m_y = m_emitterPos.m_y + m_velocity.m_y * t - (0.5f * m_force.m_y * t * t);
   m_startPosOrg.m_z = m_emitterPos.m_z + m_velocity.m_z * t - (0.5f * m_force.m_z * t * t);
   break;

   case SWITCH_ON:
   m_startPosOrg.set(m_emitterPos); // Respawn
   if (m_useSpeed == true)
      calcVelocity();
   m_frames=0;
   break;

   case SWITCH_OFF:
   if (m_action == NO_RESPAWN)
      m_status = IS_DEAD;
   break;

   default:
   break;
   }
}

/****************************************************************************/
/** \brief Setter fuer die Aktive Zeit
    \param ontime zeit im millisec.
*****************************************************************************/
void Partikel::setONtime(int ontime)
{
m_ONtime = (unsigned long) ontime;
}

/****************************************************************************/
/** \brief Setter fuer die Passive Zeit
    \param offtime zeit im millisec.
*****************************************************************************/
void Partikel::setOFFtime(int offtime)
{
m_OFFtime = (unsigned long) offtime;
}

/****************************************************************************/
/** \brief Richtungsvektor fuer die Bewegung
    \param rolltime Richtungsvektor
*****************************************************************************/
void Partikel::setROLLtime(int rolltime)
{
m_ROLLtime = (unsigned long) rolltime;
}

/****************************************************************************/
/** \brief Richtungsvektor fuer die Bewegung
    \param fading Richtungsvektor
*****************************************************************************/
void Partikel::setFading(bool fading)
{
m_isFading = fading;
}

/****************************************************************************/
/** \brief Liefert ON/OFF Status des Partikels
    \return true, false
*****************************************************************************/
bool Partikel::isON()
{

if (m_status == IS_ON)
   return (true);
return (false);
}

/****************************************************************************/
/** \brief Fuegt ein Sprite an das Partikel an
    \param sprite Richtungsvektor
*****************************************************************************/
void Partikel::addSprite(Sprite* sprite)
{
m_spriteOrg[m_spriteCount] = sprite; 
m_spriteCount++;

m_sprite = m_spriteOrg[0];
}

/****************************************************************************/
/** \brief Richtungsvektor fuer die Bewegung
*****************************************************************************/
void Partikel::querySprite(void)
{
if (m_spriteCount > 1)
   {
   unsigned long tnow = getMSTimer();
   unsigned long tdiff;

   if (m_ROLLstart == 0)
      m_ROLLstart = tnow;

   tdiff = tnow - m_ROLLstart;
   if (tdiff > m_ROLLtime)
      {
      m_ROLLstart = tnow;
      m_currSpriteID++;
      if (m_currSpriteID >= m_spriteCount)
          m_currSpriteID = 0;
      }      
   }

m_sprite = m_spriteOrg[m_currSpriteID];
}
