// ------------------------------------------------------------------------------------------------- // CreateReflectShot02関数 //  壁で反射する弾を生成する関数です。 //  引数:11個 // // PosX : 発射点のX座標 // PosY : 発射点のY座標 // Speed : 弾の初速 // Angle : 弾の角度 // Accelerate : 弾の1フレームごとの加速量 // MaxSpeed : 最大速度 // Graphic : 弾の画像 // Delay : 弾が発射されるまでの遅延時間 // Wall : 上下左右それぞれの壁で反射するかどうか // Count : 反射回数(0を指定すると無制限) // Frame : 弾の生存フレーム数(0を指定すると無制限) // // 返り値 : オブジェクト型(内部的にはreal値、生成した弾オブジェクトを指す) // // Wallに設定する引数について //  Wallには2進数で4桁のフラグを指定してください。 //  0(=0000)を指定した場合、壁での反射を行いません。 //  15(=1111)を指定した場合、すべての壁で反射します。 //  個別に反射する壁を指定したい場合は、足し算を行ってください。 //  それぞれの壁を示す数字は、上:8 左:4 右:2 下:1 です。 //  たとえば、上と左と右の壁で反射する弾を生成したい場合、 //  Wallには引数として「8+4+2=14」を与えてください。 // // -改定履歴---------------------------------------------------------------------------------------- // 2007/12/27 新規作成 // 2007/12/30 生存フレーム数の設定を追加、Wall設定用のグローバル変数を追加 // 2008/02/06 弾を画面外に生成したときの挙動を変更 // ------------------------------------------------------------------------------------------------- function CreateReflectShot02(PosX,PosY,Speed,Angle,Accelerate,MaxSpeed,Graphic,Delay,Wall,Count,Frame) { let Obj = Obj_Create(OBJ_SHOT); // オブジェクト弾の基本パラメータを設定します。 Obj_SetPosition(Obj,PosX,PosY); Obj_SetSpeed(Obj,Speed); Obj_SetAngle(Obj,Angle); ObjShot_SetGraphic(Obj,Graphic); ObjShot_SetDelay(Obj,Delay); // 描画領域を超えても自動削除は行わないように設定します。 Obj_SetAutoDelete(Obj,false); // タスクを呼び出して反射制御を行います。 CreateReflectShot02Task(Obj,Accelerate,MaxSpeed,Wall,Count,Frame); // 生成したオブジェクトを示す値を返り値に返します。 return Obj; } task CreateReflectShot02Task(Obj,Accelerate,MaxSpeed,Wall,argCount,argFrame) { let Count = argCount; let CountFlag = (Count > 0); let Frame = argFrame; let FrameFlag = (Frame > 0); let Top = (floor(Wall / 8) == 1); let Left = (floor((Wall % 8) / 4) == 1); let Right = (floor((Wall % 4) / 2) == 1); let Bottom = (Wall % 2 == 1); let X = Obj_GetX(Obj); let Y = Obj_GetY(Obj); let Speed = Obj_GetSpeed(Obj); let Angle = Obj_GetAngle(Obj); // 弾が画面外に生成されていた場合、 //  弾の速度と角度から、弾が画面内に入れるかどうかを計算します。 // X軸方向、Y軸方向それぞれに1フレームごとに進む量を計算します。 let OneStepX = cos(Angle) * Speed; let OneStepY = sin(Angle) * Speed; // X軸方向で弾が画面内に入るフレーム、画面外に出るフレームを計算します。 let InFrameX = (GetClipMinX - X) / OneStepX; let OutFrameX = (GetClipMaxX - X) / OneStepX; if (InFrameX > OutFrameX) { let Work = InFrameX; InFrameX = OutFrameX; OutFrameX = Work; } // Y軸方向で弾が画面内に入るフレーム、画面外に出るフレームを計算します。 let InFrameY = (GetClipMinY - Y) / OneStepY; let OutFrameY = (GetClipMaxY - Y) / OneStepY; if (InFrameY > OutFrameY) { let Work = InFrameY; InFrameY = OutFrameY; OutFrameY = Work; } // X軸方向に入る前にY軸方向から抜けてしまう場合、 // またはY軸方向に入る前にX軸方向から抜けてしまう場合、 // 弾は画面内に入る弾道ではないため、弾オブジェクトを削除します。 if ((InFrameX > OutFrameY)||(InFrameY > OutFrameX)) { Obj_Delete(Obj); } // 弾が削除されるか、画面内に入るまで待ちます。 while (Obj_BeDeleted(Obj) == false) { X = Obj_GetX(Obj); Y = Obj_GetY(Obj); Speed = Obj_GetSpeed(Obj); // 弾が画面内に入った場合、ループを抜けます。 if ((X >= GetClipMinX)&&(X <= GetClipMaxX)&&(Y >= GetClipMinY)&&(Y <= GetClipMaxY)) { break; } // 弾の加速処理を行います。 if (Accelerate > 0) { if (Speed + Accelerate < MaxSpeed) { Obj_SetSpeed(Obj,Speed + Accelerate); } } else if (Accelerate < 0) { if (Speed + Accelerate > MaxSpeed) { Obj_SetSpeed(Obj,Speed + Accelerate); } } yield; // 生存フレーム判定フラグがオンになっている場合、 //  弾の生存フレーム数を更新します。 //  生存フレーム数が尽きた場合、オブジェクトを削除します。 if (FrameFlag == true) { Frame -= 1; if (Frame <= 0) { Obj_Delete(Obj); } } } // 弾が削除されるまで、反射判定と反射処理を繰り返します。 while (Obj_BeDeleted(Obj) == false) { X = Obj_GetX(Obj); Y = Obj_GetY(Obj); Speed = Obj_GetSpeed(Obj); Angle = Obj_GetAngle(Obj); // 反射したかどうかを判定します。 //  @座標が描画範囲を超えていること(=弾が壁を越えたこと) //  A座標が越えた壁が、反射対象になっていること //  B反射回数が残っていること、または反射回数判定フラグがオフになっていること // この3つの条件をすべて満たした場合のみ、反射処理を行います。 if (Y < GetClipMinY) { if ((Top == true)&&((Count > 0)||(CountFlag == false))) { Y = (GetClipMinY * 2) - Y; Angle = 0 - Angle; Count -= 1; } else { Obj_Delete(Obj); } } if (Y > GetClipMaxY) { if ((Bottom == true)&&((Count > 0)||(CountFlag == false))) { Y = (GetClipMaxY * 2) - Y; Angle = 0 - Angle; Count -= 1; } else { Obj_Delete(Obj); } } if (X < GetClipMinX) { if ((Left == true)&&((Count > 0)||(CountFlag == false))) { X = (GetClipMinX * 2) - X; Angle = 180 - Angle; Count -= 1; } else { Obj_Delete(Obj); } } if (X > GetClipMaxX) { if ((Right == true)&&((Count > 0)||(CountFlag == false))) { X = (GetClipMaxX * 2) - X; Angle = 180 - Angle; Count -= 1; } else { Obj_Delete(Obj); } } // 弾の加速処理を行います。 if (Accelerate > 0) { if (Speed + Accelerate < MaxSpeed) { Obj_SetSpeed(Obj,Speed + Accelerate); } } else if (Accelerate < 0) { if (Speed + Accelerate > MaxSpeed) { Obj_SetSpeed(Obj,Speed + Accelerate); } } Obj_SetPosition(Obj,X,Y); Obj_SetAngle(Obj,Angle); yield; // 生存フレーム判定フラグがオンになっている場合、 //  弾の生存フレーム数を更新します。 //  生存フレーム数が尽きた場合、オブジェクトを削除します。 if (FrameFlag == true) { Frame -= 1; if (Frame <= 0) { Obj_Delete(Obj); } } } } // Wall設定用のグローバル変数 let WALL_TOP = 8; let WALL_LEFT = 4; let WALL_RIGHT = 2; let WALL_BOTTOM = 1;