p2k8 blog mini

イラストを中心にその他色々紹介**天体写真はこちらに移転しました→https://p2k8-net.fc2.net/

【AS】RPGメッセージシステム

【AS】RPGメッセージシステム
お約束の通り、プログラミングネタの解説にチャンレンジしてみました。
まずはゼロから作る自作RPGの解説です。
間違っている部分、おかしな所もあるかもしれませんが、FLASHRPGを作る参考になれば幸いです。
苦戦のFLASH RPGプログラミング。本日はRPGのメッセージ部分を作っていました。
後は変数を読み込むだけでインスタンスを使いまわせるようにしたのがポイントです。


Scriptのおおまかな構成

以下の図でこのプログラムの仕組みを何となく理解してください。
イメージ 1
_rootは最上部のタイムライン。その中に、戦闘シーンのインスタンス(パスは"_root.fight.")が
常駐しています。フィールド操作の時も戦闘シーンは消えずに残っています。味方キャラと敵キャラ、
そしてボックス部分を表示していないだけです。この戦闘シーンのインスタンスを消してしまうと、
味方キャラの現在HP値、ステータスなども失われてしまいますし、次回エンカウントまでの情報も
非表示な状態の戦闘シーンが担っています。

画面のタイムラインは、_root.field のインスタンス内の様子です。上から二段目のレイヤーがAction Script記述専用フレームです。Scriptを記述しているフレームには「a」と表示されていますね
画面は「階段hit」のレイヤーの4フレーム目のインスタンス名「speak_mc」を選択している状態です。ゲームの始まりのフロアーが1フレームなので、これは「4面」(切り替わって4番目の画面)ということになります。
まだプログラムを開発しているうちはファミコン版FF3をベースに作っていっているので、下の画面はちょうどランドタートルのボス階部分です。

この画面で赤塗りしているインスタンスですが、ボス戦闘が終了した直後に話しかけるクリスタルにあたります。
フルパスは「_root.field.speak_mc」にあたります。


さて、ここからメッセージを発動して正常に表示、そしてボタン操作を行えるようにする方法が今回のテーマとなります。

まずは、ここに話しかけてメッセージを発動するまでの手順。

1. インスタンス接触した状態で
2. ENTERキーを押すと(または▼印を直接クリック)
3. 操作キャラの方向操作は無効となる(方向キーの無効化)。
4. 画面にメッセージが現れる
5. 表示するメッセージのページ数 (変数"nowitem";) が複数の場合、ENTERキーを押すと次のページに切り替わるが、
6. メッセージが下から上へスクロールして入れ替わらなければならない(スクロール時に文字が青枠からはみ出してはならない)。
7. 最後のページを表示し終わってENTERを押すとメッセージが消え、キャラ操作の無効が解除される。


まず、1.の項目を実施するには、「hit.Test」のScriptを使用します。
これは、インスタンス同士の重なり合いを検出するScriptです。
ベクトル同士がちょっとでも重なったらTrueとなります。

上の条件には、「インスタンス接触した状態でENTERを押すと方向キーの無効化」とありますが、
これでは操作キャラはENTERを押さなければインスタンスに重なってしまえます。
宝箱や障害物など、本来インスタンスに重なってはならないのですが、ここではそこまで対応していませんので予めご了承を。

▼1枚目の画像の赤塗りインスタンスの内部のフレームです。

イメージ 2

「透明ラップ」レイヤー、フレーム番号1にある孫インスタンスに外側から記述している「onClipEvent(enterFrame)」で囲まれたif文。
この部分が、操作キャラが重なった場合に反応する部分に当たります。

onClipEvent (enterFrame) {
if (this.hitTest(_root.f_chara)) {
this.gotoAndStop("btn";)
//ここにキャラが接したら次のフレームへ。
//会話をスタート。
} else {
this.gotoAndStop(1);
//hitTestでFalse(重なっていない)場合は、ボタンを受け付けない1フレームへ。
}
}

onClipEvent (enterFrame)

enterFrame を使用すると、随時条件を調べるので、hit.Testで重なっているかどうかという
リアルタイムで判定する記述が可能となります。

もしこれをonClipEvent ('load')とすると、インスタンス同士が重なってもif文でTrueにならなくなりますので注意。


if (this.hitTest(_root.f_chara))

これは、このインスタンス(this.)が操作キャラ(パスは _root.f_chara)と重なっていたら、
という条件のif文です。つまり、操作キャラが「クリスタル」に接した瞬間にtrueとなります。
乗っかっている間もずっとtrue、抜け出したらfalseです。

で、インスタンスが重なっている場合に行う式

this.gotoAndStop("btn";)

このthis.とは、このインスタンスの内部(さらに下の階層)のことを示します。

イメージ 3

ジャンプ先「"btn"」は、上の図のフレーム番号2、赤いマークの付いているFLAGです。
画面に見えている通り、三角形のボタンインスタンスが現れました(実際には透明度0%にして隠します)。
このボタンインスタンスに記述するon()の文が、いよいよメッセージを発動させるScriptになります。

on (keyPress "<Enter>";) {
_parent.nextFrame();
//▲メッセージ開始。
}

_parent.nextFrame()


さて、_parent. とは、「上の階層を」というパスです。nextFrame(); は、次のフレームに送る、という意味。
そのため、上の階層が発動し、次のフレームを読み込みます。そこにはどう記述しているかというと…

_root.sento = 1;
//▲キャラ操作停止。
_root.mes_mc.gotoAndPlay("mes_multi";)
this.stop();
//ボタン操作がカブらぬよう、ここでstop。

_root.sento = 1

_root.にある変数「sento」。これは、戦闘判定です。0だと非戦闘(フィールド操作)、1だと戦闘シーン(バトル操作)。
先述の通り、このプログラムではフィールド画面の上からバトル画面を被せていますので、フィールド画面操作とバトル操作が連動しないようにするためです。
バトル操作中は、フィールドを動くキャラの十字キー操作を無効にする為にsent = 1としていますが、これを条件3 (操作キャラの方向操作は無効となる(方向キーの無効化))に利用したのです。
つまり、実際には戦闘シーンではないのだが、操作キャラの十字キー反応を無効にする為に、わざと戦闘状態と認識させるのです。
もちろん、メッセージが終わったら sent = 0 に戻して解除します。

_root.mes_mc.gotoAndPlay("mes_multi";)


次の文、これはというと、複数ページにわたるメッセージを発動させるという部分です。




(続く)

開始日: 2005/2/9(水)