第13回:冥符「常世桜」 3
反射
今回は反射弾です。
反射弾は普通の弾だと作れないのでオブジェクト弾というものを使って実装します。
オブジェクト弾の他の弾と違うところは、発射後に弾速や角度を変更できるということです。
オブジェクト弾は関数Obj_Create(OBJ_SHOT)で作成し、
この関数が返すオブジェクトIDをObj系関数の引数とすることでパラメータの変更・参照を行います。
とりあえず下のやつをスクリプト内に取り込みましょう。
task CreateObjectShot(x, y, speed, angle, graphic, delay) {
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, x, y);
Obj_SetSpeed(obj, speed);
Obj_SetAngle(obj, angle);
ObjShot_SetGraphic(obj, graphic);
ObjShot_SetDelay(obj, delay);
loop(delay){ yield; }
while(!Obj_BeDeleted(obj))
{
yield;
}
x, y: Obj_SetPositionで弾の発射座標の指定
speed: Obj_SetSpeedで弾速の指定
angle: Obj_SetAngleで弾の角度を指定
graphic: ObjShot_SetGraphicで弾の種類を指定
delay: ObjShot_SetDelayで弾の発射遅延時間を指定
この弾を画面端で反射させるには、処理をwhile(!Obj_BeDeleted){}に書くことになります。
このとき、間違ってyieldを削除したりするとフリーズするので注意。
では、反射処理を実装しましょう。
通常、反射後の角度は左右端では「180-反射前の角度」、上下端では「360-反射前の角度」です。
が、今回は反射後ランダムな角度に飛び散ります。
なので、反射後の角度を、rand関数を使ってばらけさせることにします。
また、反射後の座標は「反射端の座標*2-反射前の座標」となります。
角度と座標は、Obj_GetAngleとObj_GetX,Obj_GetYで取得できます。
一度反射したら[break]を使ってループを脱出し、2回反射しないようにします。
反射後の角度のランダム化と弾グラフィックの変更はループ脱出後に行いましょう。
while(!Obj_BeDeleted(obj))
{
//左端反射
if(Obj_GetX(obj)<GetClipMinX){
Obj_SetX(obj, GetClipMinX*2 - Obj_GetX(obj));
Obj_SetAngle(obj, 180 - Obj_GetAngle(obj));
break;
}
//右端反射
if(Obj_GetX(obj)>GetClipMaxX){
Obj_SetX(obj, GetClipMaxX*2 - Obj_GetX(obj));
Obj_SetAngle(obj, 180 - Obj_GetAngle(obj));
break;
}
//上端反射
if(Obj_GetY(obj)<GetClipMinY){
Obj_SetY(obj, GetClipMinY*2 - Obj_GetY(obj));
Obj_SetAngle(obj, 360 - Obj_GetAngle(obj));
break;
}
yield;
}
ObjShot_SetGraphic(obj, PURPLE12);//弾種を変更
Obj_SetAngle(obj, Obj_GetAngle(obj)+rand(-25,25));//弾の角度を変更
Obj_SetSpeed(obj, rand(0.5, 1.5));//弾速を変更
これを組み込んだら、nwayのCreateShot01をCreateObjectShotに変更しましょう。
ここまでのスクリプトがこれです。
#東方弾幕風
#Title[冥符「常世桜」]
#Text[冥符「常世桜」]
#ScriptVersion[2]
script_enemy_main{
let imgBoss= "script\img\ExRumia.png";
@Initialize{
SetLife(2000);
LoadGraphic(imgBoss);
SetTexture(imgBoss);
SetGraphicRect(0, 0, 63, 63);
CutIn(YOUMU, "冥符「常世桜」", "", 0, 0, 0, 0);
SetScore(2000000);
SetTimer(50);
Tmain;
}
@MainLoop{
SetCollisionA(GetX, GetY, 24);
SetCollisionB(GetX, GetY, 24);
yield;
}
@DrawLoop{
DrawGraphic(GetX, GetY);
}
@Finalize{
DeleteGraphic(imgBoss);
}
task Tmain
{
SetMovePosition02(GetCenterX, GetCenterY, 60);
wait(60);
let angle;
let frame = 50;
loop
{
shot(4, 4, 2);
wait(frame);
if(frame>30){frame-=0.5;}
}
}
function shot(speed, way, nloop)
{
let angle = rand(180-25, 360+25);
loop(nloop)
{
nway(GetX, GetY, speed, angle, way, 10, BLUE22);
speed-=0.5;
}
}
function nway(x, y, speed, anglebase, way, span, color)
{
let angle = anglebase - (way - 1) / 2 * span;
loop(way)
{
CreateObjectShot(x, y, speed, angle, color, 10);
angle += span;
}
}
task CreateObjectShot(x, y, speed, angle, graphic, delay) {
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, x, y);
Obj_SetSpeed(obj, speed);
Obj_SetAngle(obj, angle);
ObjShot_SetGraphic(obj, graphic);
ObjShot_SetDelay(obj, delay);
loop(delay){ yield; }
while(!Obj_BeDeleted(obj))
{
//左端反射
if(Obj_GetX(obj)<GetClipMinX){
Obj_SetX(obj, GetClipMinX*2 - Obj_GetX(obj));
Obj_SetAngle(obj, 180 - Obj_GetAngle(obj));
break;
}
//右端反射
if(Obj_GetX(obj)>GetClipMaxX){
Obj_SetX(obj, GetClipMaxX*2 - Obj_GetX(obj));
Obj_SetAngle(obj, 180 - Obj_GetAngle(obj));
break;
}
//上端反射
if(Obj_GetY(obj)<GetClipMinY){
Obj_SetY(obj, GetClipMinY*2 - Obj_GetY(obj));
Obj_SetAngle(obj, 360 - Obj_GetAngle(obj));
break;
}
yield;
}
ObjShot_SetGraphic(obj, PURPLE12);
Obj_SetAngle(obj, Obj_GetAngle(obj)+rand(-25,25));
Obj_SetSpeed(obj, rand(0.5, 1.5));
}
function wait(w){loop(w){yield}}
}
このスクリプトを実行すると、それっぽいものが出来たかと思います。
これで、冥符「常世桜」の再現は終わりです。
次回は、豊作「穀物神の約束」です。