#東方弾幕風[Single]
#ScriptVersion[3]
#Title["SampleE02"]
#Text["SampleE02：ボス周囲のゆらぎエフェクト"]
#Background["script/default_system/Default_Background_IceMountain.txt"]

//デフォルト弾画像をロード
#include"script/default_system/Default_ShotConst.txt"

//----------------------------------------------------
//グローバル変数宣言
//この位置で宣言した変数はスクリプト全体で有効です。
//ただしこの箇所での変数への代入は、定数以外の代入は行えません。
//(実行順序が保障されないため乱数などの使用はできません)
//----------------------------------------------------
let objEnemy; //敵オブジェクト
let objPlayer; //自機オブジェクト
let frame = 0; //敵動作に使用するカウンタ(@MainLoopで1づつ増加させます)

//----------------------------------------------------
//敵の動作
//----------------------------------------------------
@Event
{
	alternative(GetEventType())
	case(EV_REQUEST_LIFE)
	{
		//敵ライフを要求された
		SetScriptResult(500);//ライフを500に設定
	}
}

@Initialize
{
	//自機オブジェクト取得
	objPlayer = GetPlayerObjectID();

	//敵オブジェクトを生成し登録
	objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
	ObjEnemy_Regist(objEnemy);

	//敵画像の設定
	let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; //敵画像ファイル
	ObjPrim_SetTexture(objEnemy, imgExRumia); //画像ファイルを読み込む
	ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); //描画元矩形を(64,1) - (127,64)に設定
	ObjSprite2D_SetDestCenter(objEnemy); //描画先を中心(0, 0)に設定

	//座標(cx, 120)へ60フレームかけて移動する
	let cx = GetStgFrameWidth() / 2;//STGシーンの中心x座標を取得
	ObjMove_SetDestAtFrame(objEnemy, cx, 120, 60);

	//let objScene = GetEnemyBossSceneObjectID();
	//ObjEnemyBossScene_StartSpell(objScene);

	TWaveCircle();
}

@MainLoop
{
	//敵の座標を取得
	let ex = ObjMove_GetX(objEnemy);
	let ey = ObjMove_GetY(objEnemy);

	if(frame == 90)
	{
		let px = GetPlayerX();
		ObjMove_SetDestAtFrame(objEnemy, rand(192-100, 192+100), rand(50, 200), 60);
	}

	if(frame == 180)
	{
		//frameが180になったら実行される部分
		//自機の座標を取得
		let px = GetPlayerX();
		let py = GetPlayerY();

		//敵からみた自機方向の角度を求める。
		let angleToPlayer = atan2(py - ey, px - ex);

		//angleを-30から15ずつ増加させ5WAYにする
		let angle=0;
		while(angle<360)
		{//(angle：15°間隔で0〜360まで)
			//一定時間で自機方向へ角度を変える弾
			//弾を作成する。
			let obj = CreateShotA2(ex, ey, 5, angle, -0.10, 1, DS_RICE_S_BLUE, 30);
			//発射後60フレーム目に、自機方向を基準に角度変更するように設定
			ObjMove_AddPatternA4(obj, 60, 3, 0, 0, 0, 3, objPlayer, NO_CHANGE);
			angle += 15;
		}

		frame = 0;//弾を出したらframeを0にする
	}

	//当たり判定登録
	ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32);//当たり判定(自機弾用)登録
	ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24);//当たり判定(体当たり用)登録

	//カウンタに1追加
	frame++;

	//ライフ0処理
	if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
	{
		//ライフが0になったら即座に終了
		//本来は爆発エフェクトのタスクを登録し、
		//エフェクト終了を待って、スクリプトを終了します。
		yield;
		Obj_Delete(objEnemy);
		CloseScript(GetOwnScriptID());
		return;
	}

	yield;
}


//----------------------------------------------------
//ボス周囲のゆらぎエフェクト
//----------------------------------------------------
task TWaveCircle()
{
	//レンダリングターゲットに使用するテクスチャ
	let renderTexture = GetReservedRenderTargetName(0);

	let frame = 0; //フレーム
	let baseEffectRadius = 144; //基準エフェクト半径
	let outerFluct = 16; //エフェクト半径の最大変化量
	let effectRadius = 0; //エフェクト半径
	let circleVertexCount = 16; //円をあらわすのに使用する頂点の数
	let innerCircleCount = 4;

	let priEffectMin = 20; //エフェクトをかける最小優先度
	let priEffectMax = 28; //エフェクトをかける最大優先度

	//背景のみエフェクトの対象とする
	//エフェクトの描画でまかなえるため、
	//優先度20〜28の通常描画を無効にする。
	SetInvalidRenderPriorityA1(priEffectMin, priEffectMax);


	let frameWidth = GetStgFrameWidth();
	let frameHeight = GetStgFrameHeight();
	let frameLeft = GetStgFrameLeft();
	let frameRight = frameLeft + frameWidth;
	let frameTop = GetStgFrameTop();
	let frameBottom = frameTop + frameHeight;

	//--------------------------------
	//円形の影
	let path = GetCurrentScriptDirectory() ~ "Effect02.png";
	let objShadow = ObjPrim_Create(OBJ_SPRITE_2D); //2Dスプライトオブジェクト生成
	Obj_SetRenderPriorityI(objShadow, 25); //描画優先度を設定
	ObjPrim_SetTexture(objShadow, path); //テクスチャを設定
	ObjRender_SetBlendType(objShadow, BLEND_MULTIPLY);
	ObjSprite2D_SetSourceRect(objShadow, 1, 1, 255, 255); //描画元設定(44, 54)-(71,105)
	ObjSprite2D_SetDestCenter(objShadow);
	ObjRender_SetScaleXYZ(objShadow, 1.2, 1.2, 0);


	//--------------------------------
	//円内
	let objInnerC = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	Obj_SetRenderPriorityI(objInnerC, priEffectMax + 1);
	ObjPrim_SetTexture(objInnerC, renderTexture);
	ObjPrim_SetVertexCount(objInnerC, 6 * circleVertexCount * innerCircleCount);

	//円外〜エフェクト枠
	let objOuterC = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	Obj_SetRenderPriorityI(objOuterC, priEffectMax + 1);
	ObjPrim_SetTexture(objOuterC, renderTexture); //テクスチャを設定
	ObjPrim_SetVertexCount(objOuterC, 3 * circleVertexCount);

	//エフェクト枠外オブジェクト
	let objOuterE = ObjPrim_Create(OBJ_SPRITE_LIST_2D);
	Obj_SetRenderPriorityI(objOuterE, priEffectMax + 1);
	ObjPrim_SetTexture(objOuterE, renderTexture); //テクスチャを設定


	//ボスのライフが0になるまでエフェクトをかける。
	let objEnemy = GetEnemyBossObjectID[0];
	while(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0)
	{
		//エフェクト半径
		effectRadius = baseEffectRadius + outerFluct * sin(frame*4);

		let enemyX = ObjMove_GetX(objEnemy); //敵座標X
		let enemyY = ObjMove_GetY(objEnemy); //敵座標Y
		let circleLeft = enemyX - effectRadius + frameLeft; //エフェクト円の左端
		let circleRight = enemyX + effectRadius + frameLeft; //エフェクト円の右端
		let circleTop = enemyY - effectRadius + frameTop; //エフェクト円の上端
		let circleBottom = enemyY + effectRadius + frameTop; //エフェクト円の下端

		//--------------------------------
		//優先度20〜28(背景)をエフェクト用のテクスチャに描画
		RenderToTextureA1(renderTexture, priEffectMin, priEffectMax, true);

		//--------------------------------
		//影
		ObjRender_SetPosition(objShadow, enemyX, enemyY, 0);

		//--------------------------------
		//円内
		//エフェクト内円を描画
		//ゆらいでいる部分
		ObjRender_SetPosition(objInnerC, -frameLeft, -frameTop, 0);
		ascent(let iPosI in 0 .. circleVertexCount) 
		{
			let xyOldRadius = 0;
			ascent(let iCircle in 0 .. innerCircleCount) 
			{
				let vertexIndex = (iPosI * innerCircleCount + iCircle) * 6;
				let angle1 =  iPosI * (360 / circleVertexCount);
				let angle2 =  (iPosI + 1) * (360 / circleVertexCount);

				//テクスチャのUV座標
				let uvRadius1 = iCircle * effectRadius / innerCircleCount;
				let uvRadius2 = (iCircle + 1) * effectRadius / innerCircleCount;

				//テクスチャのUV座標と描画先のXY座標を変化させることでゆらぎを表現する
				let xyRadius1t = iCircle * effectRadius / innerCircleCount;
				let xyRadius2t = (iCircle + 1) * effectRadius / innerCircleCount;
				let xyRadius1 = xyOldRadius;
				let xyBias = (xyRadius2t - xyRadius1t) / 2 + (xyRadius2t - xyRadius1t) * sin(frame*16 + (iCircle * 360 / innerCircleCount)) / 4;
				let xyRadius2 = xyRadius2t + xyBias / ((innerCircleCount - iCircle + 1) / 2);

				xyOldRadius = xyRadius2;
				if(iCircle == innerCircleCount - 1)
				{
					xyRadius2 = uvRadius2;
				}

				//上記の頂点座標を設定
				let leftBias = enemyX + frameLeft;
				let topBias = enemyY + frameTop;
				ObjPrim_SetVertexPosition(objInnerC, vertexIndex  , leftBias + xyRadius1 * cos(angle1), topBias + xyRadius1 * sin(angle1), 0);
				ObjPrim_SetVertexPosition(objInnerC, vertexIndex+1, leftBias + xyRadius2 * cos(angle1), topBias + xyRadius2 * sin(angle1), 0);
				ObjPrim_SetVertexPosition(objInnerC, vertexIndex+2, leftBias + xyRadius1 * cos(angle2), topBias + xyRadius1 * sin(angle2), 0);
			
				ObjPrim_SetVertexPosition(objInnerC, vertexIndex+3, leftBias + xyRadius1 * cos(angle2), topBias + xyRadius1 * sin(angle2), 0);
				ObjPrim_SetVertexPosition(objInnerC, vertexIndex+4, leftBias + xyRadius2 * cos(angle1), topBias + xyRadius2 * sin(angle1), 0);
				ObjPrim_SetVertexPosition(objInnerC, vertexIndex+5, leftBias + xyRadius2 * cos(angle2), topBias + xyRadius2 * sin(angle2), 0);

				ObjPrim_SetVertexUVT(objInnerC, vertexIndex  , leftBias + uvRadius1 * cos(angle1), topBias + uvRadius1 * sin(angle1));
				ObjPrim_SetVertexUVT(objInnerC, vertexIndex+1, leftBias + uvRadius2 * cos(angle1), topBias + uvRadius2 * sin(angle1));
				ObjPrim_SetVertexUVT(objInnerC, vertexIndex+2, leftBias + uvRadius1 * cos(angle2), topBias + uvRadius1 * sin(angle2));
			
				ObjPrim_SetVertexUVT(objInnerC, vertexIndex+3, leftBias + uvRadius1 * cos(angle2), topBias + uvRadius1 * sin(angle2));
				ObjPrim_SetVertexUVT(objInnerC, vertexIndex+4, leftBias + uvRadius2 * cos(angle1), topBias + uvRadius2 * sin(angle1));
				ObjPrim_SetVertexUVT(objInnerC, vertexIndex+5, leftBias + uvRadius2 * cos(angle2), topBias + uvRadius2 * sin(angle2));

			}
		}


		//--------------------------------
		//円外〜エフェクト枠
		//揺らいでいる円の外側から矩形までを埋める
		ObjRender_SetPosition(objOuterC, -frameLeft, -frameTop, 0);
		ascent(let iPosO in 0 .. circleVertexCount) 
		{
			let angle1 = iPosO * (360 / circleVertexCount);
			let angle2 = (iPosO + 1) * (360 / circleVertexCount);
			let rectX = 0;
			let rectY = 0;
			if(angle1 >= 0 && angle1 < 90)
			{
				rectX = circleRight;
				rectY = circleBottom;
			}
			else if(angle1 >= 90 && angle1 < 180)
			{
				rectX = circleLeft;
				rectY = circleBottom;
			}
			else if(angle1 >= 180 && angle1 < 270)
			{
				rectX = circleLeft;
				rectY = circleTop;
			}
			else if(angle1 >= 270 && angle1 < 360)
			{
				rectX = circleRight;
				rectY = circleTop;
			}
			let vertexIndex = iPosO * 3;
			ObjPrim_SetVertexPosition(objOuterC, vertexIndex, enemyX + effectRadius * cos(angle1) + frameLeft, enemyY + effectRadius * sin(angle1) + frameTop, 0);
			ObjPrim_SetVertexPosition(objOuterC, vertexIndex+1, rectX, rectY, 0);
			ObjPrim_SetVertexPosition(objOuterC, vertexIndex+2, enemyX + effectRadius * cos(angle2) + frameLeft, enemyY + effectRadius * sin(angle2) + frameTop, 0);

			ObjPrim_SetVertexUVT(objOuterC, vertexIndex, enemyX + effectRadius * cos(angle1) + frameLeft, enemyY + effectRadius * sin(angle1) + frameTop);
			ObjPrim_SetVertexUVT(objOuterC, vertexIndex+1, rectX, rectY);
			ObjPrim_SetVertexUVT(objOuterC, vertexIndex+2, enemyX + effectRadius * cos(angle2) + frameLeft, enemyY + effectRadius * sin(angle2) + frameTop);
		}
		

		//--------------------------------
		//エフェクト枠外
		//エフェクト枠外の背景を描画する
		ObjSpriteList2D_ClearVertexCount(objOuterE);
		ObjRender_SetPosition(objOuterE, -frameLeft, -frameTop, 0);
		ObjSpriteList2D_SetSourceRect(objOuterE, frameLeft, frameTop, frameRight, circleTop + 1);
		ObjSpriteList2D_SetDestRect(objOuterE, frameLeft, frameTop, frameRight, circleTop + 1);
		ObjSpriteList2D_AddVertex(objOuterE);

		ObjSpriteList2D_SetSourceRect(objOuterE, frameLeft, circleTop, circleLeft + 1, circleBottom);
		ObjSpriteList2D_SetDestRect(objOuterE, frameLeft, circleTop, circleLeft + 1, circleBottom);
		ObjSpriteList2D_AddVertex(objOuterE);

		ObjSpriteList2D_SetSourceRect(objOuterE, circleRight, circleTop, frameRight, circleBottom);
		ObjSpriteList2D_SetDestRect(objOuterE, circleRight, circleTop, frameRight, circleBottom);
		ObjSpriteList2D_AddVertex(objOuterE);

		ObjSpriteList2D_SetSourceRect(objOuterE, frameLeft, circleBottom, frameRight, frameBottom);
		ObjSpriteList2D_SetDestRect(objOuterE, frameLeft, circleBottom, frameRight, frameBottom);
		ObjSpriteList2D_AddVertex(objOuterE);

		frame++;
		yield;
	}

	//エフェクト用オブジェクト削除
	Obj_Delete(objInnerC);
	Obj_Delete(objOuterC);
	Obj_Delete(objOuterE);
	Obj_Delete(objShadow);
	ClearInvalidRenderPriority();
}

