黒の時代

弾幕風ph3初心者による弾幕風講座。まだ難しいことは出来ませんが、質問要望あればコメントにどうぞ。

no.5 難敵()マイクロスレッド

マイクロスレッドの話です。

 前回まで弾幕を作っていたアナタは、色々限界を感じているはずだ。
そう。常に一定の間隔でしか弾幕を吐けない。

いや配列使えばできるかな…

と言うわけで、今回は周りと独立して仕事をしてくれるシャンハーイのような機能を紹介。一度呼び出したら、10フレームごとに5回弾幕を吐いて吐き終わったら消えてくれる。そんな便利な機能。

それがマイクロスレッド。

task NWAYS(color) {
   loop(7) {
      nway(2,color);
      loop(10) {yield;}
   }
}
function nway(speed,color) {
   let a = 0;
   while(a<360) {
      CreateShotA1(ex,ey,speed,GetAngleToPlayer(objEnemy)+a, color,0); a+=15; }
   }
}

@Mainloopには

if(frame%100==80) { NWAYS(DS_BALL_S_WHITE); }

を。

なんかちょっと複雑なモノが出来ましたね。

そしてloop(10) {yield;} とは・・・?

ざっくり説明します。正確なことはロベールさんの解説講座(0.x用)に書かれているのでそちらを参照してください(超目そらし

実はこのyield;さん、最初のテンプレからいました。

@MainLoop {
   ex = ObjMove_GetX(objEnemy);
   ey = ObjMove_GetY(objEnemy); 
   ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24);
   frame++;
   yield;  ←ココ
   if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) { Obj_Delete(objEnemy); CloseScript(GetOwnScriptID()); return; }
 }

簡単に説明をすると、

task X { A ; yield; B; yield; C; yield; D;}

とある場合、

  1. task X が呼び出される
  2. Aを処理
  3. yieldだ!@MainLoopのyieldに戻れ!
  4. @MainLoopを、yieldの後の残ったif(ObjEnemy_GetInfo 〜以下最後まで実行
  5. 次フレームの@MainLoop実行
  6. @MainLoopの処理中にyield;まで到達
  7. task Xのyield;に移動
  8. Bを実行
  9. yieldだ!MainLoopのyieldに戻れ!
  10. @MainLoopを、yieldの後の残ったif(ObjEnemy_GetInfo 〜以下最後まで実行
  11. 次フレームの@MainLoop実行
  12. and so on ...

となります。青字が1フレーム中の動作です。複数のマイクロスレッドがあった場合、Mainloopのyield;→task Xのyield;→task Yのyield;→Mainloopに帰って来ます。こうやって同時進行をしていきます。Bに何も書いてない場合、何も行われません。

ここで

task X {
   A;
   loop(10) {yield;}
   B;
}

は task X { A; yield; yield; yield; yield; yield; yield; yield; yield; yield; yield; B;}と同じ。
10フレーム間何もせずに@MainLoopのyieldからやってきた処理を受け流していることになります。休んで、タイミングを計っているわけです。

わかって貰えたでしょうか…

なんだろう。一瞬ごとに咲夜が時を止めてバラバラに動くナイフの動きを見て回っていちいち制御してる、みたいな。そんな感じ(ぇ

で、休んでるloop(10) {yield;}を

function wait(time) {
   loop(time) {
      yield;
   }
}

スクリプト末に書いて、wait(10);って書くと楽です。よく使うので。

 

…このwaitはtaskではいけない。しばらくはtaskの方がよく使うから、ついついfunctionを軽視しがち(?)だけど、taskとfunctionは別物。

これをtaskで書くと、別の独立したマイクロスレッドで10回yield;がループするだけで、何もしてくれません。10フレーム間突っ立ってて消えるシャンハーイを呼び出すだけ。

対して、functionはコピペみたいなモノ。呼んだ瞬間に処理に割り込んでくれる。

そこは大きく違います。

 

あと、functionは返り血返り値があったりします。これもロベールさんのサイト参照でお願いします。

 

・・・うん。

 

とりあえずマイクロスレッドは便利だし、これなしに弾幕は作れません。

>>目次:no.0