// Copyright 1994 Brad Pitzel
//
// Feel free to use/distribute/modify as long as credit/copyrights for myself 
// are included.

// To use explosions:  There is a predefined Boom class, to use it first
// make a Boom object:   
// 			Boom   boomObj;
// call boomObj.add( ... ) to start an explosion (you can have as many
// concurrent explosions as you want.
//
// call boomObj.tick() to make all the current explosions move one step
// call boomObj.draw() to draw the explosions on screen (with svgalib).
//
// The default explosion is a simpley a bunch of dots spreading outwards.
// You can define your own explosion class modelled (or even derived), from
// the SimpleExpl class, and then:
// BoomManager<MyExplosion> MyBoom;
//
// Then you use myBoomObj.add(..), tick(), draw(), just
// like the build-in Boom class.
//
// The requirements of your own explosion class:
// It must have a tick() function which moves the explosion one step.
// it must have a draw() function to draw the explosion wherever.
// It must have a isAlive() function that returns 1 if the explosion is
// still happening, or 0 if it has finished (and will be removed from the
// list of active explosions my the BoomManager)
// It must have a constructor:  MyExplosion(x,y,dots,dur,vx,vy)
// Where:
//	x = x co-ordinate where explosion starts (what it means depends on
//          your draw() function.
//      y = y co-ord of explosion start.
//	dots = size of explosion, your constructor can use or ignore it.
//	dur  = how long the explosion lasts in steps, your tick()
// 	       routine has to handle the life and death of the explosion
//	vx,vy = velocities of explosion in x,y directions. Used by tick()
//		By velocity I mean the movement of the center of the explosion
//		(eg, a stationary object will have a 0 velocity explosion
//		when it blows up)	

#ifndef __Explos__
#define __Explos__

#include <stdlib.h>
#include <math.h>
#include <vgagl.h>

#include "ObjTools.h"
#include "PtrList.h"
#include "FastMath.h"

// this class defines a single point in the SimpleExpl class.
class TrajPoint : public Trajectory
	{
	public:
	
	TrajPoint( unsigned char color=0, FixedPoint Fxp=0, FixedPoint Fyp=0 )
		: Vcolor(color), Trajectory(Fxp,Fyp) 
		{
		};

	unsigned char Vcolor;
	};

#define BMAX	200
//////////////////////////////////////////////////////////////////////////////
class SimpleExpl : public Life {
    public:
    	SimpleExpl( FixedPoint Fxp, FixedPoint Fyp, int size, int duration, 
    	           FixedPoint Fxvel=0, FixedPoint Fyvel=0);
    	           
	inline void draw() const
		{
		register int i;
		TrajPoint *p=Vbit;

		for(i=0;i<Vsize;i++) 
			{
			gl_setpixel( FP2INT(p->VFx), FP2INT(p->VFy), 
			             p->Vcolor );
			p++;
			}
		}

	inline void tick()
		{
		register int i;
		TrajPoint *p=Vbit;

		for(i=0;i<Vsize;i++) (p++)->moveNoWrap();

		Life::tick();
		}
	    
    protected:
	TrajPoint	Vbit[BMAX];
	int		Vsize;

    };


//////////////////////////////////////////////////////////////////////////////
// BoomManager manages explosions. The Explosion type is not fixed, but 
// passed in as the template parameter.

template <class EXPL>
class BoomManager
    {
    public:
    	
	 void add( FixedPoint Fxp, FixedPoint Fyp, 
	           int size, int duration, 
    	           FixedPoint Fxvel=0, FixedPoint Fyvel=0)
    	  {
    	  list.add(new EXPL( Fxp, Fyp, size, duration, Fxvel, Fyvel ));
    	  }
	
    	 void tick();
	 void draw();
	 void die() { list.removeAll(); }
		
    protected:

	// PtrList is a linked-list template class.
	// Here we are declaring a linked-list of EXPL's    
	PtrList<EXPL>	list;
    };

//typedef BoomManager<SimpleExpl>	Boom;

////////////////////////////////////////////////////////////////////////////

template <class EXPL>
void BoomManager<EXPL>::tick()
	{
    	EXPL* e;
    	list.gotoFirst();
    	while ( (e=list.current())!=NULL)
    		{
    		e->tick(); 
    		if (!e->isAlive()) list.remove();
    		else	list.gotoNext();
    		}
    	}

template <class EXPL>
void BoomManager<EXPL>::draw()
	{
    	EXPL* e;
    	list.gotoFirst();
    	while ( (e=list.current())!=NULL)
    		{
    		e->draw(); 
    		list.gotoNext();
    		}
    	}
    
#endif
