スーパープロセッサ
〜 Tonyu System 改良プログラム 〜
点滅現象について
← メインページ
目次
ここでは点滅現象が起こる原因や、Tonyu内部のKernelの事について書いています。
Tonyuの深い部分の話なので難しいかもしれません。
興味があれば読む程度でいいです。
点滅現象はなぜ起こるのでしょうか?
結論から言うと、Tonyuはオブジェクト数が多い時に、いくつかのオブジェクトの処理を後回しにするからです。
(マルチタスクのような処理をしている)
例えば、荷物が多すぎると1回では運べません。こういう時は、2,3回に分けて荷物を運ぶでしょう。
Tonyuも同じで、オブジェクトが多すぎると1フレームでは処理できないので、2,3フレームと分けて処理するのです。
while(1){
}
例えば、上のプログラムは「update();」を書いていません。
Tonyuをやっている方なら、誰もが一回は「update();」を忘れたことがあると思います。
updateメソッドでは、「オブジェクトの書き換え処理を行います」とヘルプに書かれていますが、
実際は、そのオブジェクトを「1フレーム分だけ一時停止(休憩)」させます。
それと同時に、他のオブジェクトに処理を回します。
上のプログラムを実行してしまうと、updateが無いので、本来はオブジェクトが永遠に処理を続けます。
つまり、そのオブジェクトが処理を独占してしまい、ゲームが止まってしまう事が考えられます。
(Tonyuがシングルタスクだったらの話)
しかし、これを実行しても、ゲームが止まるということは起きません。
実は、Tonyuは途中でこの「休憩の無いプログラム」を後回しにして、他のオブジェクトを処理をしにいきます。
こうすることで、Tonyuは並行処理を保ち、
プログラムミスによる無限ループで、ゲームが止まらないようにしていると考えられます。
(Tonyuはマルチタスク)
しかし、このような仕様があるからこそ点滅現象が発生してしまうのです。
話は変わりますが、普段Tonyuプログラマが作ったオブジェクト
(SpriteChar,DxChar,TextChar,PanelChar,SecretCharなど)は、
Kernel内の ProcessGroup.tonyu によって、自動的に管理・実行されています。
ProcessGroup.tonyu が行っている処理を説明すると、下記のようなイメージです。
(下のプログラムはかなり簡略化したものです)
/* ProcessGroup.tonyu 内のオブジェクト実行部分 (イメージ) */
// 実行部分
for ( i=0; i<$procs.size(); i++) {
p = $procs.get(i);
p.オブジェクトを実行();
}
// 表示部分
for ( i=0; i<$chars.size(); i++) {
c = $chars.get(i);
c.オブジェクトを表示();
}
ProcessGroup.tonyu では、オブジェクトの実行部分と表示部分に分かれています。
Tonyuプログラマが、設計画面や、appearメソッドで作り出したオブジェクトは、
$chars配列に登録されます。
Tonyuのヘルプには書かれていない事ですが、
それと同時に$procs配列という実行専用の配列にも、登録されます。
上のプログラムの実行部分では、$procs配列に入っているオブジェクトを、
1つずつ実行するということをやっています。
表示部分も同様に、$chars配列に入っているオブジェクトを、
1つずつ表示するということをやっています。
しかし、オブジェクトが多くなると、処理を後回しにし始めます。
その結果、実行部分が1セットの処理に2フレームかかってしまい、
ゲームの動作速度が 1/2 と遅くなってしまいます。(PCのスペックが低くて処理落ちしている場合は 1/2 より遅くなります)
更に、オブジェクトが多くなると、1/3 1/4 1/5 … と遅くなっていきます。

また、表示部分では1フレーム目に処理できたオブジェクトまでが表示され、
次のフレームで画面がリセットされてから、残りのオブジェクトが表示されます。
つまり、1フレーム目で処理されたオブジェクトと、2フレーム目で処理されたオブジェクトが、交互に表示されます。
交互に表示されるところが、ユーザからは点滅して見えるわけです。
こちらも、更にオブジェクトが多くなると、3フレーム 4フレーム 5フレーム … と表示の切り替えが多くなります。


長時間見ない方がいいです
そのため、Tonyuユーザからみると動作速度が遅くなり、オブジェクトが点滅しているように見えるわけです。
1つのオブジェクトでは、1フレームで処理できる数に制限がかかります。
そこで、このプログラム(ライブラリ)では複数のオブジェクトに処理を分担させています。
複数のオブジェクトを使うことによって、1フレーム中の処理量を増やすことができます。
(実際にはオブジェクトを2つ作りだして、そのオブジェクトを何回も実行させている。次ページで説明します)

図のように、ProcessGroup.tonyu から50個の Processor.tonyu に処理を依頼し、
さらに各々の Processor.tonyu が50個の Processor.tonyu に処理を依頼しています。
一番下の Processor.tonyu が実際のオブジェクトの処理を50個分行っています。
2重に分担させることで、125000個ものオブジェクトを処理できるようになります。
Tonyuで125000個もオブジェクトを出すことはまずないでしょう。
125000個を超えてもバグ・エラーは起きないような作りになっています。
ただし、点滅や処理速度が 1/2 になる現象は発生します。
一応、改良した ProcessGroup.tonyu の中の変数を変えると、この最大処理量を変えることができます。
初期設定では 50×50×50 で125000個まで処理出ますが、
変数の値を変えると、最大処理量を増やすことも減らすこともできます。
オブジェクトを出し過ぎても、点滅は起きなくなりました。
動作も、PCのスペックによる処理落ちが起きない限り、遅くなりません。
しかし、プログラマ自作のオブジェクトの処理量は増えていません。
この改良プログラムは、あくまで ProcessGroup.tonyu の処理量を増やしただけで、
プログラマ自作のオブジェクトまでは、関与できていません。
問題になるのは、1つのオブジェクトで大量の処理を行えない事です。
例えば、次のような問題が起きます。
- 1つのオブジェクトで、大量の描画処理を行うと点滅する
- オブジェクト数が大すぎる時、当たり判定を行っているオブジェクトだけ、動作が遅くなる
ただし、後者の問題はオブジェクト数が約2000〜3000の時に起こる問題で、
当たり判定を行っている状態では、激しく処理落ちしてしまいます。
したがって、この問題はあまり気にしなくていいと思います。
1つのオブジェクトでは、処理量が限られています。
そこで、複数のオブジェクトに処理を分担して、処理量を増やす方法を使います。
次ページから、その方法を紹介していきます。
このライブラリも、その方法を使って処理量を増やしています。
しかし、この方法は少し難しいです。
Tonyuのヘルプにも書いていないメソッドを使ったりします。
多少、処理が複雑になるので、推奨しない方法です。
→ オブジェクトの処理量を増やす方法
← メインページ