自機の作成

注意


ph3には使えない内容です。v0.xにだけ使えます。


1 最初にやること


やっておいたほうがいいこと。

  th_dnhフォルダ内にplayerフォルダを作る
   混乱を避けるためにさらにフォルダを作っておく
   (名前は適当に決めてください。ここではTestという名前にしておきます)

Testフォルダの中にスクリプトを入れていきます。

2 最低限必要な部分


まずはTestフォルダの中に「TestPlayer.txt」というファイルを作ってください。
次に、↓をコピーしたり入力したりして下さい。

#東方弾幕風[Player] //自機スクリプトであることを示す
#ScriptVersion[2] //スクリプトバージョンが2であることを示す
#Menu[Sample] //自機を選ぶときに表示される部分、自機の名前
#Text[] //自機の説明
#Image[] //自機を選ぶときに表示される画像
#ReplayName[Sample] //リプレイに記載される自機の名前(半角8文字以内)
 
script_player_main {
 
    @Initialize {
        // 初期化
    }
    
    @MainLoop {
        // 毎フレーム実行される
    }
    
    @Missed {
        // 被弾したとき@MainLoopの代わりに実行される
    }
    
    @SpellCard {
        // スペルカードを発動した瞬間に実行される
    }
    
    @DrawLoop {
        // 描画するとき実行される
    }
    
    @Finalize {
        // 後始末
    }
}

ここに色々と書き込んでいきます。とりあえずこれが骨組みだと分かればいいです。

3 自機の画像を表示


自機の画像はふつう、
・正面を向いている状態
・左を向いている状態
・右を向いている状態
この3つがあります。
これらの画像を区別させるには、「キーが押されているか否か」で分岐することで実装できます。
キーを押しているかどうかはGetKeyStateで取得できるので、
この関数を使ってif文などで分岐させましょう。
尚、ここでは最初からplayerフォルダに入っているRumia.pngを借用します。
予めTestPlayer.txtがあるフォルダにRumia.pngを入れておいてください。
後、下の例では.\Rumia.pngと書かれていますが、
実際のプログラムには.¥Rumia.pngと書いてください。(¥は半角)


@Initialize{
    LoadGraphic(".\Rumia.png");
}
@DrawLoop{
    SetTexture(".\Rumia.png");
     
    if((GetKeyState(VK_LEFT) == KEY_PUSH) | | (GetKeyState(VK_LEFT) == KEY_HOLD)) {
        SetGraphicRect(1, 133, 49, 188);
    }else if((GetKeyState(VK_RIGHT) == KEY_PUSH) | | (GetKeyState(VK_RIGHT) == KEY_HOLD)) {
        SetGraphicRect(1, 69, 49, 124);
    }else{
        SetGraphicRect(1, 5, 49, 60);
    }
    DrawGraphic(GetPlayerX, GetPlayerY);
}
@Finalize{
    DeleteGraphic(".\Rumia.png");
}

解説




4 基本的な内容の実装

移動速度


関数SetSpeedを使う。宣言は@Initializeで行う。


SetSpeed(引数:2)
//1:高速移動速度
//2:低速移動速度

かすり判定


関数SetGrazeCircleを使う。宣言は@Initializeで行う。


SetGrazeCircle(引数:1)
//1:かすり判定の半径

アイテム回収ライン


関数SetItemCollectLineを使う。宣言は@Initializeで行う。


SetItemCollectLine(引数:1)
//1:アイテムを回収するライン(y軸)

初期ボム数


関数SetInitialBombCountを使う。宣言は@Initializeで行う。

SetInitialBombCount(引数:1)
//1:初期ボム数

残機画像


関数SetPlayerLifeImageを使う。宣言は@Initializeで行う。

SetPlayerLifeImage(引数:5)
//1:描画する画像のパス
//2:矩形x軸最小値
//3:矩形y軸最小値
//4:矩形x軸最大値
//5:矩形y軸最大値

当たり判定


関数SetIntersectionCircleを使う。宣言は@MainLoopで行う。

SetIntersectionCircle(引数:3)
//1:当たり判定の中心座標 x軸
//2:当たり判定の中心座標 y軸
//3:当たり判定の半径

5 ショットの実装


自機ショットを作成する関数があります。それは

CreatePlayerShot01(引数:7)
//1:x座標
//2:y座標
//3:速度
//4:角度
//5:威力
//6:貫通力
//7:ID値

これです。勘の良い方なら(ry、この関数には「画像」を指定する引数がありません。
その代わりに、「ID値」なるものを指定しなければならないようです。
公式ヘルプを見ると、「定義済みの画像のID値」とあります。
「定義済みの画像」、つまり画像を先に定義しておかなければならないのです。
画像の定義は別のスクリプトで行います。新しいファイルを作ってください。
場所はplayerフォルダ内ならどこでもおkです。名前も適当に

スクリプトにまず書いてもらいたいのが、これ

#PlayerShotData

これは何か?というと、「#東方弾幕風」←これと同じようなものです。
PCに「このスクリプトは自機画像の定義をしている」ということを伝えるのです。
わかんないなら何も考えずに書きましょう。意味はそんなに重要じゃないですから

次に書くのは画像のパスです。

ShotImage = "画像のパス"

画像のパスは今までどおりに書いておkです。
今回も初期から入ってる画像を流用させてもらいましょう。

ShotImage = "player\Rumia\RumiaShot.png"

あ、そうそう 「;」を忘れてるじゃんって思ってる人もいると思いますが、
別に忘れてるわけじゃなくてこれにはつけないだけですからね。文法ですからね?

次は画像の定義です。
文法はこんな感じ


ShotData {
  id = 1
  rect = (1, 1, 31, 31)
  render = ADD
  alpha = 64
  angular_velocity = rand(-5, 5)
}

これらも;はいりません。
まず id ですね。これはそのまま、CreatePlayerShot01で指定するID値を決めます。
次に rect 。これは画像の矩形を指定します。
render は画像の描画方法です。ALPHA, ADD 等があります。
ALPHA は半透明描画、ADD は加算描画です。詳しくはヘルプへ

加算描画:重なるとどんどん白くなっていく描画方法のこと。
     原作では大弾や火炎弾などがこれにあたる。

alpha は透明度を指定します。普通に255だと、他の弾と見間違え易くなるので、なるべく低い値を入れましょう。低すぎると見えませんが
angular_velocity は画像の回転速度です。右回りの速さなので、左回りにしたい時はマイナスの値を指定しましょう。
今回の画像は円いので回転させますが、札などを回転させると違和感があります。
回転させるか否かは考えましょう。

んで、さっきのCreatePlayerShot01に指定したID値を入れると、ちゃんとショットが出来たと思います。
ですが、すごい連射ですね。威力が低め(1とか)でも、結構な威力になってしまっています。
これの解決方法はif文を使うことです。
変数ShotCountとかを用意して、毎フレーム増加させ、
if文で分岐させればできます。例はコチラ


let ShotCount = 0;
@MainLoop {
  if(ShotCount % 5 == 0){
    CreatePlayerShot01(GetPlayerX, GetPlayerY, 20, -90, 3, 1, 1);
  }
  ShotCount += 1;
}

こんな感じで良いんじゃないでしょうか。
ShotCount % 5 == 0 っていうのは、「ShotCountの値を5で割った余りが0」ということ、
つまり「ShotCountが5の倍数のとき」という判定をしているのです。
数値を大きくすれば連射しなくなるし、逆に小さくすればチート威力です。
あえて威力低くして擬似レーザーなんてのも面白いかも

公式ヘルプにも「複雑な挙動の弾はObjShotとかObjLaserで作ってください」って書いてあります。
具体的に言えば、ホーミング弾ですね。その辺は+で説明しようと思ってたり

6 ボムの実装

+1 作成した自機で分岐をするには


GetPlayerScriptNameで自機スクリプトの名前を取得して、それをif文などで分岐させる。会話の分岐などに使える

    
let PlayerName = GetPlayerScriptName;
 
if(PlayerName == "TestPlayer1.txt"){
    //分岐内容1
}else if(PlayerName == "TestPlayer2.txt"){
    //分岐内容2
}


+2 特殊な軌道の弾


特殊な軌道の弾は、公式ヘルプにもあるように
「ObjShotやObjLaserを使って実装できます」。
ObjShotには、威力や貫通力を指定できる関数があります。

ObjShot_SetDamage(引数:2);


ObjShot_SetPenetration(引数:2);

この2つですね。これらを使って、

task HomingShot {
  let obj = Obj_Create(OBJ_SHOT);
  Obj_SetPosition(obj, GetPlayerX, GetPlayerY);
  /* 省略 */
  ObjShot_SetGraphic(obj, 2); //ここには定義済みのID値を入れます
  ObjShot_SetDamage(obj, 4);
  ObjShot_SetPenetration(obj, 1);
  
  while(!Obj_BeDeleted(obj)){
    yield;
  }
}

このwhileの中で角度を敵の方向に毎フレーム調整すればホーミング弾の出来上がり。

  • 最終更新:2016-04-11 04:55:23

このWIKIを編集するにはパスワード入力が必要です

認証パスワード