/*
メインボール(白の番号付けなし)が左右の壁に当たると
子ボールを一個ずつその場で産み落とすプログラム。
実行時に何個まで出現させるか入力を行い、入力された個数だけ子ボールを産み落とす。

画面内でマウスやキーボード操作を行うと、子ボールと対応数字を非表示にしたサブモードでの処理を行います。
子ボール同士の衝突が頻繁になってきた時に試してみてください。
*/

#include<stdio.h>
#include<eggx.h>
#include <math.h>

int main(){
	int win;
	int cnt,max,i,ii;//配置されているボールの個数、最大個数、第一ループ、第二ループ用変数
	
	max=300;
	cnt=1;
	
	//マウス入力関連、サブモード適応フラグ
	int type,oasobi,code;
	float x,y;
	oasobi=0;
	
	printf("Please input the maximum number of balls.[1~%d]:",max);
	scanf("%d",&max);
	if(max>300||max<=0){
		printf("An illegal numerical value was input.\n");
		return 0;
	}
	
	//各ボールの状態管理関連
	int balldx[max],balldy[max],ballflg[max];//x,y方向の移動量、画面内への配置済み判定用
	float ballx[max],bally[max],ballr[max];//x,y,r
	
	//衝突時の波紋もどき生成関連
	int circflg[max*2];//波紋もどきの生成の必要があるか
	float circx[max*2],circy[max*2],circr[max*2];//x,y,r
	
	//全ボール情報の初期化
	for(i=0;i<=max;i++){
		balldx[i]=10;
		balldy[i]=5;
		ballx[i]=20.0;
		bally[i]=20.0;
		ballr[i]=10.0;
		ballflg[i]=0;
		circflg[i]=0;
	}
	
	//波紋もどき情報の初期化
	for(i=0;i<=(max*2);i++){
		circflg[i]=0;
		circr[i]=0.0;
	}
	win=gopen(600,600);
	winname(win,"Ball Action");
	gsetnonblock(ENABLE);
	
	
	while(1){
		code=0;//キー入力情報を初期化
		if( ggetxpress( &type, &code, &x, &y) == win ) {
			if(code!=-1){//クリックやキー入力がされた場合はサブモード処理の適応フラグ変更
				if(!oasobi)oasobi=1;else oasobi=0;
				//printf("Check...type:%d, code:%d\n",type,code);
			}
		}
		
		gclr(win);
		newpen(win,1);
		ballx[0]+=balldx[0];
		bally[0]+=balldy[0];
		fillcirc(win,ballx[0],bally[0],ballr[0],ballr[0]);
		
		
		/*画面内に配置されている子ボールの処理*/
		for(i=1;i<cnt;i++)
		{
			if(!ballflg[i]){
				ballx[i]=ballx[0];
				bally[i]=bally[0];
				balldx[i]+=i%10+i;
				balldy[i]+=i%10+i;
				if(ballx[0]>390){
					balldx[i]*=-1;
				}
				ballflg[i]=1;
			}
			
			ballx[i]+=balldx[i];
			bally[i]+=balldy[i];
			
			/*他ボールとの衝突判定処理*/
			for(ii=0;ii<cnt;ii++)
			{
				if(i!=ii)
				{
					//三平方の定理を用いて対象との距離を比較
					int sx,sy;
					double length;
					
					sx=ballx[i]-ballx[ii];
					sy=bally[i]-bally[ii];
					length=sx*sx + sy*sy;
					length=sqrt(length);
					
					if(length < (ballr[ii] + ballr[i]))
					{
						if(!circflg[i]){
							circx[i]=ballx[i];
							circy[i]=bally[i];
							circflg[i]=1;
						}else if(!circflg[i+max]){
							circx[i+max]=ballx[i];
							circy[i+max]=bally[i];
							circflg[i+max]=1;
						}
						if(ii==0){//メインボール(ball0)に跳ね返り処理を行うと都合が悪いので子ボールだけ。
							balldy[i]*=-1;
							bally[i]+=balldy[i];
						}else{
							balldy[ii]*=-1;
							bally[ii]+=balldy[ii];
							balldy[i]*=-1;
							bally[i]+=balldy[i];
						}
					}
				}
			}
			/*衝突判定処理ここまで*/
			
			
			if(ballx[i]>590||ballx[i]<10)
			{
				if(ballx[i]>590){
					ballx[i]=580;
				}else{
					ballx[i]=20;
				}
				balldx[i]*=-1;
			}
			if(bally[i]>590||bally[i]<10)
			{
				if(bally[i]>590){
					bally[i]=580;
				}else{
					bally[i]=20;
				}
				balldy[i]*=-1;
			}
			
			
			newpen(win,i%15+1);
			
			/*波紋もどきの生成*/
			if(circflg[i]){
				circr[i]+=10.0;
				if(circr[i]>100){
					circflg[i]=0;
					circr[i]=0.0;
				}
				drawcirc(win, circx[i], circy[i], circr[i], circr[i]);
			}
			if(circflg[i+max]){
				circr[i+max]+=10.0;
				if(circr[i+max]>100){
					circflg[i+max]=0;
					circr[i+max]=0.0;
				}
				drawcirc(win, circx[i+max], circy[i+max], circr[i+max], circr[i+max]);
			}
			/*ここまで*/
			
			if(!oasobi)fillcirc(win,ballx[i],bally[i],ballr[i],ballr[i]);//子ボールの描画
			newpen(win,1);
			if(!oasobi)drawstr(win, ballx[i], bally[i], 30, 0.0, "%d",i+1);//子ボールに追従する識別番号の描画
			
		}
		/*子ボールの処理ここまで*/
		
		
		if(ballx[0]>590||ballx[0]<10)
		{
			circflg[0]=1;
			circx[0]=ballx[0];
			circy[0]=bally[0];
			if(ballx[0]>590){
				ballx[0]=580;
			}else{
				ballx[0]=20;
			}
			balldx[0]*=-1;
			if(cnt<max)cnt++;//左右の壁に当たったので子ボールの個数を一つ追加
		}
		if(bally[0]>590||bally[0]<10)
		{
			circflg[max]=1;
			circx[max]=ballx[0];
			circy[max]=bally[0];
			if(bally[0]>590){
				bally[0]=580;
			}else{
				bally[0]=20;
			}
			balldy[0]*=-1;
		}
		
		/*波紋もどきの生成*/
		if(circflg[0])
		{
			circr[0]+=10.0;
			if(circr[0]>100){
				circflg[0]=0;
				circr[0]=0.0;
			}
			drawcirc(win, circx[0], circy[0], circr[0], circr[0]);
		}
		if(circflg[max])
		{
			circr[max]+=10.0;
			if(circr[max]>100){
				circflg[max]=0;
				circr[max]=0.0;
			}
			drawcirc(win, circx[max], circy[max], circr[max], circr[max]);
		}
		/*ここまで*/
		
		if(cnt>=max){//画面内にある子ボールの個数が入力値以上の場合
			drawstr(win, 50.0, 50.0, 100, 0.0, "Ball full!\nPlease push Q key if you want to end. ");
			if(code==113)break;
		}else{
			drawstr(win, 250.0, 120.0, 16, 0.0, "Ball :%d (Max-%d)",cnt,max);
		}
		msleep(50);
	}
	/*
	gsetnonblock(DISABLE);
	drawstr(win, 250.0, 50.0, 100, 0.0, "Ball full!");
	ggetch();
	*/
	return 0;
}
