アプリ版:「スタンプのみでお礼する」機能のリリースについて

Actionscriptで、配列dのleftからrightまでの間のデータをクイックソートする再帰のプログラムの中で、
function quick(d,left, right){
if(left>=right){
return;
}
var p = d[d];
disp.text = "基準値は"+p;
・・・・・・
・・・・
}
でC言語のように処理が行なわれる度にムービー上に基準値を順番に出力させたいのですが、最後の処理の時の基準値が出力されるだけで、初めの時の基準値、1回目から最後までの途中経過の基準値を出力させる事ができません。
どうしたらいいのでしょうか? よろしくお願いします。

A 回答 (3件)

trace アクションのように履歴のような形式で表示するのではなく、値の部分だけがアニメーションするといいますか、値が変遷していく様子を表示したいとのことでしょうか?


これですと、少々面倒な話になります。


Flash にはフレームという考え方があります。
タイムラインにフレームがたくさん並んでいて、再生ヘッドが動くたびにそのフレームが表示されます。
メインのタイムラインとは別に、ムービークリップもタイムラインとフレームを持っていて、ムービークリップがステージに存在している間は、ムービークリップは自分のタイムラインに従って自分のフレームを再生し続けます。
絵が動いて見えるのは、フレームが再生されて次々に絵が切り替わっている、つまりパラパラマンガと同じ原理によるものなのです。

for ループは1フレーム内で繰り返し処理を行うものです。
#1でご紹介しました for ループで配列変数の内容を表示するスクリプトでは、1フレームのうちに表示内容が決定され、テキストフィールドにまとめて出力されるため、1行ずつ順に表示されていくといった動きは付きません。
1行ずつ順に表示されるようにしたいのであれば、1フレームに1度、”基準値は○”という出力を送るようにしなければなりません。

もっとも、フレームレートが 12 fps ですと、これは1秒間に 12 フレーム再生する速さということです。
1フレームごとに1度、つまり 1 / 12 秒ごとに1度出力したのでは、速すぎて順に表示されているようには見えないかもしれません。
分かりやすく更新するなら、別途カウントを取って、例えば6フレームに1度出力する、といった調整も必要になるかと思います。

---------------------------------------------------

1フレーム内でまとめてではなく一定間隔で表示されていくようにするには、ムービークリップが持っている enterFrame というイベントを利用する方法があります。
enterFrame イベントは、ムービークリップがステージに存在する限り、フレームレート分の1秒ごとに発生しています。
つまり、enterFrame イベント発生時に指定の処理をさせるように定義すると、フレームレート分の1秒ごとにその処理が自動的に行われます。

例えば、#1の例を

(↓各行頭に全角のスペースが入っています。コピーする際はご注意ください)


 //配列変数を用意
 d = new Array( 0 , 5 , 10 , 15 , 20 );

 //配列変数の参照位置を保持
 tbl_ref = 0;

 //出力間隔を調整するウェイトカウンタ
 out_wait = 0;


 disp.text = "";


 /*数フレームに1度、テキストフィールドに出力*/ 
 _root.onEnterFrame = function()
 {
  //6フレームに1度、配列変数の中身をダイナミックテキストに出力
  out_wait++;
  if( out_wait >= 6 )
  {
   //テキストフィールドに表示
   disp.text = "基準値は" + d[ tbl_ref ];

   //配列変数の参照位置を1つ進める
   tbl_ref++;

   //配列変数が尽きたら、この処理を終了する
   if( tbl_ref >= d.length )
   {
    delete _root.onEnterFrame;
   }

   //出力ウェイトをリセット
   out_wait = 0;
  }
 };


このように変えると、6フレームに1度、テキストフィールドに出力が行われます。フレームレートが 12 fps なら、6 / 12 = 1 / 2 で、約 0.5 秒間隔での出力となります。
テキストは常に「基準値は○」という形で更新しているので、値の部分だけが更新されていくように見えます。

_root.onEnterFrame = function 内の処理はフレームレート分の1秒ごとに呼び出されます。
つまり、フレームレートが 12 fps の時は 1 / 12 秒ごとに呼び出されることになります。
1/12 秒ごとに出力すると表示が速すぎてしまいますので、out_wait という変数でカウントを取り、表示する間隔を調整しています。


Flash ではムービー自体もムービークリップとして扱います。
通常は _root という名前で識別します。
ムービー自体はムービーが再生されている間はステージから消えることがありませんから、_root の enterFrame イベントはムービーが再生されている限り、フレームレート分の1秒ごとに発生し続けます。

_root.onEnterFrame = function ・・・は、_root で enterFrame イベントが発生する度に以下の処理を呼び出せ、という定義をするものです。
onEnterFrame はイベントハンドラと呼ばれるもので、一種の変数のようなものです。
C言語の、関数を指すポインタに似ていると言えば、分かりやすいでしょうか。
ただ、1度定義しておくと、指定のイベントが発生する度に指定の処理(関数)が自動的に呼び出される点が独特です。
上記の例では、配列変数の中身が尽きた後は呼び出す必要がないので、delete というアクションを使って onEnterFrame ごと削除し、以降は呼び出されないようにしています。

---------------------------------------------------

長くなりましたが、結論をいいますと。
1フレーム内で for ループなどを利用して出力させる限りは、trace アクションのように

 基準値は○
 基準値は△
 基準値は□
  :

という形式で表示するか、最終的の値だけを「基準値は□」という形でしか表示できません。
「基準値は○」の○の部分だけが次第に更新されていく様子を見せるには、○の値を求める処理をムービークリップの enterFrame イベントを使って数フレームに1度だけ実行し、フレームごとに更新していかないと、徐々に変遷していくようには見えないということです。
    • good
    • 0
この回答へのお礼

とても丁寧に解説してくださりありがとうございます。面倒なことをやろうと思ってしまっていた感じですね。すみません。
1人で行き詰って困っていたので、大変感謝しています。本当にありがとうございました。明日早速、やってみます。本当にありがとうございます。

お礼日時:2005/11/13 20:51

> 基準値が変わるごとに表示される値を書き換えたいので、値が次の処理になったら値が書き換わるようにしたいのですが、




この部分が、よく分からないのですが・・・
trace アクションのように、

 基準値は○
 基準値は△
 基準値は□
  :

といった具合にテキストフィールドに表示させたい、とのことでよろしいでしょうか?


#1でも書きました通り、text プロパティとは文字列を保持している、ただの変数です。
そして、テキストフィールド(今回の例では disp )がステージに存在している間は常に text プロパティも存在しており、いつでも自由に参照して値を書き換えることができます。
#1では、配列変数の中身をテキストフィールドに出力する例として for ループの中で使っていますけれど、別にループやある関数内などの特定の場所で1回で書き換えないと、text プロパティがメモリ上からクリアされて使用できなくなるといったことではありません。

つまり、値を出力したい時に、随時

 disp.text += "基準値は" + p + "\n";

とすれば、前の表示に新しい内容が連結されて表示されます。
前の内容を消していいのであれば、

 disp.text = p;

このように = 演算子で新しい文字列(数値の入った変数を代入すると、文字列として連結されます)を代入すればいいだけです。
表示をまっさらな状態にしたいなら

 disp.text = "";

と、空文を代入すると、文字列がクリアされ、テキストフィールドは全くの空白になります。


要するに、text プロパティを書き換えるタイミングの問題だと思います。
今回の件ですと、基準値を求める関数内や、その関数から値を取得した時などが目安でしょうか。

この回答への補足

基準値は○です。と初め出力されて、次の処理が呼び出されたら、文の表示はそのままで、前の○の値を消して、○の値だけを書き換えるということがしたいのですが、そうなると、基準値を求める関数内で、
disp.text = p;
を行なえばよいということでしょうか?
初めそう思い、
function quick(d, left, right) {
if (left>=right) {
return;
}
trace("左は"+(left+1));
trace("右は"+(right+1));
var a = (left+right)/2;
//基準値はとりあえず配列の中心の値で
var b = Math.floor(a);
//trace(b);
var p = d[b];
      ***

***部分にdisp.text = p; をやってみたのですが、最後の基準値だけが出力され、最初の値から最後の基準値へと処理されるたびに出力が書き換わって表示されなかったのです。
プログラムに弱くてすぐに理解できなく申し訳ありません。

補足日時:2005/11/12 11:43
    • good
    • 0

TextField クラスの text プロパティの正体は、文字列を保持する、ただの変数に過ぎません。


ですから、例えば

(↓各行頭に全角のスペースが入っています。コピーする際はご注意ください)


 //配列変数を用意
 d = new Array( 0 , 5 , 10 , 15 , 20 );

 //配列変数の中身をダイナミックテキストに表示
 disp.text = "";
 for( i = 0 ; i < d.length ; i++ )
 {
  p = d[ i ];

  disp.text += p + "\n";
 }


このように text プロパティに数値や文字列を次々に連結していくと、trace アクションと同様に表示できます。
( ActionScript では、文字列も + 演算子で連結できます)
disp.text = "・・・"; とした時は text プロパティに代入するという意味になりますので、先に入っていた内容に新しい文字列が上書きされて、最後に代入した文字列だけが出力されます。

trace アクションは1回の出力ごとに自動で改行してくれるサービスがありますが、text プロパティを操作した時は改行は入りません。改行は随時、自分で追加してください。
このあたりは、C言語をご存知でしたら、何となくご理解いただけると思います。


なお、テキストフィールドに何も表示されていない時、text プロパティには改行コードが入っているようで、そのまま文字列を連結すると最初の行が勝手に改行されて空いてしまいます。
テキストフィールドに出力する前に

 disp.text = "";

として text プロパティを全くの空っぽにしておくと、この1行は空かなくなります。

この回答への補足

出力は出来るようになりました。ありがとうございます。
ですが、基準値が変わるごとに表示される値を書き換えたいので、値が次の処理になったら値が書き換わるようにしたいのですが、その場合はどうしたらいいのでしょうか?

補足日時:2005/11/11 21:52
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!