p2k8 BLOG SKY

天文・自然の写真を中心にその他色々紹介*

アプリFLASH

[ リスト | 詳細 ]

記事検索
検索

全2ページ

[1] [2]

[ 次のページ ]

RPGで複数にわたるメッセージを連続表示するAction Scriptの処理流れです。興味のない方は無視して下さい。文中の変な顔文字はWiki文法の仕業ですので括弧閉じとセミコロンに置き換えて読んで下さい。

高校時代に習ったフローチャートを思い出して書きましたが、いかんせん8年ぶり。作図の自信はありませんがとりあえずザッと書いてみました。2つの変数を読み込んでメッセージのページ送りする処理の流れをご覧下さい。

変数一覧

/*【戦闘シーンの変数代用】
_root.fight.now・・・・・・・初期のメッセージ番号 (ここでは 'now' とする)
_root.fight.pg_su・・・・・・・メッセージを表示するページ数 ('pg_su' 〃)
_root.fight.cnt・・・・・・・(変動型)現在のメッセージ番号 ('cnt' 〃)
*/

フローチャート

イメージ 1

ここからは、フローチャート各部ごとの詳細な説明とScriptです。

【1】 メッセージシステムの立ち上げ

前編で紹介した、hit.Testで会話する物体(宝箱、村人など)に触れ、
その状態のままEnterキーを押すことでメッセージシステムが発動する。

_root.sento = 1;
//▲キャラ操作停止。戦闘判定を利用してキャラを動かせなくしておく。
_root.mes_mc.gotoAndPlay("mes_multi";);
//▲メッセージシステム発動。
this.stop();


【2】 変数入力

会話インスタンスに外側から記述しています。
入力する変数は now と pg_su の2つだけです。

onClipEvent (load) {
//メッセージ欄のインスタンスで使用する初期ページ番号「now」を指定。
_root.fight.now = 4;
//ページ4番の変数。
_root.fight.pg_su = 4;
//ページ表示数は4。
}


ページ番号4番から、4ページを表示。
つまり、4〜7ページを表示する、ということ。


【3】 カウンタの初期化


_root.fight.cnt = _root.fight.now;
this.play();

変数 now で、予め始まりの数字が指定されていますので、
変数 cnt の初期値は now と同じにします。
4を入力していますので、cnt と now には4が入ります。


【4】 メッセージの表示


onClipEvent (load) {
this.gotoAndStop(_root.fight.cnt);
//▲ここではメッセージ表示用にcntを使用している。
//メッセージ番号へ飛んで該当メッセージ(複数行)を表示する。
}

ムービーシンボルの単一フレーム表示を利用して目的のフレームを静止表示させます。



【5】 メッセージのスクロール


ここでは、プレイヤーがEnterキーを押すことで、メッセージが次のページへ移り変わる部分です。
以下のように、▼印のボタンを設けて、プレイヤー側からの入力を待ちます。

イメージ 2

ボタンのon();内には、Enterキーを押しても、直接マウスで▼をクリックしても良いようにしています。
いずれかが入力されたら this.play(); ですので、このフレームのASレイヤーにはStop();をかけています。



【6】【7】 判定と加算


表示させるページ数に達したかどうかの判定。もし達した(true)ならば、
メッセージ表示を終了させます。達していない場合は、elseの中で cnt を加算処理します。

if (_root.fight.now+_root.fight.pg_su-1<=_root.fight.cnt) {
//▲現在のページ番号(cnt)が表示し終わるページ番号(now+pg_su-1)を超えたならば。
this.gotoAndPlay("mes_close";);
} else {
_root.fight.cnt++;
//ページ番号を加算。
}


【8】 メッセージスクロール

先ほどのif文でelseとなった場合にこの処理が行われます。
そのため、先ほどelseのカッコ内でページ番号が1つ加算されたので、メッセージ表示インスタンスは
一つ先のページに切り替わってしまったはずです。それでもそれは一つ前のフレームなので、時間軸は
なく、このフレームで対応すればよいのです。ここでは、表示しているメッセージをcnt-1番目のページに
切り替えます。先ほどまで表示していたメッセージ表示インスタンスに外側から記述する文です。


onClipEvent (load) {
this.gotoAndStop(_root.fight.cnt-1);
}


このインスタンスをモーショントゥイーンで上へスクロールさせます。
青枠の外側にはみ出してしまうので、青枠に収まるように四角いマスクを利用します。
そして、同じスピード(動き量)で、下から同じインスタンス(onClipEventを記述)が上がってくるようにします。
そのインスタンスが次のページを担うので、こう記述します。


onClipEvent (load) {
this.gotoAndStop(_root.fight.cnt);
}


お判りの通り、gotoAndStopをcnt-1ではなく、cntにして、1つ先のページの読み込ませています。
このスクロールが完了したフレームに記述したScriptから、そのまま判定へ戻らせます。

this.gotoAndStop("mes_stop";);
//mes_stopは判定部分のフレーム名。ループ先で停止。



【9】 初期化

メッセージ表示システムで使用した変数を最後に初期化しておきます。
これらの変数は戦闘シーンでも使用するし、変数が残ったままだとバグとなる恐れがあるので、
念の為に初期化します。無難な0で。

_root.fight.cnt = 0;
_root.fight.pg_su = 0;
_root.fight.now = 0;
//▲【初期化】使い捨てではありません。使った後は元あった状態に戻しましょう。
_root.sento = 0;
//▲キャラ操作可能に復帰。
_root.field.speak_mc.gotoAndStop("after";);
//▲このタイムラインを発動させた元(speak_mc)に、時間軸を受け渡す。
this.gotoAndStop(1);

メッセージボックスのクローズは、バトンタッチ先のspeak_mc側から行うようにしています。
これで、2つの変数(表示開始番号と表示ページ数)を読み込むだけで任意のメッセージ表示が
行えるシステムが完成しました。もちろん、別途メッセージをフレームごとに記述した「メッセージ表示インスタンス」が必要です。
−−−

この記事に

開く コメント(1)

お約束の通り、プログラミングネタの解説にチャンレンジしてみました。
まずはゼロから作る自作RPGの解説です。
間違っている部分、おかしな所もあるかもしれませんが、FLASHでRPGを作る参考になれば幸いです。
苦戦の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";)


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




(続く)

この記事に

開く コメント(0)

3月4日朝、九州地方でのみ見られた「月没帯月食」。このあと月は皆既月食になるのですが、九州では欠けながら沈んでいきました。1秒おきのインターバル撮影で捉えたものを早回ししています。夜が明けて空が明るくなりながら、月食中の月が山へと沈んでいく様子をご覧下さい。

以下リンクをクリックするとYahooビデオキャストに移動して映像をご覧頂けます。


撮影日時 : 2007年3月4日06時20分頃〜06時35分頃
カメラ : ソニー DCR-HC90

デジタル一眼レフカメラ+望遠鏡で撮影した部分月食の写真は以下記事に掲載しています。
部分月食【3月4日撮影】part2 - 2007年3月4日投稿
熊本での部分月食【3月4日撮影】 - 2007年3月4日投稿


ところで、動画といえばYouTubeには天文現象ネタもあります。探ってみるとオーストラリアやニュージーランド方面での、1月の化け物彗星の映像もたくさんありましたよ。
−−−−−−−

この記事に

開く コメント(0)

敵遭遇カウントダウン方式

今日の話題はFLASH作る人にしか判らないかもしれませんが、RPGフラッシュのActionScriptです。これまではずっと戦闘シーンのプログラミングをしていましたが、本日新たにフィールドシーンを歩いていてランダムでモンスター出現、というエンカウントの流れを自分の腕で組み込むことに成功! パブリッシュしてうまくいった時の達成感は大きかったです。

ゲーム全体のAction Scriptの仕組みを全て解説するとなるととても複雑になるので、ここではエンカウントまでの残り歩数の変数を算出するif文だけ載せておきます。

まず、グローバル変数として1〜99までのランダム値を代入する「mainransu」を1ターンの始まりに算出して、ターン毎に変わるように仕組んでおきます。これは、攻撃や防御の数値のターンごとの揺らぎとしても使っています。

さらに戦闘終了時に読み込むフレームにて、以下のようなif文によるエンカウント率の計算を行います。変数「encmode」はエンカウントまでの残り歩数量のパターン、つまり出現頻度グループ分けです(1〜6)。7割が下限値20、上限値44のエンカウントの歩数になりますが、7%の確率で起こる「超長」ですと下限値105歩、上限値120歩とかなりの範囲を歩けます。最初から3〜120の間でランダムを取ると、均一に散らばって面白みがありません。歩数のランダム範囲にバラつきを発生させるために「6つのグループ」と「グループの範囲内での乱数」という二重構造にしているのです。


if (_global.mainransu<=70) {
encmode = 3;
//【確率70%】 出現頻度3/5(普通)。
encmas = Math.floor((Math.random()*10)*2.2)+20;
//【範囲20〜44】 *2.2は、1〜10 の乱数を 2〜22 の間に変換するため。末尾の+20は計算結果が下限22、上限42になるように。
} else if (_global.mainransu<=80) {
encmode = 4;
//【確率10%】 出現頻度4/5(長い)。
encmas = Math.floor((Math.random()*10)*2)+60;
//【範囲60〜80】 *2は 2-20 の間に変換するため。+60は 60-80 の間にするため。
} else if (_global.mainransu<=81) {
encmode = 6;
//【確率1%】 出現頻度「スペシャルランダム」(1〜271。適用範囲広い)。
encmas = Math.floor((Math.random()*10)*30)-29;
//【範囲1〜271(30増分)】 *30は 30-300 の間に変換するため。-29は ランダムで0.1出た場合に30となり、これを1にしたいから(1マス出現。最終的に1/1000の確率)。
} else if (_global.mainransu<=83) {
encmode = 1;
//【確率2%】 出現頻度1/5(超短)。
encmas = Math.floor((Math.random()*10)*0.5)+3;
//【範囲3〜8】
} else if (_global.mainransu<=93) {
encmode = 2;
//【確率10%】 出現頻度2/5(短い)。
encmas = Math.floor((Math.random()*10)*0.9)+10;
//【範囲10〜19】
} else {
encmode = 5;
//【確率7%】 出現頻度5/5(超長)。
encmas = Math.floor((Math.random()*10)*1.5)+105;
//【範囲105〜120】
}

戦闘終了から次のエンカウントまでの残り歩数

上のif文を流すと、encmode(頻度グループ)が1〜6、encmas(実歩数)が3〜120の範囲で算出されます。

1:「超短」: 2% 3〜8 歩
2:「短い」:10% 10〜19 歩
3:「普通」:70% 20〜42 歩
4:「長い」:10% 60〜80 歩
5:「超長」:7% 105〜120 歩
6:「スペシャル」: 1% 1〜271

encmodeが6になる「スペシャル」は確率が1%ですが、もっと確率を上げても面白そうです。ちなみに1歩だけでエンカウントする確率は1/100×1/10で1/1000となります。

変数「encmas」はエンカウントまでの残り歩数になります。キャラが1歩歩くアクションはモーショントゥイーンではなくAS制御(if文によるループ処理)で行っています。条件を満たしてif文を脱出する際に一歩進むのも完了するので、そのタイミングでエンカウントまでの残り歩数(encmas)を減算 (encmas--;) します。さらに一歩歩くアクションの一番最初に読み込むフレームでencmasが0になったかをif文でで検査して、trueであればgotoAndPlay(〜)で戦闘インスタンスをスタートさせます。これでランダムなエンカウントまでの歩数を経て、戦闘スタートとなります。


−−−−−−
p2k6◇MX2004

この記事に

開く コメント(0)

TOP FLASH 更新

さて、早いものでもう6月です。そんなわけで私のサイトのTOP FLASHも梅雨バージョンに変えました。
これまでの雪と違って雨のアニメーションは早い動きの為CPUを消費し、少しコマ落ちするのとブラウザのスクロールがスムーズにいかない、などの影響が出てしまいました。そこで、FLASHの画質を中にするScript _quality = "MEDIUM"; をROOTに記述しました。FLASHはデフォルトでは画質設定が高なんですよ。


隠しコンテンツの発見方法

そんな、雨が降りしきる「プレオリ」TOP FLASHですが、隠しコンテンツを埋め込んでみました。FLASH内のテレビを操作することで隠しコンテンツを表示することが出来ますので、興味がある方はやってみて下さい。
まず右側のどれかのアイコンをクリックし、テレビに接近します。次に、テレビ左側の出っ張りをクリックしてチャンネルを表示させます。その後、素早く電源ボタンを繰り返し押します。案内キャラに「テレビを消すな!」と突っ込まれますが、構わず連打してください。60になると、テレビ画面に隠しチャンネルが表示されます。


−−−−−−−−−−
hugflash使用禁止p2k5

この記事に

開く コメント(0)

全2ページ

[1] [2]

[ 次のページ ]


.


みんなの更新記事