
//  must be loaded as soon as game starts;

  BITMAP BasicFire[10];
  BITMAP HFire;
  BITMAP Explosion[3];
  BITMAP Smoke[3];

 ////////////////////// advanced class operations
 ///////////////////////// derived class :> sprite_object

  class  csprite_object
      {
      private:
	int ButtonStatus;


      protected:

      public:
	int AimSpeed;
	int ClassInteger;
	int ClassInteger2;
	int FireType;

      typedef
      struct
	   {
	    int dx;
	    int dy;
	    int sdx;
	    int sdy;
	    int dxabs;
	    int dyabs;
	    int x,x1,x2;
	    int y,y1,y2;
	    int px;
	    int py;
	    int i;
	    int cursor;
	    int speed;
	   }Seek;
	  typedef
      struct
	   {
	    int x;
	    int y;
	    int state;
	    int speed;
	    int width;
	   }Aimer;
      // using the structure for a Homing Missle system
      Seek Homer;
      Aimer aim;


	 csprite sprite;
	 csprite fire;
	 csprite HomingFire;
	 csprite explode;
	 csprite smoulder;

      // fire speed information
	int FireSpeed;
	int SpriteSpeed;
	int ExplodeCount;
	int SmoulderCount;

     // pointer to the object;
     typedef csprite_object *csprite_object_ptr;



  ///////////////////  combined advanced functions
  void csprite_object::HomeCall 	(void);
  void csprite_object::Home		(csprite_object *Target);
  void csprite_object::initialize 	(int xx, int yy);
  int  csprite_object::MouseScanControl	(void);
  int  csprite_object::MouseFeelControl	(void);
  int  csprite_object::MouseScanControl2(void);
  int  csprite_object::MouseFeelControl2(void);
  int  csprite_object::OutOfBoundary 	(void);
  void csprite_object::InBoundary       (void);
  void csprite_object::KeyboardControl 	(void);
  void csprite_object::KeyboardControl2 (void);
  void csprite_object::VerticalVibration(int yy);
  void csprite_object::HorizontalVibration(int yy);
  void csprite_object::Fire             (void);
  void csprite_object::LFireCall        (void);
  void csprite_object::RFireCall        (void);
  void csprite_object::Explode          (void);
  void csprite_object::ExplodeCall      (void);
  void csprite_object::Aim	        (csprite_object *Target);
  void csprite_object::AimCall          (void);
  void csprite_object::Smoulder         (void);
  void csprite_object::SmoulderCall     (void);
       };


    void csprite_object::VerticalVibration(int yy)
    {
    if( (sprite.y <= yy) || (sprite.y > (Getmaxy-sprite.height-yy)))
    {
     ClassInteger*=(-1);
    }
    sprite.y += ClassInteger;
    }

    void csprite_object::HorizontalVibration(int yy)
    {
    if( (sprite.x <= yy) || (sprite.x > (Getmaxx-sprite.width-yy)))
    {
     ClassInteger2*=(-1);
    }
    sprite.x += ClassInteger2;
    }

    void csprite_object::InBoundary (void)

    {
	    if (/****/sprite.x < 0 )
		/****/sprite.x = 0;
	    else
	    if (/****/sprite.x > (Getmaxx - sprite.width))
		/****/sprite.x = (Getmaxx - sprite.width);

	   if (/****/sprite.y < 0 )
		/****/sprite.y = 0;
	    else
	    if (/****/sprite.y > (Getmaxy - sprite.height))
		/****/sprite.y = (Getmaxy - sprite.height);

     }




  void csprite_object:: KeyboardControl (void)

  {
	// cursor control
	if(key_up)	   {sprite.y -= SpriteSpeed;}
	else if (key_down) {sprite.y += SpriteSpeed;}

	if(key_left)       {sprite.x -= SpriteSpeed;}
	else if (key_right){sprite.x += SpriteSpeed;}


	//fire control
	if (key_Ctrl)
		{
	       ButtonStatus=2;
		}

  }

   int csprite_object::MouseScanControl(void)
     {
	 ScanMouse(&sprite.x,&sprite.y,&ButtonStatus);
	 sprite.x>>=1;
	 return(ButtonStatus);
     }

     #define sign(x) ((x<0)?-SpriteSpeed:((x>0)?SpriteSpeed:0))
   int csprite_object::MouseFeelControl (void)
     {
       int xx,yy,bb;

	 ScanMouse(&xx,&yy,&bb);
	 FeelMouse(&xx,&yy);

	   sprite.x+=sign(xx);
	   sprite.y+=sign(yy);

       return(bb);
     }


 /////  the following must have 3 sprite figures

  void csprite_object:: KeyboardControl2 (void)

  {
	// cursor control
	if(key_up)	   {sprite.y -= SpriteSpeed;
			    sprite.curr_frame=1;}
	else if (key_down) {sprite.y += SpriteSpeed;
			    sprite.curr_frame=2;}

	if(key_left)       {sprite.x -= SpriteSpeed;}
	else if (key_right){sprite.x += SpriteSpeed;}

  }

   int csprite_object::MouseScanControl2(void)
     {
     int y;

	 ScanMouse(&sprite.x,&sprite.y,&ButtonStatus);
	 sprite.x>>=1;
	 y=sprite.y;

	   if      (sprite.y < y) sprite.curr_frame=1;
	   else if (sprite.y > y) sprite.curr_frame=2;

	   return(ButtonStatus);
     }

     #define sign(x) ((x<0)?-SpriteSpeed:((x>0)?SpriteSpeed:0))
   int csprite_object::MouseFeelControl2 (void)
     {
       int xx,yy,bb,y;

	 ScanMouse(&xx,&yy,&bb);
	 FeelMouse(&xx,&yy);

	   sprite.x+= sign(xx);
		  y = sprite.y;
	   sprite.y+= sign(yy);

	   if      (sprite.y < y) sprite.curr_frame=1;
	   else if (sprite.y > y) sprite.curr_frame=2;

       return(bb);
     }



      void csprite_object::Home (csprite_object *Target)
      {
	if (/****/HomingFire.state == 0)
	      {
   /****/Homer.x1=   /****/sprite.x+/****/sprite.width;
   /****/Homer.y1=   /****/sprite.y+(/****/sprite.height>>1);
   /****/Homer.x2=   Target->sprite.x;
   /****/Homer.y2=   Target->sprite.y+(Target->sprite.height>>1);
   /****/HomingFire.state = SPRITE_ALIVE;
   /****/Homer.i=0;

  /****/Homer.dx=/****/Homer.x2-/****/Homer.x1;      /* the horizontal distance of the line */
  /****/Homer.dy=/****/Homer.y2-/****/Homer.y1;      /* the vertical distance of the line */
  /****/Homer.dxabs=abs(/****/Homer.dx);
  /****/Homer.dyabs=abs(/****/Homer.dy);
  /****/Homer.sdx=sgn(/****/Homer.dx);
  /****/Homer.sdy=sgn(/****/Homer.dy);
  /****/Homer.x=/****/Homer.dyabs>>1;
  /****/Homer.y=/****/Homer.dxabs>>1;
  /****/Homer.px=/****/Homer.x1;
  /****/Homer.py=/****/Homer.y1;

       }
     }

void csprite_object::HomeCall (void)
{
    if (/****/HomingFire.state == SPRITE_DEAD)
    {
//    /****/Homer.i=0;
    return;
    }

    sound(5000-(HomingFire.x<<5));
  ///****/Homer.i+=/****/Homer.speed;

  if (/****/Homer.dxabs>=/****/Homer.dyabs) /* the line is more horizontal than vertical */
  {
//    if ((/****/Homer.i>=/****/Homer.dxabs))
//     {
//     /****/HomingFire.state = SPRITE_DEAD;
//     return;
//     }
    for(/****/Homer.cursor=0;
    /****/Homer.cursor<=/****/Homer.speed;
    /****/Homer.cursor++)

    {
      /****/Homer.y+=/****/Homer.dyabs;
      if (/****/Homer.y>=/****/Homer.dxabs)
      {
	/****/Homer.y-=/****/Homer.dxabs;
	/****/Homer.py+=/****/Homer.sdy;
      }
      /****/Homer.px+=/****/Homer.sdx;
    }
  }
  else /* the line is more vertical than horizontal */
  {
//     if (/****/Homer.i>= /****/Homer.dyabs)
//     {
//     /****/HomingFire.state = SPRITE_DEAD;
//     return;
//     }
      for(/****/Homer.cursor=0;
      /****/Homer.cursor<=/****/Homer.speed;
      /****/Homer.cursor++)
	{
      /****/Homer.x+=/****/Homer.dxabs;
      if (/****/Homer.x>=/****/Homer.dyabs)
      {
	/****/Homer.x-= /****/Homer.dyabs;
	/****/Homer.px+=/****/Homer.sdx;
      }
      /****/Homer.py+=/****/Homer.sdy;
    }


  }

      /****/HomingFire.x = /****/Homer.px;
      /****/HomingFire.y = /****/Homer.py;
      /****/HomingFire.paste_db();

    if (HomingFire.OutOfScreen())
    {
    HomingFire.state=SPRITE_DEAD;
    }


}

   void csprite_object::initialize (int xx, int yy)
     {
     sprite.initialize(xx,yy);

     fire.initialize(0,0);
     fire.state     = SPRITE_DEAD;
     fire.frames[0]=  BasicFire[0].data;
     fire.width     = BasicFire[0].width;
     fire.height    = BasicFire[0].height;

     FireType=0;

     HomingFire.initialize(0,0);
     HomingFire.state     = SPRITE_DEAD;
     HomingFire.frames[0] = HFire.data;
     HomingFire.width     = HFire.width;
     HomingFire.height    = HFire.height;

     explode.initialize(0,0);
     explode.state     = SPRITE_DEAD;

     for (int i=0; i<=3 ;i++)
     explode.frames[i] = Explosion[i].data;

     explode.width     = Explosion[0].width;
     explode.height    = Explosion[0].height;
     ExplodeCount = 0;

     Homer.speed=1;
     FireSpeed  =5;
     SpriteSpeed=1;
     ClassInteger=SpriteSpeed;
     ClassInteger2=SpriteSpeed;

     aim.state = SPRITE_DEAD;
     AimSpeed  = 1;

     smoulder.initialize(0,0);
     smoulder.state     = SPRITE_DEAD;

     for (i=0; i<=3 ;i++)
     smoulder.frames[i] = Smoke[i].data;

     smoulder.width     = Smoke[0].width;
     smoulder.height    = Smoke[0].height;
     SmoulderCount = 0;
     }



      void csprite_object::Fire (void)
      {
	if (/****/fire.state == 0)
	      {
	 fire.x=sprite.x+ (sprite.width>>1);
	 fire.y=sprite.y+ (sprite.height>>1);

   /****/fire.state = SPRITE_ALIVE;
	       }
      }

void csprite_object::LFireCall (void)
{
    if (/****/fire.state == SPRITE_DEAD)
    {
    return;
    }
    fire.x-=FireSpeed;
    fire.paste_db();
    sound(fire.x<<5);

    if (fire.OutOfScreen())
    {
    fire.state=SPRITE_DEAD;
    }


}

void csprite_object::RFireCall (void)
{
    if (/****/fire.state == SPRITE_DEAD)
    {
    return;
    }
    fire.x+=FireSpeed;
    sound(fire.x<<5);
    fire.paste_db();

    if (fire.OutOfScreen())
    {
    fire.state=SPRITE_DEAD;
    }

}

void csprite_object::Explode (void)
      {
	if (/****/explode.state == 0)
	      {
	 explode.x=sprite.x+ (sprite.width>>1);
	 explode.y=sprite.y;

   /****/explode.state = SPRITE_ALIVE;
	       }
      }

void csprite_object::ExplodeCall (void)
{
    if (/****/explode.state == SPRITE_DEAD)
    {
    return;
    }

      sound(random(150));

	 if (ExplodeCount < 10)  { explode.curr_frame=0; }
    else if (ExplodeCount < 20) { explode.curr_frame=1; }
    else if (ExplodeCount < 30) { explode.curr_frame=2; }
    else
	{ ExplodeCount  = 0;
	  explode.state = SPRITE_DEAD;
	}


    explode.x-=2;
    explode.y+=1;

    sound(random(400));
    explode.paste_db();
    ExplodeCount++;

}
void csprite_object::Aim (csprite_object *target)
      {
	if (/****/aim.state == 0)
	      {
	 aim.x=target->sprite.x+ (target->sprite.width>>1);
	 aim.y=target->sprite.y+ (target->sprite.height>>1);
	 aim.width=target->sprite.width;
   /****/aim.state = SPRITE_ALIVE;
	   sound(2000);
	       }
      }



void csprite_object::AimCall (void)
{
   if (/****/aim.state == SPRITE_DEAD)
    {
    return;
    }

	if (aim.width < 1)
	{
	aim.state = SPRITE_DEAD;
	}

    square_db(aim.x,aim.y,aim.width,(220));
    aim.width-=AimSpeed;


   }


void csprite_object::Smoulder (void)
      {
	if (/****/smoulder.state == 0)
	      {
	 smoulder.x=sprite.x+ (sprite.width>>1);
	 smoulder.y=sprite.y;


   /****/smoulder.state = SPRITE_ALIVE;
	       }
      }

void csprite_object::SmoulderCall (void)
{
    if (/****/smoulder.state == SPRITE_DEAD)
    {
    return;
    }

	 if (SmoulderCount < 5)  { smoulder.curr_frame=0; }
    else if (SmoulderCount < 10) { smoulder.curr_frame=1; }
    else if (SmoulderCount < 15) { smoulder.curr_frame=2; }
    else
	{ SmoulderCount  = 0;
	  smoulder.state = SPRITE_DEAD;
	}


    smoulder.x-=3;


    sound(random(300));
    smoulder.paste_db();
    SmoulderCount++;
    sound(5000+random(5000));
}

