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

	Bubble Fight EX
	relminator
	http://rel.betterwebber.com


	RotoSpark class


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


#include "RotoSpark.h"


#define MIN_X ( -16 << 12 )
#define MIN_Y ( -16 << 12 )

#define MAX_ROTOSPARKS 16

//------------------------------------------------------------------------------
//	RotoSpark Enemy
//------------------------------------------------------------------------------
RotoSpark::RotoSpark()
{
	Frame = 0;
	Active = false;
}

RotoSpark::~RotoSpark()
{
}

void RotoSpark::Update()
{
	x += Dx;
	y += Dy;
	
	if( x < MIN_X )
	{
		Active = false;
		x = 300 << 12;
		y = 96 << 12;
	}
	
	Counter++;
	// animate
	if( ( Counter & 3 ) == 0 )
	{
		Frame = (Frame + 1);
		if( Frame > 2 ) Frame = 0;
	}

}


//------------------------------------------------------------------------------
//	RotoSpark Container
//------------------------------------------------------------------------------
//--------------------------------------
//	Ctor and Dtor
//--------------------------------------
RotoSparkContainer::RotoSparkContainer()
{
}
	
RotoSparkContainer::~RotoSparkContainer()
{
	RotoSparks.clear();				// clear the bullets
}


void RotoSparkContainer::Init( int Palette, glImage* const Sprites )
{
	ColorTable = Palette;		// init needed data for drawing
	Images = Sprites;
	RotoSparks.resize( MAX_ROTOSPARKS/2 );			// 1/2 of max (speed of iteration)
	RotoSparks.reserve( MAX_ROTOSPARKS );		// reserve max for speed.  No need to do this for enemies
}

//--------------------------------------
//	Virtual Functions
//--------------------------------------
void RotoSparkContainer::UpdateEntities()
{
	
	std::vector<RotoSpark>::iterator iter;
	for( iter = RotoSparks.begin(); iter != RotoSparks.end(); ++iter )
	{
		if( iter->Active )
			iter->Update();
	}
	
}

void RotoSparkContainer::DrawEntities()
{

	
	glColorTable( GL_RGB16, ColorTable );
	numEntities = 0;
	std::vector<RotoSpark>::iterator iter;
	for( iter = RotoSparks.begin(); iter != RotoSparks.end(); ++iter )
	{
		if( iter->Active )
		{
			numEntities++;
			glSpriteRotate( (iter->x >> 12), 
						    (iter->y >> 12), 
							iter->RotDir * iter->Counter*64, 
							GL_FLIP_NONE, &Images[iter->Frame] 
						  );
			/*  // view collision boxes
			s32 xa = cosLerp( iter->RotDir * iter->Counter*64 + BRAD_PI/2 );
			s32 ya = sinLerp( iter->RotDir * iter->Counter*64 + BRAD_PI/2 );
			for( int i = 0; i < 3; i++ )
            {
				int xlen = xa * ( i * 18 );
				int ylen = ya * ( i * 18 );
                int cx1 = (iter->x >> 12) + ( xlen >> 12 );
				int cy1 = (iter->y >> 12) + ( ylen >> 12 );
				int cx2 = (iter->x >> 12) - ( xlen >> 12 );
				int cy2 = (iter->y >> 12) - ( ylen >> 12 );
				
				glBoxFilled( cx1 - 1, cy1 - 1, cx1 + 1, cy1 + 1, RGB15(31,31,15) );
				glBoxFilled( cx2 - 1, cy2 - 1, cx2 + 1, cy2 + 1, RGB15(31,31,15) );
            }
			*/
		}
	}
	
}

bool RotoSparkContainer::Collide( StarFighter &Star )
{
	std::vector<RotoSpark>::iterator iter;
	for( iter = RotoSparks.begin(); iter != RotoSparks.end(); ++iter )
	{
		if( iter->Active )
		{
			int rad2 = 12 * 12;
			s32 xa = cosLerp( iter->RotDir * iter->Counter*64 + BRAD_PI/2 );
			s32 ya = sinLerp( iter->RotDir * iter->Counter*64 + BRAD_PI/2 );
			
			for( int i = 0; i < 3; i++ )
            {
				int xlen = xa * ( i * 18 );
				int ylen = ya * ( i * 18 );
                
				int cx1 = (iter->x >> 12) + ( xlen >> 12 );
				int cy1 = (iter->y >> 12) + ( ylen >> 12 );
				int cx2 = (iter->x >> 12) - ( xlen >> 12 );
				int cy2 = (iter->y >> 12) - ( ylen >> 12 );
				
				int cx = (cx1) - (Star.x >> 12);
				int cy = (cy1) - (Star.y >> 12);
				
				if( ( (cx * cx) + (cy * cy) ) < rad2 )
					return true;
				
				cx = (cx2) - (Star.x >> 12);
				cy = (cy2) - (Star.y >> 12);
				if( ( (cx * cx) + (cy * cy) ) < rad2 )
				{
					if(!Star.IsBursting())
					{
						//kill star
						if( !Star.IsInvincible() ) Star.Kill();
					}
					return true;
				}	
					
			}
			
		}
	}
	return false;
}



void RotoSparkContainer::KillAllEntities()
{
	std::vector<RotoSpark>::iterator iter;
	for( iter = RotoSparks.begin(); iter != RotoSparks.end(); ++iter )
	{
		if( iter->Active )
		{
			iter->Active = false;
			iter->x = 600 << 12;
			iter->y = 96 << 12;
		}
	}
	
}


//--------------------------------------
//	Non-Virtual Functions
//--------------------------------------
void RotoSparkContainer::Spawn( int _x, int _y, bool reverse )
{
	
	bool SlotFull = true;      		// value to check if all the slots are occupied
	
	std::vector<RotoSpark>::iterator iter;
	for( iter = RotoSparks.begin(); iter != RotoSparks.end(); ++iter )
	{
		if( !iter->Active )		// insert a bullet on a free slot
		{

			iter->x = _x << 12;
			iter->y = _y << 12;
			iter->Dx = -floattof32( 0.3 );
			iter->Dy = 0;
			iter->Active = true;
			iter->Frame = 0;
			iter->Counter = 0;
			if( reverse ) 
				iter->RotDir = -1;
			else
				iter->RotDir = 1;
			SlotFull = false;			// there's a free slot so we dont execute the code below
			break;
		
		}
	}
	
	// All the slots are full
	// Only push back a bullet if the slot is full and we have less than numbullets
	if( SlotFull && (RotoSparks.size() < MAX_ROTOSPARKS) )
	{
		RotoSpark spark;
		spark.x = _x << 12;
		spark.y = _y << 12;
		spark.Dx = floattof32( 0.3 );
		spark.Dy = 0;
		spark.Active = true;
		spark.Frame = 0;
		spark.Counter = 0;
		if( reverse ) 
			spark.RotDir = -1;
		else
			spark.RotDir = 1;
		
		RotoSparks.push_back(spark);
	}
	
}


