/*
	Asteroids
    Copyright (C) 2006  Darragh Coy.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*##############################################################################

Module name: Particle
Purpose:     Particle movement and drawing

##############################################################################*/

#include "Player.h"

/*******************************************************************************
Private module prototypes: Not for outside use!
*******************************************************************************/

   //..

/*******************************************************************************
Variables
*******************************************************************************/
   
   // The array of particles
   
   Particle_t particles[PAR_MAX_PARTICLES];
   
   // Current position in the particle array- use when creating particles..
   
   static int arrayPos = 0;
   
/*******************************************************************************

Name:       Particle_Init
Purpose:    Initialise data in the particle array
Parameters: None
Returns:    None

*******************************************************************************/  

void Particle_Init ( void ) 
{
     // Set particle array data to '0'
    
    memset(particles,0,sizeof particles);
    
    // Set particle array position to 0
    
    arrayPos = 0;
} 

/*******************************************************************************

Name:       Particle_Shift
Purpose:    Shifts all active particles by a given amount
Parameters: x amount and y amount
Returns:    None

*******************************************************************************/  

void Particle_Shift ( float x , float y )
{
   // Current particle
   
   Particle_t *pParticle = particles;
     
   // Move all active particles
   
   for ( int i = 0 ; i < PAR_MAX_PARTICLES ; i++ )
   {
       // If particle not active then continue on...
       
       if ( ! pParticle->active ){ pParticle++ ; continue ; }
       
       // Move this particle by shift amount
       
       pParticle->position.x += x;
       pParticle->position.y += y;

       // Move onto the next particle
       
       pParticle++;
   }
   
}
   
/*******************************************************************************

Name:       Particle_Move
Purpose:    Moves all active particles
Parameters: None
Returns:    None

*******************************************************************************/  

void Particle_Move ( void )
{
   // Current particle
   
   register Particle_t *pParticle = particles;
   
   // Get current time: save on function calls to Timer_FrameTime(): slow!!
   
   register float frameTime = Timer_FrameTime();
     
   // Move all active particles
   
   for ( register int i =  PAR_MAX_PARTICLES ; i > 0  ; i-- )
   {
       // Only move particle if active
       
       if ( pParticle->active )
       {
           // Move this particle by its move vector
           
           pParticle->position.x += pParticle->velocity.x * frameTime;
           pParticle->position.y += pParticle->velocity.y * frameTime;
                  
           // Take from its time left the time the last frame took
           
           pParticle->timeleft -= frameTime;
           
           // If time left < 0 then kill
           
           if ( pParticle->timeleft < 0  ){ pParticle->active = false ; }
       }
       
       pParticle++;
   }
   
}

/*******************************************************************************

Name:       Particle_Explosion
Purpose:    Creates a particle explosion centered at specified point
Parameters: Pointer to a point
Returns:    None

*******************************************************************************/ 

void Particle_Explosion ( struct Vec2D_t * center )
{
   // Pointer to current particle
   
   Particle_t * pParticle = particles + arrayPos;
   
   // Holds a random float
   
   float randomFloat;
     
   // Create a number of random particles
   
   for ( int i = 0 ; i < PAR_EXPLOSION_AMT ; i++ )
   {
       // Set this particle as active:
              
       pParticle->active = true;
       
       // Set its position randomly (scattered) around the center point 
       
       pParticle->position.x = center->x + rand() % PAR_EXPLOSION_SCATTER - PAR_EXPLOSION_SCATTER / 2;
       pParticle->position.y = center->y + rand() % PAR_EXPLOSION_SCATTER - PAR_EXPLOSION_SCATTER / 2;   
       
       // Get a random float between 1.0 and 0.0
       
       randomFloat = (float)( rand() % 65536 ) / 65535.0f;
       
       // Pick a speed between minimum and maximum speeds using this float as a interpolator
       
       float speed = PAR_MIN_SPEED * randomFloat + ( 1.0f - randomFloat ) * PAR_MAX_SPEED;
       
       // Pick another random float
       
       randomFloat = (float)( rand() % 65536 ) / 65535.0f;
       
       // Scale by 6.2831 (or 360 degress in radians ) : this is a random move angle
       
       randomFloat *= 12.4f;
       
       // Get movement vector using random speed and direction
       
       pParticle->velocity.x = cos(randomFloat) * speed;
       pParticle->velocity.y = sin(randomFloat) * speed;       
       
       // Pick another random float
       
       randomFloat = (float)( rand() % 65536 ) / 65535.0f;
       
       // Use to pick a random live time betwen minimum and maximum live times
       
       pParticle->timeleft = randomFloat * PAR_MIN_TIME + ( 1.0f - randomFloat ) * PAR_MAX_TIME;
       
       // Move onto the next particle in the array
       
       arrayPos++;
       pParticle++;
       
       // If over array boundary then rewind position to the start
       
       if ( ! ( arrayPos < PAR_MAX_PARTICLES ) )
       {
            // over array boundary: rewind..
            
            arrayPos   = 0;
            pParticle  = particles;
       }
       
   } // End create particle loop
}

/*******************************************************************************

Name:       Particle_Draw
Purpose:    Draws all active particles
Parameters: None
Returns:    None

*******************************************************************************/ 

void Particle_Draw ( void )
{
   // Pointer to current particle
   
   register Particle_t * pParticle = particles;
   
   // Set point size
   
   glPointSize(PAR_PARTICLE_SIZE);
   
   // Begin drawing
   
   glBegin(GL_POINTS);
   
   // Draw all active particles
   
   for ( register int i = PAR_MAX_PARTICLES ; i > 0 ; i-- )
   {
       // Only draw if current particle active
       
       if ( pParticle->active )
       {
          // Calculate brightness based on maximum particle time and how long it
          // has left:
       
          register float brightness = float(pParticle->timeleft) * PAR_MAX_TIME_DIVIDE;
       
          // Set color as a grayscale shade of brighness
       
          glColor3f(brightness,brightness,brightness);
       
          // Vertex
       
          glVertex2f(pParticle->position.x,pParticle->position.y);
       }

       // Move onto next particle
       
       pParticle++;
   }
   
   // End drawing
   
   glEnd();

}
