#include "tinyptc.h"
#include "math.h"


#define WIDTH 512
#define HEIGHT 384

#define SIZE (WIDTH*HEIGHT)
#define PIXEL(x, y, red, gre, blu, al, buffer) *(buffer+(y)*WIDTH+(x)) = ((al)<<24) | ((red)<<16) | ((gre) <<8) | (blu);

#define MAXPART 2000
static int ColorBCN[]={116,87,93,187,209,202,214,227,223,235,241,240 };
struct Particle2D {
		int X,Y;
		int R,B,G;
		int VIDA;
};
struct sParticles
{       struct Particle2D Particle[MAXPART];

};
struct sParticles ArrayParticle;
struct Particle2D GenParticle(void);


static int scr_buffer[SIZE];

void circlefill (int colorR, int colorG, int colorB, int rad, int x, int y, int Factor, int *scr_buffer);
int rand256 ();
void _clr (int *scr_buffer, long Bytes, int colorR, int colorG, int colorB,int Alpha);

int main()
{

	//long time = 0, frames = 0;
	long frames = 0;
	float time=0.0;
	int Vez;
	static long timeini = 0;

    for (Vez=0;Vez<MAXPART;Vez++) 
         ArrayParticle.Particle[Vez] = GenParticle();
	
	//if (ptc_open("Decathlon Code Compo",WIDTH,HEIGHT)) return 1;
	if (!ptc_open("Decathlon Code Compo",WIDTH,HEIGHT)) return 1;

	int angle = 0;
	int dist  = 0;
	while (1)
	{
		//timeini=time;
		for (Vez=0;Vez<(MAXPART/2);Vez++)
		{
			angle = ArrayParticle.Particle[Vez].X+ArrayParticle.Particle[Vez].Y;
			dist  = ArrayParticle.Particle[Vez].VIDA;
			

			if (time<10)
				circlefill (
					ArrayParticle.Particle[Vez].R,
					ArrayParticle.Particle[Vez].G,
					ArrayParticle.Particle[Vez].B,
					(int)((0.2+(ArrayParticle.Particle[Vez].VIDA/50.0))*7.0),
					WIDTH/2.0f+dist*cos (angle/100.0f),	//ArrayParticle.Particle[Vez].X,
					HEIGHT/2.0f+dist*sin (angle/100.0f),	//ArrayParticle.Particle[Vez].Y,
					13,
					scr_buffer);
			else
				circlefill (
					ArrayParticle.Particle[Vez].R,
					ArrayParticle.Particle[Vez].G,
					ArrayParticle.Particle[Vez].B,
					(int)((0.2+(ArrayParticle.Particle[Vez].VIDA/50.0))*7.0),
					WIDTH/2.0f+dist*cos ((float)angle/(float)time),	//ArrayParticle.Particle[Vez].X,
					HEIGHT/2.0f+dist*sin ((float)angle/(float)time),	//ArrayParticle.Particle[Vez].Y,
					13,
					scr_buffer);

			ArrayParticle.Particle[Vez].Y -= 30;
			ArrayParticle.Particle[Vez].X  = ArrayParticle.Particle[Vez].X-(rand256()%1);


			ArrayParticle.Particle[Vez].VIDA -= 10;
			
			// Aixo anava fora del for
			if (ArrayParticle.Particle[Vez].VIDA<10) 
				ArrayParticle.Particle[Vez] = GenParticle();
		}	
		
		ptc_update (scr_buffer);
		_clr (scr_buffer,WIDTH*HEIGHT,255,255,255,255);
		time+=1;
	}
	return 0;
}

void circlefill (int colorR, int colorG, int colorB, int rad, int x, int y, int Factor, int *scr_buffer)
{
        int contY, incX, CoX, FiCoX, CoY, FiCoY, rad2;

		CoY=y-rad;
		if (CoY<0) CoY=0;
		FiCoY=y+rad;
		if (FiCoY>HEIGHT) FiCoY=HEIGHT;

		rad2=rad+rad;
		for (contY=0;contY<rad;contY++)
        {
			incX=(int)(sqrt((rad2)-(contY*contY))*(float)(Factor/9.0));

			CoX=x-incX;
			if (CoX<0) CoX=0;
			FiCoX=x+incX;
			if (FiCoX>WIDTH) FiCoX=WIDTH;

			if ((y-contY>0)&&(y-contY<HEIGHT))
			{
				for(;CoX<FiCoX;CoX++)
				{
					PIXEL((CoX), (y-contY), (colorR), (colorG), (colorB),(255), (scr_buffer))
				}
				CoX=x-incX;
				if (CoX<0) CoX=0;
			}
			if ((y+contY>0)&&(y+contY<HEIGHT))
			{
				for(;CoX<FiCoX;CoX++)
				{
					PIXEL((CoX), (y+contY), (colorR), (colorG), (colorB),(255), (scr_buffer));
				}
			}
		}
}

int rand256 ()
{
	int carry;
	static int noise = 0x45345;
    static int seed = 0x12345;

	noise = seed;
    noise >>= 3;
    noise ^= seed;
    carry = noise & 1;
    noise >>= 1;
    seed >>= 1;
    seed |= (carry << 30);
    noise &= 0xFF;

//	noise *= seed;

	return (noise);
	//return (rand ()%256);
}

void _clr (int *scr_buffer, long Bytes, int colorR, int colorG, int colorB,int Alpha)
{
        int i;
        for (i=0;i<=(Bytes);i++) 
			*(scr_buffer+i) = (Alpha<<24) | (colorR<<16) | (colorG <<8) | colorB;
}

struct Particle2D GenParticle(void)
{
	   struct Particle2D Strella;
	   int randnum = rand256()%3;
	   //int randnum = rand ()%3;

       Strella.X = (rand256()*2);
	   Strella.Y = 384+rand256();
	   Strella.R = ColorBCN[randnum*3  ];
	   Strella.G = ColorBCN[randnum*3+1];
	   Strella.B = ColorBCN[randnum*3+2];
	   Strella.VIDA = Strella.Y-100;
       return Strella;
}