第15回 人界剣「悟入幻想 -Easy-」 (2)

今回は敵を色々と移動させてみます。また、各段階でダメージの大きさを変更したりもしてみましょう。

要旨

それではいってみましょう。

敵の移動

では、今回は敵を移動させてみましょう。悟入幻想では、ボスは次のように移動します。

  1. 右下へ移動します。
  2. 一旦浮揚します。
  3. 一時停止し、力を溜めます。
  4. 左端へ一気に移動し、暫く停止します。
  5. 左上へ移動します。
  6. あとは、移動→構え→攻撃を続けます。

1 は既に standBy で行いましたね。今回は 2 以降を作りたいと思います。

これら全ての動作を TMain に直接書くこともできます。しかし、standBy でやったのと同様に、段階ごとにサブルーチンに分けた方が流れが把握しやすくなります。1つの関数、サブルーチン、マイクロスレッドは、あまり長くならないようにするのが、綺麗なプログラムを書くコツです。どんなに長くても、100 行は超えないよう心がけましょう。綺麗なプログラムは、バグを未然に防ぎやすく、また、バグを発見しやすく、修正しやすいです。一方、複雑で汚いプログラムは、バグを生みやすく、バグを発見しにくく、修正しにくいのです。プログラムを綺麗に書くというのは、美的感覚を満足させるために行うのではなく、バグを抑えるために行うのです。

では、1つずつ作っていきましょう。先ずは 2 の浮揚するサブルーチン levitate です。

// 浮揚
sub levitate {
    let wLev = 60;

    setGraphicStop;
    SetMovePosition02(xIni, yIni + 10, wLev);
    wait(wLev);
    SetMovePosition02(xIni, yIni, wLev);
    wait(wLev);
}

先ず、浮揚時はキャラのグラフィックを停止時のグラフィックにします。そのため、サブルーチン setGraphicStop を呼んでいます。これは前回作ったサブルーチンです(この講座では自作の関数やサブルーチンは小文字で始めているので、東方弾幕風が提供する関数かそうでないかが分かるようになっています)。

あとは 60×2 フレームかけて、10 ピクセルだけ上下します。これは特に問題ないですね。

次は、3 の力を溜めるサブルーチン concentration です。力を溜める効果を表示するには、Concentration01 という関数を使います。

// 力を集中
sub concentration {
    let wConc = 60;

    setGraphicPose;
    Concentration01(wConc);
    wait(wConc);
}

力を溜めるときは、特殊なポーズをとることにします。そのため、サブルーチン setGraphicPose を呼んでいます。そして、力を溜めるために Concentration01 を呼んでいます。これは、指定したフレーム数の間、力を溜める効果を表示する関数です。自動的に yield してくれるわけではないので、wait を自前で呼ぶ必要があります。これで力を溜める処理は終了です。

次は、4 の左端へ移動するサブルーチン slash です。実際には一番下に剣戟の跡が残って、そこに当たると死ぬわけですが、この部分は今回実装しません。

// 横薙ぎ
sub slash {
    let wMove = 10;
    let wStop = 60 - wMove;

    SetMovePosition02(xSlash, ySlash, wMove);
    setGraphicMove;
    wait(wMove);
    wait(wStop);
}

単に、左端へ移動し、その後停止しているだけです。座標 xSlash, ySlash は別のところで定義しておきます。

次は、5 の左上へ移動するサブルーチン ready です。

// 定位置へ移動して、攻撃開始
sub ready {
    let wMove = 120;
    let wStop = 60;

    SetMovePosition02(xStart, yStart, wMove);
    setGraphicMove;
    wait(wMove);

    setGraphicStop;
    wait(wStop);
}

単に、左上へ移動し、その後停止しているだけです。slash では停止時にも移動時とグラフィック同じでしたが、ready では停止時のグラフィックに変更しています。

最後に、6 の移動するサブルーチン move を作ります。

// 移動
sub move {
    let wMove = 60;

    moveToPlayer(rand(40, 80), rand(-40, 40), wMove,
                 GetClipMinX + 48, GetClipMinY +  32,
                 GetClipMaxX - 48, GetClipMinY + 128);
    setGraphicMove;
    wait(wMove);
}

前と可動範囲が変わってますが、それ以外は特に変わっていませんね。moveToPlayer の定義は前と同じです。

では、これらのサブルーチンを TMain で呼んでみましょう。

// メインタスク
task TMain {
    yield;

    standBy;
    levitate;
    concentration;
    slash;
    ready;

    loop {
        move;
        shot;
    }
}

すっきりしてますね。ここで、shot は攻撃のためのサブルーチンですが、今のところは一時停止するだけにしておきましょう。

// way 弾を発射
sub shot {
    let wStop = 60;

    setGraphicPose;
    wait(wStop);
}

以上をまとめたプログラムをここに置いておきます。実際に実行してみて、期待通り動いていることを確かめてみてください。

ダメージレート

さて、実行してみて気付いたことはありませんか? ショットを打たないでテストしていると気付かないかもしれませんが、ちょっとショットを当ててみてください。最初の下側で動いているところでも、ゴンゴンとライフが減っていくことが分かると思います。

こういう、準備段階の動作中でもライフがどんどん削れてしまうのは問題です。実際、妖々夢においては攻撃が始まるまでは守備力が非常に高く、あまりライフが減らないようになっています。

そこで、ここでも同様にライフがあまり減らないようにしてみましょう。具体的には、

  1. 初期位置に移動するまでは無敵。
  2. 左上に移動するまでは守備力高。
  3. 左上に移動して以降は通常の守備力。

としてみましょう。ただ、このように守備力を変化させるにはどのようにすればいいのでしょうか?

先ずは、無敵状態にする方法です。無敵状態にするには、SetInvincibility という関数を使います。Invincibility というのは無敵という意味で、Invincible(インビンシブル;無敵の)の名詞形です。ファミコン世代の人には、ファイナル○ァンタジー3で出てくる巨大飛空艇でおなじみの単語ですね。SetInvincibility には、無敵にする時間を指定します。

// 初期位置へ移動
sub standBy {
    let wIni = 120;

    SetMovePosition02(xIni, yIni, wIni);
    setGraphicMove;

    SetInvincibility(wIni);
    wait(wIni);
}

次は、守備力を変化させる方法です。守備力を変化させるにするには、SetDamageRate という関数を使います。これには、ショットに対するダメージレートと、ボムに対するダメージレートを指定します。ダメージレートは、ダメージを通常の何 % にするかを表します。

@Initialize {
    CutIn(YOUMU, name, "", 0, 0, 0, 0);

    SetLife(2000);
    SetTimer(66);
    SetScore(4000000);
    SetDamageRate(5, 5);

    LoadGraphic(imgBoss);
    SetTexture(imgBoss);

    TMain;
}

// 定位置へ移動して、攻撃開始
sub ready {
    let wMove = 120;
    let wStop = 60;

    SetMovePosition02(xStart, yStart, wMove);
    setGraphicMove;
    wait(wMove);

    setGraphicStop;
    wait(wStop);

    SetDamageRate(40, 40);
}

100 で 100% になるわけですが、別に最終的に 100% にする必要はありません。最終的にダメージレートが 100% になるようにライフを調整するか、それともライフを変えずにダメージレートを調整するかは、状況次第です。後に出てくる Plural のスクリプトを作る場合には、ライフを固定してダメージレートを調整する場合が多くなると思います。ここでは、Single のスクリプトですが、気にせずライフを固定して調整しました。

また、ダメージレートを 0% にすることで無敵にすることもできます。SetInvincibility を使うか SetDamageRate を使うかは、状況と好み次第でしょう。

以上をまとめたプログラムをここに置いておきます。実際に実行してみて、ダメージレートが変化してることを確認してみてください。

要旨

次回はレーザーを配置してみましょう。

第14回 | 第16回 | 目次へ戻る

この講座はロベールが作成しました。
inserted by FC2 system