#pragma once
#include<Framework/Camera.h>
#include<Multimedia/Drawing.h>

namespace SDX
{
class Shape;
class Complex;
class Point;
class Line;
class Circle;
class Rect;

/** 位置情報を持つ図形の抽象クラス.*/
///	\include ShapeSample.h
class Shape
{
protected:
	double zoomX;
	double zoomY;
			
	/** 矩形の交差判定.*/
	static bool RectRect( double x1 , double y1 , double x2 , double y2 , double x3 , double y3 , double x4 , double y4)
	{
		//x座標をラフチェック
		if ( x1 >= x2)
		{
			if ((x1 < x3 && x1 < x4) || (x2 > x3 && x2 > x4))
			{
				return false;
			}
		}
		else
		{
			if ((x2 < x3 && x2 < x4) || (x1 > x3 && x1 > x4))
			{
				return false;
			}
		}
		//y座標をラフチェック
		if (y1 >= y2)
		{
			if ((y1 < y3 && y1 < y4) || (y2 > y3 && y2 > y4))
			{
				return false;
			}
		}
		else
		{
			if ((y2 < y3 && y2 < y4) || (y1 > y3 && y1 > y4))
			{
				return false;
			}
		}

		return true;
	}
	
	/** 線分の交差判定.*/
	static bool LineLine( double x1 , double y1 , double x2 , double y2 , double x3 , double y3 , double x4 , double y4)
	{
		//交差判定
		if ((double(x1 - x2) * (y3 - y1) + (y1 - y2) * (x1 - x3)) *
			(double(x1 - x2) * (y4 - y1) + (y1 - y2) * (x1 - x4)) > 0)
		{
			return false;
		}

		if ((double(x3 - x4) * (y1 - y3) + (y3 - y4) * (x3 - x1)) *
			(double(x3 - x4) * (y2 - y3) + (y3 - y4) * (x3 - x2)) > 0)
		{
			return false;
		}
		return true;

	}
			
	/** 二点間の距離を計算.*/
	static int PointPoint(double x1 , double y1 , double x2 , double y2)
	{
		return int((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
	}
			
public:
	Shape():
		zoomX(1),
		zoomY(1)
	{}
			
	/** 衝突判定.*/
	virtual bool Hit(const Shape *shape) const = 0;
	virtual bool Hit(const Complex *complex) const = 0;
	virtual bool Hit(const Point *point) const = 0;
	virtual bool Hit(const Line *line) const = 0;
	virtual bool Hit(const Rect *rect) const = 0;
	virtual bool Hit(const Circle *circle) const = 0;
	
	/** 指定座標に移動.*/
	virtual void SetPos(double X座標 , double Y座標) = 0;
			
	/** 同じ形の図形を作る.*/
	virtual Shape* Clone(double x , double y) const = 0;

	/** 拡大率を設定.*/
	void SetZoom(double X拡大率 , double Y拡大率)
	{
		MultiZoom( X拡大率 / zoomX , Y拡大率 / zoomY);
	}
			
	/** 拡大率を掛け算する.*/
	void MultiZoom(double 倍率)
	{
		MultiZoom(倍率,倍率);
	}
			
	/** 縦横別で拡大率を掛け算する.*/
	virtual void MultiZoom(double X倍率 , double Y倍率) = 0;
			
	/** 相対座標で移動.*/
	virtual void Move(double X移動量 , double Y移動量) = 0;
			
	/** 極座標で移動.*/
	void MoveA(double 距離 , double 方向 )
	{
		Move( 距離 * cos(方向) , 距離 * sin(方向) );
	}
			
	/** 描画する.*/
	virtual void Draw(Color rgb , int transRate , Camera *camera = 0) const = 0;
			
	/** 回転する.*/
	virtual void Rotate(double angle) = 0;
			
	/** 角度を指定する.*/
	virtual void SetAngle(double angle) = 0;

	/** 対象との角度を取得.*/
	double GetDirect(Shape* 比較対象)
	{
		return atan2(比較対象->GetY() - this->GetY(), 比較対象->GetX() - this->GetX());
	}

	/** 対象との相対座標を取得.*/
	double GetDistance(Shape* 比較対象)
	{
		const double xd = this->GetX() - 比較対象->GetX();
		const double yd = this->GetY() - 比較対象->GetY();

		return sqrt( xd * xd + yd * yd );
	}
			
	/** X座標を取得.*/
	virtual double GetX() const = 0;

	/** Y座標を取得.*/
	virtual double  GetY() const = 0;

	/** 幅を取得.*/
	virtual double  GetW() const = 0;

	/** 高さを取得.*/
	virtual double  GetH() const = 0;
};
	
/** 複合図形を表すクラス.*/
///	\include ShapeSample.h
class Complex : public Shape
{
public:
	std::vector<Shape*> shapes;

	Complex(){};

	Complex(Shape *shape)
	{
		shapes.push_back( shape );
	}
			
	Shape* Clone(double x,double y) const
	{
		Complex *buf = new Complex();

		for( auto it: shapes )
		{
			buf->shapes.push_back( it );
		}

		return buf;
	}
			
	void SetPos(double x , double y)
	{
		for( auto it: shapes )
		{
			it->SetPos( x , y );
		}		
	}

	void Move(double mX , double mY)
	{
		for( auto it: shapes )
		{
			it->Move( mX , mY );
		}
	}

	double GetX() const
	{
		return shapes[0]->GetX();
	}

	double GetY() const
	{
		return shapes[0]->GetY();
	}
			
	double GetW() const
	{
		return shapes[0]->GetW();
	}

	double GetH() const
	{
		return shapes[0]->GetH();
	}

	void MultiZoom(double rateX , double rateY)
	{
		for( auto it: shapes )
		{
			it->MultiZoom( rateX , rateY );
		}
		zoomX *= rateX;
		zoomY *= rateY;
	}

	void Rotate(double angle)
	{
		for( auto it: shapes )
		{
			it->Rotate( angle );
		}
	}

	void SetAngle(double angle)
	{
		for( auto it: shapes )
		{
			it->SetAngle( angle );
		}
	}

	void Draw( Color rgb , int transRate , Camera *camera = 0) const
	{
		for( auto it: shapes )
		{
			it->Draw( rgb , transRate , camera );
		}
	}
		
	bool Hit(const Shape *shape) const
	{
		return shape->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto itA : this->shapes )
		{
			for( auto itB : this->shapes )
			{
				if( itA->Hit(itB) ) return true;
			}
		}
		return false;
	}
	bool Hit(const Point *point) const;
	bool Hit(const Line *line) const;
	bool Hit(const Rect *rect) const;
	bool Hit(const Circle *circle) const;
};
	
/** 点を表す図形クラス.*/
///	\include ShapeSample.h
class Point : public Shape
{
public:
	double x;
	double y;

	Point() :
		x(0),
		y(0)
	{};
			
	Point(double x , double y):
		x(x),
		y(y)
	{}

	Shape* Clone(double x,double y) const
	{
		return new Point( x , y );
	}

	void SetPos(double x , double y)
	{
		this->x = x;
		this->y = y;			
	}

	void Move(double mX , double mY)
	{
		this->x += mX;
		this->y += mY;
	}

	double GetX() const
	{
		return x;
	}

	double GetY() const
	{
		return y;
	}
			
	double GetW() const
	{
		return 1;
	}

	double GetH() const
	{
		return 1;
	}
	
	void MultiZoom(double rateX , double rateY)
	{
		zoomX *= rateX;
		zoomY *= rateY;
	}

	void Rotate(double angle){}

	void SetAngle(double angle){}

	void Draw( Color rgb , int transRate , Camera *camera = 0) const
	{
		Screen::SetBlendMode(BlendMode::Alpha, transRate);
		if( camera )
		{
			Drawing::Pixel((int)camera->TransX(x), (int)camera->TransY(y), rgb);
		}
		else
		{
			Drawing::Pixel((int)x, (int)y, rgb);
		}
		Screen::SetBlendMode(BlendMode::NoBlend, transRate);
	}
			
	bool Hit(const Shape *shape) const
	{
		return shape->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->shapes )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return ( point->x == this->x && point->y == this->y );
	}
	bool Hit(const Line *line) const;
	bool Hit(const Rect *rect) const;
	bool Hit(const Circle *circle) const;
};
	
/** 太さのある線を表す図形クラス.*/
///	\include ShapeSample.h
class Line : public Shape
{
private:
	virtual void CulParam()
	{
		CulLine();
	}

	void CulLine()
	{
		this->xA = x + cos( angle ) * lengthA;
		this->yA = y + sin( angle ) * lengthA;
		this->xB = x - cos( angle ) * lengthB;
		this->yB = y - sin( angle ) * lengthB;
		this->width = int(abs(this->xB - this->xA));
		this->height =	int(abs(this->yB - this->yA));
		this->thickHarf = int(this->thick / 2);
		this->thickPow = int(this->thick * this->thick / 4);
		this->minX = int( this->xA < this->xB ? this->xA:this->xB );
		this->maxX = int( this->xA > this->xB ? this->xA:this->xB );
		this->minY = int( this->yA < this->yB ? this->yA:this->yB );
		this->maxY = int( this->yA > this->yB ? this->yA:this->yB );
	}

	double x;
	double y;
	double xA;
	double yA;
	double xB;
	double yB;
	double thick;//半径

	double angle;//角度

	double lengthA;
	double lengthB;

	double width;
	double height;
	double thickHarf;//半径の二条
	double thickPow;
	double minX;
	double minY;
	double maxX;
	double maxY;

public:

	Line( double x , double y , double angle , double length , double thick):
		x(x),
		y(y),
		angle(angle),
		lengthA( length/2 ),
		lengthB( length/2 ),
		thick( thick )
	{
		this->CulLine();
	}
			
	virtual Shape* Clone(double x,double y) const
	{
		return new Line( x , y , this->angle , this->lengthA , this->thick);
	}

	double GetX() const
	{
		return x;
	}

	double GetY() const
	{
		return y;
	}			
			
	double GetW() const
	{
		return int(xA - xB);
	}
			
	double GetH() const
	{
		return int(yA - yB);
	}

	void SetPos(double x , double y )
	{
		this->x = x;
		this->y = y;
		this->CulParam();
	}
	
	void MultiZoom(double rateX , double rateY)
	{
		this->lengthA *= rateX;
		this->lengthB *= rateY;
		this->thick *= rateX;

		this->CulParam();

		zoomX *= rateX;
		zoomY *= rateY;
	}

	void Rotate(double angle)
	{
		this->angle += angle;
		this->CulParam();	
	}

	void SetAngle(double angle)
	{
		this->angle = angle;
		this->CulParam();	
	}

	void Move(double mX , double mY )
	{
		this->x += mX;
		this->y += mY;
		this->xA += mX;
		this->yA += mY;
		this->xB += mX;
		this->yB += mY;
				
		this->minX += mX;
		this->minY += mY;
		this->maxX += mX;
		this->maxY += mY;
	}

	void Draw( Color rgb , int transRate , Camera *camera = 0 ) const
	{
		Screen::SetBlendMode(BlendMode::Alpha, transRate);
		if( camera )
		{
			Drawing::Line((int)camera->TransX(xA), (int)camera->TransY(yA), (int)camera->TransX(xB), (int)camera->TransY(yB), rgb, (int)(camera->GetZoom()));
			Drawing::Circle((int)camera->TransX(xA), (int)camera->TransX(yA), (int)(thickHarf*camera->GetZoom()), rgb, true);
			Drawing::Circle((int)camera->TransX(xB), (int)camera->TransX(yB), (int)(thickHarf*camera->GetZoom()), rgb, true);
		}
		else
		{
			Drawing::Line((int)xA, (int)yA, (int)xB, (int)yB, rgb, (int)thick);
			Drawing::Circle((int)xA, (int)yA, (int)thickHarf, rgb, true);
			Drawing::Circle((int)xB, (int)yB, (int)thickHarf, rgb, true);
		}
		Screen::SetBlendMode(BlendMode::NoBlend, transRate);
	}

	double GetXA() const
	{
		return xA;
	}

	double GetYA() const
	{
		return yA;
	}

	double GetXB() const
	{
		return xB;
	}

	double GetYB() const
	{
		return yB;
	}

	double GetThick() const
	{
		return thick;
	}

	void SetThick(double thick)
	{
		this->thick = thick;
		this->thickHarf = int(this->thick / 2);
		this->thickPow = int(this->thick * this->thick / 4);
	}

	double GetAngle() const
	{
		return this->angle;
	}

	void MoveAngle(double angle)
	{
		this->angle += angle;
		this->CulParam();
	}

	double GetLength() const
	{
		return this->lengthA + this->lengthB;
	}

	double GetThickHarf() const
	{
		return this->thickHarf;
	}

	double GetThickPow() const
	{
		return this->thickPow;
	}
			
	double GetMinX() const
	{
		return minX;
	}

	double GetMinY() const
	{
		return minY;
	}

	double GetMaxX() const
	{
		return maxX;
	}

	double GetMaxY() const
	{
		return maxY;
	}

	bool Hit(const Shape *shape) const
	{
		return shape->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->shapes )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return LinePoint( point->GetX() , point->GetY() , this->GetThickPow() );
	}
	bool Hit(const Line *line) const
	{
			//四角形でラフチェック
			if( RectRect(this->GetXA() - this->GetThickHarf() ,this->GetYA() - this->GetThickHarf() , this->GetXB() - line->GetThickHarf() , this->GetYB() - line->GetThickHarf() ,
							line->GetXA() - this->GetThickHarf() ,line->GetYA() - this->GetThickHarf() , line->GetXB() - line->GetThickHarf() , line->GetYB() - line->GetThickHarf() ) )
			{
				return true;
			}
			//交差チェック
			if( LineLine(this->GetXA() ,this->GetYA() ,this->GetXB() ,this->GetYB() ,line->GetXA(),line->GetYA(),line->GetXB(),line->GetYB() ) )
			{
				return true;
			}
			//線と端のチェック
			//線が点になっているかで分ける
			if( this->GetLength() != 0)
			{
				if( this->LinePoint( line->GetXA() , line->GetYA() , (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;
				if( this->LinePoint( line->GetXB() , line->GetYB() ,  (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;	
			}
			if( line->GetLength() != 0 )
			{
				if( line->LinePoint( this->GetXA() , this->GetYA() ,  (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;
				if( line->LinePoint( this->GetXB() , this->GetYB() ,  (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;	
			}

			return false;
	}
	bool Hit(const Rect *rect) const;
	bool Hit(const Circle *circle) const;
	
	/** 説明.*/
	bool LinePoint(double px , double py , double range ) const
	{
		const double dx = GetXB() - GetXA();
		const double dy = GetYB() - GetYA();

		const double a = dx * dx + dy * dy;
		const double b = dx *(GetXA() - px) + dy *(GetYA() - py);

		//点の場合
		if (a == 0)
		{
			if( 
				( GetXA() - px ) *( GetXA() - px ) +
				( GetYA() - py ) *( GetYA() - py )
				< range ) return true;
			return false;
		}

		const double t = -b / a;

		const double tx = GetXA() + dx*t;
		const double ty = GetYA() + dy*t;

		const double d = (px - tx)*(px - tx) + (py - ty) * (py - ty);

		return (d < range);
	}
};
	
/** 矩形を表す図形クラス.*/
///	\include ShapeSample.h
class Rect : public Shape
{
public:
	double x;
	double y;

	double upLength;
	double downLength;
	double leftLength;
	double rightLength;

	Rect(double x,double y,double width,double height):
		x(x),
		y(y),
		upLength( height/2 ),
		downLength( height/2 ),
		leftLength( width/2 ),
		rightLength( width/2 )
	{}

	virtual Shape* Clone(double x,double y) const
	{
		return new Rect( x , y , GetW() , GetH() );
	}
			
	void SetPos(double x , double y)
	{
		this->x = x;
		this->y = y;
	}

	void Move(double mX , double mY )
	{
		this->x += mX;
		this->y += mY;
	}

	void MultiZoom(double rateX , double rateY)
	{
		upLength *= rateY;
		downLength *= rateY;
		leftLength *= rateX;
		rightLength *= rateX;

		zoomX *= rateX;
		zoomY *= rateY;
	}

	void Rotate(double angle)
	{
	}

	void SetAngle(double angle)
	{
	}

	void Draw( Color rgb , int transRate , Camera *camera = nullptr) const
	{
		Screen::SetBlendMode(BlendMode::Alpha, transRate);
		if( camera )
		{
			Drawing::Rect
			(
				(int)camera->TransX(x - leftLength) ,
				(int)camera->TransY(y - upLength) ,
				(int)camera->TransX(x + rightLength) ,
				(int)camera->TransY(y + downLength) ,
				rgb ,
				true 
			);
		}
		else
		{
			Drawing::Rect
			( 
				(int)( x - leftLength ) ,
				(int)( y - upLength ) ,
				(int)( x + rightLength ) ,
				(int)( y + downLength) ,
				rgb ,
				true 
			);
		}
		Screen::SetBlendMode(BlendMode::NoBlend, transRate);
	}

	double GetX() const
	{
		return x;
	}

	double GetY() const
	{
		return y;
	}

	double GetW() const
	{
		return upLength + downLength;
	}

	double GetH() const
	{
		return leftLength + rightLength;
	}
			
	virtual double GetLeft() const
	{
		return int(x - leftLength);
	}

	virtual double GetTop() const
	{
		return int(y - upLength);
	}

	virtual double GetRight() const
	{
		return int(x + rightLength);
	}

	virtual double GetBottom() const
	{
		return int(y + downLength);
	}
			
	bool Hit(const Shape *shape) const
	{
		return shape->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->shapes )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return (
					(
						point->x < this->GetRight()
					) && (
						point->x > this->GetLeft()
					) && (			
						point->y < this->GetBottom()
					) && (
						point->y > this->GetTop()
					)		
			);
	}
	bool Hit(const Line *line) const
	{				
		if( ! RectRect
			(
				line->GetMinX() - line->GetThickHarf(),
				line->GetMinY() - line->GetThickHarf(),
				line->GetMaxX() + line->GetThickHarf(),
				line->GetMaxY() + line->GetThickHarf(),
				this->GetLeft(),
				this->GetTop(),
				this->GetRight(),
				this->GetBottom()
			)
			)
		{
			return false;
		}

		//√２/2≒0.7

		if( LineLine( line->GetXA() , line->GetYA() , line->GetXB() , line->GetYB()
					,  this->GetLeft() - int(line->GetThickHarf() * 0.7) , this->GetTop() - int(line->GetThickHarf() * 0.7) , this->GetRight() + int(line->GetThickHarf() * 0.7) , this->GetBottom() + int(line->GetThickHarf() * 0.7)  ))
		{
			return true;
		}

		if( LineLine( line->GetXA() , line->GetYA() , line->GetXB() , line->GetYB()
					, this->GetRight() + int(line->GetThickHarf() * 0.7)  , this->GetTop() - int(line->GetThickHarf() * 0.7) , this->GetLeft() - int(line->GetThickHarf() * 0.7) , this->GetBottom() + int(line->GetThickHarf() * 0.7) ))
		{
			return true;
		}

		//端の丸い所以外判定
		if( 
			line->GetXA() + line->GetThickHarf() > this->GetLeft() && line->GetXA() - line->GetThickHarf() < this->GetRight() &&
			line->GetYA() + line->GetThickHarf() > this->GetTop() && line->GetYA() - line->GetThickHarf() < this->GetBottom() 
			)
		{
				//端の丸い所判定
				if(		  line->GetXA() < this->GetLeft()				&& line->GetYA() < this->GetTop() )
				{//左上
					
					if( (line->GetXA() - this->GetLeft()) * (line->GetXA() - this->GetLeft()) +
						(line->GetYA() - this->GetTop()) * (line->GetYA() - this->GetTop()) < line->GetThickPow() ) return true;
					
				}
				else if( line->GetXA() > this->GetRight() && line->GetYA() < this->GetTop() )
				{//右上
					
					if( (line->GetXA() - this->GetRight()) * (line->GetXA() - this->GetRight()) +
						(line->GetYA() - this->GetTop()) * (line->GetYA() - this->GetTop()) < line->GetThickPow() ) return true;

				}
				else if( line->GetXA() < this->GetLeft()				&& line->GetYA() > this->GetBottom() )
				{//左下
					
					if( (line->GetXA() - this->GetLeft()) * (line->GetXA() - this->GetLeft()) +
						(line->GetYA() - this->GetBottom()) * (line->GetYA() - this->GetBottom()) < line->GetThickPow() ) return true;
					
				}
				else if( line->GetXA() > this->GetRight() && line->GetYA() > this->GetBottom() )
				{//右下

					if( (line->GetXA() - this->GetRight()) * (line->GetXA() - this->GetRight()) +
						(line->GetYA() - this->GetBottom()) * (line->GetYA() - this->GetBottom()) < line->GetThickPow() ) return true;
					
				}
				else
				{	
					return true;
				}
		}

		if( 
			line->GetXB() + line->GetThickHarf()  > this->GetLeft() && line->GetXB() - line->GetThickHarf() < this->GetRight() &&
			line->GetYB() + line->GetThickHarf()  > this->GetTop() && line->GetYB() - line->GetThickHarf() < this->GetBottom()
			)
		{
			//端の丸い所判定
			if(		  line->GetXB() < this->GetLeft()				&& line->GetYB() < this->GetTop() )
			{//左上
				if( (line->GetXB() - this->GetLeft()) * (line->GetXB() - this->GetLeft()) +
					(line->GetYB() - this->GetTop()) * (line->GetYB() - this->GetTop()) < line->GetThickPow() ) return true;
					
			}
			else if( line->GetXB() > this->GetRight() && line->GetYB() < this->GetTop() )
			{//右上
					
				if( (line->GetXB() - this->GetRight()) * (line->GetXB() - this->GetRight()) +
					(line->GetYB() - this->GetTop()) * (line->GetYB() - this->GetTop()) < line->GetThickPow() ) return true;

			}
			else if( line->GetXB() < this->GetLeft()				&& line->GetYB() > this->GetBottom() )
			{//左下
					
				if( (line->GetXB() - this->GetLeft()) * (line->GetXB() - this->GetLeft()) +
					(line->GetYB() - this->GetBottom()) * (line->GetYB() - this->GetBottom()) < line->GetThickPow() ) return true;
					
			}
			else if( line->GetXB() > this->GetRight() && line->GetYB() > this->GetBottom() )
			{//右下
				if( (line->GetXB() - this->GetRight()) * (line->GetXB() - this->GetRight()) +
					(line->GetYB() - this->GetBottom()) * (line->GetYB() - this->GetBottom()) < line->GetThickPow() ) return true;
					
			}
			else
			{	
				return true;			
			}
		}

		return false;
	}
	bool Hit(const Rect *rect) const
	{
		return RectRect
			(
				this->GetLeft() , this->GetTop() , this->GetRight() , this->GetBottom() ,
				rect->GetLeft() , rect->GetTop() , rect->GetRight() , rect->GetBottom() 
			);
	}
	bool Hit(const Circle *circle) const;
};
	
/** 円を表す図形クラス.*/
///	\include ShapeSample.h
class Circle : public Shape
{
public:
	double x;
	double y;
	double radius;

	Circle(	double x , double y , double radius):
		x(x),
		y(y),
		radius(radius)
	{}

	Shape* Clone(double x,double y) const
	{
		return new Circle( x , y , this->radius );
	}

	void SetPos(double x , double y )
	{
		this->x = x;
		this->y = y;
	}

	void MultiZoom(double rateX , double rateY)
	{
		this->radius *= rateX;

		zoomX *= rateX;
		zoomY *= rateY;
	}

	void Rotate(double angle){}

	void SetAngle(double angle){}

	void Move(double mX , double mY )
	{
		this->x += mX;
		this->y += mY;
	}

	double GetX() const
	{
		return int(x);
	}

	double GetY() const
	{
		return int(y);
	}
			
	double GetW() const
	{
		return int(radius*2);
	}

	double GetH() const
	{
		return int(radius*2);
	}

	void Draw( Color rgb , int transRate , Camera *camera = 0) const
	{
		Screen::SetBlendMode(BlendMode::Alpha, transRate);
		if( camera )
		{
			Drawing::Circle( (int)camera->TransX(x) , (int)camera->TransY(y) , (int)(radius * camera->GetZoom()) , rgb , true );
		}
		else
		{
			Drawing::Circle( (int)x , (int)y , (int)radius , rgb , true );
		}
		Screen::SetBlendMode(BlendMode::NoBlend, transRate);

	}
			
	bool Hit(const Shape *shape) const
	{
		return shape->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->shapes )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return
		(
			( point->x - this->x ) * ( point->x - this->x )  +
			( point->y - this->y ) * ( point->y - this->y )
			<=
			( this->radius * this->radius )
		);
	}
	bool Hit(const Line *line) const
	{
		return line->LinePoint( x , y , (line->GetThickHarf() + radius) * (line->GetThickHarf() + radius) );
	}
	bool Hit(const Circle *circle) const
	{
		return(
				(this->x - circle->x) * (this->x - circle->x) +
				(this->y - circle->y) * (this->y - circle->y) 			
				<=
				(this->radius + circle->radius) * (this->radius + circle->radius)
			);
	}
	bool Hit(const Rect *rect) const
	{
		return 
		(				
			(
				(
					(
						this->x + this->radius >= rect->GetLeft()						
					)&&(
						this->x - this->radius <= rect->GetRight()
					)
				)&&(
					(
						this->y >= rect->GetTop()
					)&&(
						this->y <= rect->GetBottom()
					)
				)
			) || (
				(
					(
						this->x >= rect->GetLeft()
					)&&(
						this->x <= rect->GetRight()
					)									
				)&&(
					(
						this->y + this->radius >= rect->GetTop()
					)&&(
						this->y - this->radius <= rect->GetBottom()
					)
				)
			) || (//四角形の四隅と円の判定
				(this->x - rect->GetLeft() ) * (this->x - rect->GetLeft() ) +
				(this->y - rect->GetTop() ) * (this->y - rect->GetTop() ) <=
				(this->radius * this->radius )
			) || (
				(this->x - rect->GetRight()) * (this->x - rect->GetRight()) +
				(this->y - rect->GetTop() ) * (this->y - rect->GetTop() ) <=
				(this->radius * this->radius )
			) || (
				(this->x - rect->GetLeft()) * (this->x - rect->GetLeft()) +
				(this->y - rect->GetBottom()) * (this->y -rect->GetBottom()) <=
				(this->radius * this->radius )
			) || (
				(this->x - rect->GetRight()) * (this->x - rect->GetRight()) +
				(this->y - rect->GetBottom()) * (this->y - rect->GetBottom()) <=
				(this->radius * this->radius )
			)
		);
	}
};
}
