//
//	Tiny2D.h
//
//	簡易物理エンジン
//
//	* Sun Apr 30 22:20:58 JST 2017 Naoyuki Sawa
//	- 1st リリース。
//	  □参考資料:「［書籍連動］「ゲームで学ぶJavaScript入門」物理エンジンの詳細解説」(https://thinkit.co.jp/series/4770)
//	  上記の記事の「Tiny2D.js」(https://thinkit.co.jp/sites/default/files/file_attachement/8467_Physics.zip)を参考にして、かなり変更して作成しました。
//	- 特に大きな変更点は、物理エンジンのインスタンスを廃止した事です。
//	  オリジナル版のTiny2D.jsでは、重力加速度とエンティティリストを保持する、物理エンジンクラスが定義されていました。
//	  周期処理の関数step()は、物理エンジンクラスのメソッドでした。
//	  同じように実装しても構わなかったのですが、アプリケーションがエンティティリストを保持する方が自由度が高くなると思い、構造を変更する事にしました。
//	  当実装では、物理エンジンクラスは存在せず、エンティティリストと重力加速度は、周期処理の関数step()の引数としました。
//	* Mon May 01 22:50:38 JST 2017 Naoyuki Sawa
//	- 「線分付近の円が他の円との衝突で座標補正された時に線分をすり抜ける問題」を低減しました。
//	  詳細は、Tiny2D.cのTINY2D_AVOID_LINE_THROUGHシンボルの定義箇所、及び、Tiny2D_CircleEntity_collWithCircle()の実装を参照して下さい。
//
#ifndef __TINY2D_H__
#define __TINY2D_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
//*****************************************************************************
//	定数、マクロ、構造体
//*****************************************************************************
//Tiny2D_Entity.shape
#define Tiny2D_ShapeCircle	1	//円
#define Tiny2D_ShapeRect	2	//矩形
#define Tiny2D_ShapeLine	3	//線分
//-----------------------------------------------------------------------------
typedef struct _Tiny2D_Vec		Tiny2D_Vec;
typedef struct _Tiny2D_CircleEntity	Tiny2D_CircleEntity;
typedef struct _Tiny2D_RectEntity	Tiny2D_RectEntity;
typedef struct _Tiny2D_LineEntity	Tiny2D_LineEntity;
typedef union  _Tiny2D_Entity		Tiny2D_Entity;
//*****************************************************************************
//	ベクトル
//*****************************************************************************
/*typedef*/ struct _Tiny2D_Vec {
	double	x, y;
} /*Tiny2D_Vec*/;
//-----------------------------------------------------------------------------
Tiny2D_Vec Tiny2D_Vec_new(double x, double y);
Tiny2D_Vec Tiny2D_Vec_add(Tiny2D_Vec v1, Tiny2D_Vec v2);
Tiny2D_Vec Tiny2D_Vec_sub(Tiny2D_Vec v1, Tiny2D_Vec v2);
Tiny2D_Vec Tiny2D_Vec_mul(Tiny2D_Vec v, double d);
Tiny2D_Vec Tiny2D_Vec_div(Tiny2D_Vec v, double d);
double Tiny2D_Vec_dot(Tiny2D_Vec v1, Tiny2D_Vec v2);
double Tiny2D_Vec_cross(Tiny2D_Vec v1, Tiny2D_Vec v2);
double Tiny2D_Vec_dist2(Tiny2D_Vec v1, Tiny2D_Vec v2);
double Tiny2D_Vec_dist(Tiny2D_Vec v1, Tiny2D_Vec v2);
double Tiny2D_Vec_length2(Tiny2D_Vec v);
double Tiny2D_Vec_length(Tiny2D_Vec v);
Tiny2D_Vec Tiny2D_Vec_normal(Tiny2D_Vec v);
Tiny2D_Vec Tiny2D_Vec_reflect(Tiny2D_Vec n, Tiny2D_Vec v);
//*****************************************************************************
//	円エンティティ
//*****************************************************************************
/*typedef*/ struct _Tiny2D_CircleEntity {
	int		shape;		//形状
	Tiny2D_Vec	p;		//中心座標
	double		radius;		//半径
	double		restitution;	//反発係数	0.0〜1.0の範囲で設定して下さい。
	double		deceleration;	//減速度合	0.0〜1.0の範囲で設定して下さい。0.0ならば固定円、0.0以外ならば動く円と見なします。
	Tiny2D_Vec	accel;		//加速度ベクトル
	Tiny2D_Vec	velocity;	//速度ベクトル
	void		(*onhit)(Tiny2D_CircleEntity* This, Tiny2D_Entity* Peer);	//衝突時のコールバック	【NOTE】衝突時のコールバックの中で、This,及び,Peerを変更や削除してはいけません。フラグ等で記憶しておいて、Tiny2D_Engine_step()が処理を返した後に変更や削除を行って下さい。
} /*Tiny2D_CircleEntity*/;
//-----------------------------------------------------------------------------
Tiny2D_CircleEntity* Tiny2D_CircleEntity_new(double x, double y, double radius, double restitution, double deceleration);
void Tiny2D_CircleEntity_init(Tiny2D_CircleEntity* This, double x, double y, double radius, double restitution, double deceleration);
//*****************************************************************************
//	矩形エンティティ
//*****************************************************************************
/*typedef*/ struct _Tiny2D_RectEntity {
	int		shape;		//形状
	Tiny2D_Vec	vmin;		//左上座標
	Tiny2D_Vec	vmax;		//右下座標
	double		restitution;	//反発係数
} /*Tiny2D_RectEntity*/;
//-----------------------------------------------------------------------------
Tiny2D_RectEntity* Tiny2D_RectEntity_new(double x, double y, double w, double h, double restitution);
void Tiny2D_RectEntity_init(Tiny2D_RectEntity* This, double x, double y, double w, double h, double restitution);
//*****************************************************************************
//	線分エンティティ
//*****************************************************************************
//【NOTE】衝突判定は、太さの無い線分と、円の中心に対して行います。線分自体は円にめり込みます。オリジナル版と同じ仕様です。
//【NOTE】線分付近の円が他の円との衝突で座標補正されると、線分をすり抜ける事が有ります。オリジナル版でも発生する問題です。	⇒{{2017/05/01コメント追記:「線分付近の円が他の円との衝突で座標補正された時に線分をすり抜ける問題」を低減しました。}}
/*typedef*/ struct _Tiny2D_LineEntity {
	int		shape;		//形状
	Tiny2D_Vec	s;		//始点座標
	Tiny2D_Vec	v;		//始点から終点へのベクトル
	double		restitution;	//反発係数
} /*Tiny2D_LineEntity*/;
//-----------------------------------------------------------------------------
Tiny2D_LineEntity* Tiny2D_LineEntity_new(double x1, double y1, double x2, double y2, double restitution);
void Tiny2D_LineEntity_init(Tiny2D_LineEntity* This, double x1, double y1, double x2, double y2, double restitution);
//*****************************************************************************
//	エンティティの共用体
//*****************************************************************************
/*typedef*/ union _Tiny2D_Entity {
	int			shape;	//形状
	Tiny2D_RectEntity	rect;	//矩形
	Tiny2D_LineEntity	line;	//線分
	Tiny2D_CircleEntity	circle;	//円
} /*Tiny2D_Entity*/;
//*****************************************************************************
//	物理エンジン
//*****************************************************************************
void Tiny2D_Engine_step(GSList* entities, double elapsed, double gravityX, double gravityY);
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__TINY2D_H__
