魔術師の巣窟(仮)
趣味のゲーム製作サイトです。 そのうちHPを作ると思いますので、ここは仮住まいです。
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
長々と
意外と知られていない気がする仕様についてつらつらと。

長いので追記へ
ウディタのイベント起動条件にはいくつか種類があるので、この場では便宜的に「主実行イベント」と、「並列実行イベント」に分けます。「イベント呼び出し」については呼び出すイベントによって変わるので定義できません。また、主実行イベントを並列実行から呼び出したり、その逆をやったりといった処理も可能ですが、その場合も呼び出した側のイベントに左右されます。

主実行イベント 並列実行イベント
マップイベント 決定キーで実行
プレイヤー接触
イベント接触
自動実行
並列実行
コモンイベント 自動実行 並列実行
並列実行(常時)

こんな感じ。具体的な特徴を挙げると、
主実行イベント 並列実行イベント
一度に実行できるのは一つだけ
主人公・イベントの動作が止まる
Sys13:[イベント実行中?(1=ON)]が1になる
一度に複数起動できる
主人公・イベントの動作は止まらない
Sys13:[イベント実行中?(1=ON)]には影響しない

と、まぁこんな感じです。
ここまではマニュアルでも確認できる話。ここからはもう一歩踏み込みます。
なお、この記事には『独自研究』に基づいた記述が含まれています。別に独自研究は載せないなんて制約はこのブログにはありませんので、根拠となる解釈、評価、分析、総合の根拠となる出典を示すつもりもありません。[要出典]
最近のマニュアル追加事項は結構私が書いているのでそちらも怪しいといえば怪しいかもしれません。いや、SmokingWOLFさんには見せていますけど。

まず、一つのイベントを分解しましょう。
ここで、「EOFコマンド」というものを定義します。EOFはEnd Of Frameの略です。End Of Fileではありません。この場で使っているだけですので、他の場所で言うと通じないと思います。英語的に合っているかなんて知らん知らん。

「EOFコマンド」に含まれるのは、
■文章
■文章選択肢
■文字列操作:キーボード入力
■画面スクロール:[ウェイト]
■キー入力(入力待ち)
■動作完了までウェイト(※ただし一つでも動作指定があるとき)
■トランジション実行(※ただしトランジション指定が完了までウェイトになっているとき)
■ウェイト
です。

つまり、EOFコマンドは、その地点でイベント処理が停止するコマンドです。
イベントは、1フレームの間に、「イベントの初め」または「EOFコマンドの次のコマンド」から、「イベントの最後」または「次のEOFコマンド」まで処理します。
ものすごい適当に並べていますが、仮にこんなイベントがあったとしましょう。
┏■変数操作: V0[] = 0 + 0
┃■変数操作+: V0[] = 主人公 の X座標(標準)
┃■合成音声:[これわさ'んぷるです。すこ'し/ふくざつな/おんせーき'ごーです。] 速度[100]%/音量[100]%/声の高さ[100]%/遅延[0]フレーム
┃■条件分岐(文字): 【1】このコモンEvセルフ変数5 が"" と同じ
┃ ◇分岐: 【1】 [ このコモンEvセルフ変数5 が"" と同じ ]の場合↓
┃|■
┃◇分岐終了◇◇
┃■変数操作+: V0[] = 主人公 の X座標(標準)
┃■条件分岐(文字): 【1】このコモンEvセルフ変数5 が"" と同じ
┃ ◇分岐: 【1】 [ このコモンEvセルフ変数5 が"" と同じ ]の場合↓
┃|■
┃◇分岐終了◇◇
┗■文章:
┏■ピクチャエフェクト:0 [フラッシュ] R0/G0/B0 (0)フレーム
┃■色調変更: R100 G100 B100 / 0フレーム
┃■ループ開始
┃|■ループ中断
┃|■
┃◇ループここまで◇◇
┃■回数付きループ [ 7 ]回
┃|■
┃◇ループここまで◇◇
┃■トランジションタイプ指定: [瞬間表示] 0フレーム(ウェイト有り)
┗■トランジション実行
┏■ピクチャ表示:1 ファイル「」 X:0 Y:0 0(0)フレーム
┃■データのセーブ: 1
┃■条件分岐(変数): 【1】V0[]が0と同じ 【2】V0[]が1と同じ
┃ ◇分岐: 【1】 [ V0[]が0と同じ ]の場合↓
┃|■
┃ ◇分岐: 【2】 [ V0[]が1と同じ ]の場合↓
┃|■
┃◇分岐終了◇◇
┗■
左側の┏~┗でくくってある範囲が、1フレームの処理になります(呼び出されたイベントや自動実行のイベントなどの場合はこのイベントが終わった後も処理が続くかもしれませんが……)。エラーが発生でもしない限り、一度処理を始めたらこの範囲は最後まで処理します。例え途中でイベントの起動条件を満たさなくなったとしても、です(起動条件チェックは処理開始前に行われます)。

一つのイベントを1フレームの中で分解してみました。では、次はイベント全体を1フレームの中で分解します。
"並列"イベントと名は付いているものの、コンピューターは基本的に直列にしか処理できません。並列に見えるのは処理速度がものすごく速いからで、必ず順番があるはずです。

ここで、5つのイベントが実行されているとしましょう。
1.マップイベント1 起動条件:並列実行
2.マップイベント5 起動条件:決定キーで実行(主実行イベント)
3.マップイベント8 起動条件:並列実行
4.コモンイベント10 起動条件:並列実行(常時)
5.コモンイベント20 起動条件:並列実行
いずれのイベントも、起動条件は満たしているものとします。

すると、どのような処理がなされるのか。こうなります。
マップイベント1

マップイベント8

コモンイベント10

コモンイベント20

マップイベント5

イベントの処理方法にはきちんと規則があって、以下のような優先順位で処理が行われます。
1.並列実行イベント>主実行イベント
2.マップイベント>コモンイベント
3.番号の小さいイベント>番号の大きいイベント
表にするとこうなります。
並列実行 主実行
マップ コモン マップ コモン
1 2 3 4 5 6 7 8

ちなみに主実行イベントは複数起動できないので、この例で言うと、例えばマップイベント10が自動実行で条件を満たしていたとしても、マップイベント5が実行されている限り処理は行われません。
また、複数の自動実行イベントの条件が同時に満たされたときは、上記の優先順位がもっとも高いイベントが実行されます。


次に、並列実行イベントの仕様について。


自動実行イベントの中身をこうして、条件を満たしてやりました。

■ループ開始
|■
◇ループここまで◇◇

1フレームあたりの処理数が50000を超えました!


並列実行イベントの中身をこうして、条件を満たしてやりました。

■ループ開始
|■
◇ループここまで◇◇

1フレームあたりの処理数が50000を超えました!


自動実行イベントの中身をこうして、条件を満たしてやりました。



1フレームあたりの処理数が50000を超えました!


って、出ますよね?

ですが、
並列実行イベントの中身をこうして、条件を満たしてやりました。




これだと、エラーは出ません。

なぜかと言うと、並列実行イベントは、イベントの終わりまで行くと自動的に1フレームのウェイトが入るようになっているからです。自動実行イベントは、イベントの終わりまで来ても条件を満たす限りウェイトを挟まずに繰り返すので、エラーが発生するのです。
始めのころは、誰でも処理数50000回エラーにぶち当たります。そのうち仕様を理解してきて並列イベントなんかも使うようになると、処理数50000回エラーが出ないように、最後に1フレームのウェイトを入れる人がいるのではないでしょうか? これをやると、結果として2フレームのウェイトが入ってしまいます。問題が起こらなければ、それでもいいんですけどね。


次に、場所移動と並列イベントの関係について。

場所移動で主人公がマップを移動すると、EOFコマンドまで処理を終了した時点で、並列実行イベントは処理を中断します。
そして、条件を満たしていれば、イベントの頭から処理を再開します。
例えば、こういう並列イベントがあったとします。
■条件分岐(変数): 【1】主人公のX座標(マップ)が3と同じ
◇分岐: 【1】 [ 主人公のX座標(マップ)が3と同じ ]の場合↓
|■条件分岐(変数): 【1】主人公のY座標(マップ)が9と同じ
| ◇分岐: 【1】 [ 主人公のY座標(マップ)が9と同じ ]の場合↓
||■色調変更: R0 G0 B0 / 10フレーム
||■ウェイト:10 フレーム
||■場所移動:主人公 ▲マップID1[サンプルマップA] X:0 Y:0
||■ウェイト:10 フレーム
||■色調変更: R100 G100 B100 / 10フレーム
||■ウェイト:10 フレーム
||■
|◇分岐終了◇◇
|■
◇分岐終了◇◇


主人公がマップの地点(3,9)に来たらマップ1の(0, 0)に移動するイベントですが、まぁ、そんなのプレイヤー接触で起動するマップイベントで作ればいいじゃないかという突っ込みは置いといて。
このイベント、失敗します。必ず。
なぜかと言うと、上記の通りなら、8行目のウェイトまで来た時点でイベント処理が中断され頭から再開しますが、位置(0, 0)では条件を満たさないので、色調が元に戻らない――ずっと画面が真っ暗、ということになるからです。試してみてください。

なぜこんな仕様なのかは良く分かりません。ですが、これはこれで色々と便利な点があります。
マップを移動するたびにパラメーターを初期化したい状況、というものがあります。そういう時は、こうすればいいのです。
▼ ここに処理内容を入れる
■ループ開始
|■ウェイト:999999 フレーム
|■
◇ループここまで◇◇

ウェイトは別に1フレームでも100フレームでも変わりない気がします。どちらが早いのかは定かではありません。

バグなのかも知れないとも思いますが、私はこの仕様をフル活用しているので、今更修正されたらそれはそれで困ります(笑) なので、とりあえず、場所移動での並列イベント中断によるバグを避けるため、なるべくマップ間移動は主実行イベントを使用するようにしましょう。

もう一つ、場所移動と並列実行イベントについては、妙な仕様があります。
場所移動直後には、並列実行イベントだけ1回多く実行される、というものです。ゲーム開始直後、ロード直後も同様です。
先ほどの例で言うと、こうなります。
マップイベント1

マップイベント8

コモンイベント10

コモンイベント20

マップイベント1

マップイベント8

コモンイベント10

コモンイベント20

マップイベント5

始めの1回は画面切り替えの前に行われます。従って、マップ移動直後に行いたい処理があるイベントに関してはここを使って、逆に必要のないイベントに関しては1フレームのウェイトを挟んでしまえばいいでしょう。
スポンサーサイト
コメント
この記事へのコメント
コメントを投稿する
URL:
Comment:
Pass:
秘密: 管理者にだけ表示を許可する
 
トラックバック
この記事のトラックバックURL
この記事へのトラックバック
copyright © 2005 魔術師の巣窟(仮) all rights reserved.
Powered by FC2ブログ.
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。