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

以前にも質問させていただいたのですが、非同期処理であるという事にも手こずって、どうしても解決できなく行き詰ってしまっています。
スクリプトの途中だけの部分ですが
再帰の中で
// ここで実際に○を移動させる
Pofmaru1(l);
Pofmaru2(r);

再帰の外で
// maru1を移動させる関数Pofmaru1
function Pofmaru1(l) {
if (l == 1) {
gotoAndPlay("maru1",2);
}else if (l == 2) {
・・・・・・

// maru2を移動させる関数Pofmaru2
function Pofmaru2(r) {
if (r == 1) {
gotoAndPlay("maru2",2);
}else if (r == 2) {
........
と書いてレイヤーmaru1とレイヤーmaru2の指定フレームへ移動しムービー再生後にソートプログラムへ戻り次の処理へ移るようにしたいのですがwhile文でflagを使い処理を待たせることを考えたのですがflashは非同期であるためflagの値のやり取りが上手く行きませんでした。
タイミング処理においてコールバック関数というものがあるという所に行き着いたのですがプログラムがあまり得意でなくイマイチ理解することができません・・。
flash mxで処理を待機させておくといったことを実現するにはどのように対処するといいのでしょうか?
何かアドバイスください。お願いします。

A 回答 (3件)

#1&2 です。



>> if文通りに処理されなく、
>> タイムラインに書かれた順番で
>> ムービーが再生されてしまいました・・・・。
>> なぜそうなってしまったのか、わからないのですが・・・・?

と言われましても,こちらも FLAファイル が見えない以上,
どういう状況かが全くわからないので,わかりませぬぅ…
困った。
(FLAファイル を見てもわからない可能性は大ですが。)


とりあえず,
第一の最低条件は,
Flash は 本来アニメーションソフトですから,
メインムービー( _root )も,ムービークリップも,
stop(); など止めるスクリプト何処かに書いておかなければならないということです。
何かそれらしいことを何処かに書かないと,
それぞれのタイムラインは,表示と同時に再生しはじまめす。
(フレームが 1フレーム しかないときだけは話が別です。)


次の最低条件は,オブジェクトのあるなしです。
例えば,100フレーム のメインムービーがあったとして,
50フレーム目から maru1 というムービークリップが登場したとします。
メインムービーの 1フレーム目で,

maru1.gotoAndPlay(2);

と書いても,
1フレーム目では,まだ maru1 というオブジェクトは存在していませんから,に命令は届きません。
仮に(超仮にで,実際はないことです。),
maru1 が gotoAndPlay(2); したとしても,50フレーム目まで行かないとそれは確認できませんから,
確認した時には,maru1 は,どこか別のフレームに移動しているでしょう。

ここまでが最低条件で,
ここまでではたいていの方はミスしませんし,
ミスしてもだいたいすぐに気づきます。


多くの方が,最もミスに気づかず詰まるポイントはパス(階層(住所))です。
変数や関数には,それらが存在するパス(階層(住所))があります。
パスがあるからこそ,分類や場合分けができるので大変便利なのですが,
このパスの問題で詰まる方が多いようです。
「Flashで,思うように動かないのはパスが原因だと思え。」
と,よく言われます。
パスとは,ムービークリップ間でのお互いの住所と思って良いと思います。
実は,メインムービー( _root )も1つのムービークリップです。
#2では,階層は1つしか増やしていませんが,実は無数に階層は増やせます。
簡単に言うと,ムービークリップの入れ子はいくらでもできるということです。
(当然限度はありますが,先に人間の階層管理や記憶の方が限界が来るでしょう。)
「F-site ターゲットパス」
参考URL: http://f-site.org/articles/2002/01/26153958.html


こちらの都合したものばかりで,大変申し訳ありませんが,
#2 の 少しだけ延長を作りました。
単なる簡単な例です。

メインムービーは相変わらず,

 □ レイヤー 筆・・|●|

のままで,その上にレイヤーを1つ追加します。
(追加しなくても良いと言えば良いのですが
 スクリプトを書くレイヤーは分けた方が
 都合が良い場合が多いです。)


 □ レイヤー 筆・・|○|
 □ レイヤー 筆・・|●|

上の空白キーフレームにスクリプトを書きます。

----------------------------------
// maru1を移動させる関数Pofmaru1
function Pofmaru1(l) {
// l が 1 だったら maru1 を フレーム2 へ
if (l == 1) {
_root.maru1.gotoAndPlay(2);
// l が 2 だったら maru1 を フレーム15 へ
} else if (l == 2) {
_root.maru1.gotoAndPlay(15);
}
}

// maru2を移動させる関数Pofmaru2
function Pofmaru2(r) {
// r が 1 だったら maru2 を フレーム2 へ
if (r == 1) {
_root.maru2.gotoAndPlay(2);
// r が 2 だったら maru2 を フレーム20 へ
} else if (r == 2) {
_root.maru2.gotoAndPlay(20);
}
}
----------------------------------

これは最初に, Pofmaru1,Pofmaru2 を定義しているだけです。


そしてインスタンス名 maru1 の フレーム1 のスクリプトには
---------------------
stop();
---------------------
と書きます。
上記,「第一の最低条件」で書いたことです。
これで, maru1 は勝手に進み出しません。

そして,
インスタンス名 maru1 の 最終フレーム のスクリプトは
----------------------------------
stop();
r = Math.floor(Math.random()*2)+1;
_root.Pofmaru2(r);
----------------------------------
のように書きかえます。

変数r にランダムな 1 か 2 を入れ,
その r を持って, _root の Pofmaru2 という関数を実行する。
ということです。
Pofmaru1,Pofmaru2 は _global な関数で定義していないのでここにもパスが必要です。
http://www.fumiononaka.com/TechNotes/Flash/FN020 …
また,ここの変数r は, _root の 変数r ではありません。別物の r です。
メインムービーの 変数r をあえてパス付きで書くと,
_root.r です。
このムービークリップの r はパス付きで書くと,
_root.maru1.r です。
この,_root.maru1.r を持って, _root の Pofmaru2 を実行します。


そしてインスタンス名 maru2 の フレーム1 のスクリプトにも
---------------------
stop();
---------------------
と書きます。

そして,
インスタンス名 maru2 の 最終フレーム のスクリプトは
----------------------------------
stop();
l = Math.floor(Math.random()*2)+1;
_root.Pofmaru1(l);
----------------------------------
のように書きかえます。

これで,パブリッシュしても,
関数を定義しただけで,maru1 も maru2 もストップしたままなので,
何にも起こりません。
最初の1歩を進ませるものが必要です。

そこで,メインムービーの フレーム1 にボタンを作ります。
何でも良いので塗りで ■ を書いて,ボタンシンボルに変換します。
そして,そのボタンシンボルには以下のように書きます。

--------------------------
on (release) {
A = 1;
Pofmaru1(A);
}
--------------------------

回りくどいスクリプトですが,これで,
Pofmaru1(1); が実行されます。
つまり,if の分岐により
_root.maru1.gotoAndPlay(2); が実行されるということです。

ボタンシンボルは階層を持ちません。
_root にあるボタンなので,Pofmaru1(); で _root の Pofmaru1(); が実行されます。
これが,ムービークリップとの大きな違いです。
とうぜん,
_root.Pofmaru1(); でも良いです。
URLのパスと同じで,絶対パスでも相対パスでも良いです。
変数 A にしたのは特に意味はありません。

それと,ボタンをわざわざ用意したのは,階層の説明をするためでもありますが,
フレーム1 に書いた function の下に,

Pofmaru1(1);

を付け足しても動かなかったからです。
完全にオブジェクト,つまり maru1 と maru2 が認識される前に
Pofmaru1(1); が実行されるからだと思います。
メインムービーのタイムラインを 2フレーム にして,
フレーム2 に,

stop();
Pofmaru1(1);

と書けば,Pofmaru1(1); は動作しました。

1行目に stop(); と書いたのは,
ムービーがループされるとまずいからです。
メインムービーが2フレームだけでできていたとすると,
stop(); を書かないと フレーム1 と フレーム2 を行ったり来たりしてしまいます。
すると,フレーム2 に戻るたびに Pofmaru1(1); が実行されるので,
_root.maru1.gotoAndPlay(2); がしょっちゅう実行されます。
つまり,maru1 が 3フレーム目に進もうにも,すぐに 2フレーム目に戻されてしまいます。

とにかく,Flash では時間軸で次々何かが起こるので(起こせるようにしてあるので),その辺の慣れや推測も必要です。

というか,最初から普通のアニメーションを作っていると,別に何でもないことなのですが,
いきなり難しいことをしようとすると,妙なところで詰まってしまうと思います。
ちょっとずつ順を追ってするほうが早道だと思いますよ。

いつか書かれていた,
配列の順序を並び替えて,それによって l や r を得て…
というのにはほど遠いとは思いますが,
これがなんとか回答できる限度です。

この回答への補足

そうですよね、いきなり難しいことをしようとしてしまっている事に結構問題がありますね。
>Flash では時間軸で次々何かが起こるので(起こせる>ようにしてあるので),その辺の慣れや推測も必要で>す。
ここの点についてもまだ慣れてなく推測が出来ていないのだと感じました。
sassakunさんが丁寧に解説してくださった例を明日、作ってみて動きみようと思います。
いつも丁寧に教えてくださりありがとうございます。聞ける人がまわりに居なく行き詰ってしまったりしているのでとても感謝しております。

補足日時:2005/12/21 20:06
    • good
    • 0

#1です。


結論から言うと,最初からちゃんと説明したサイトはないです。
何度もいろいろ見ましたが,どこもが,どこか断片的です。
最初は本です。
本も自分で手にとって見つけるのが一番だと思うので,
特定の本を薦めるのはあまり好きではないですが,

「おしえて!!Flashシリーズ」
http://www.makion.net/profile/books/books.html
を薦めています。
これで基礎を養って,さらなる本を自分で探されるのが良いと思います。

また,このカテゴリにもたくさん「本」に関する質問が寄せられますので,
そちらを参考にして頂いても良いと思います。
(もし質問者さまが,OKWave系の方でしたら,教えて!gooからの引用ですみません。)

「質問:アクションスクリプトの勉強方法」
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1831329
「質問:FLASHを学ぶ本」
http://oshiete1.goo.ne.jp/kotaeru.php3?q=183057
「質問:Flashについて教えて下さい。」
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1770033
などなどなど…

サイトでしたら,バージョン違いや,断片的であることを
ある程度考慮した上で,

「FLASH道場」
http://www2.netwave.or.jp/~light/index.html
「FLASHの枝」
http://www.1art.jp/

などでしょうか。

============================

>> また、明日
>> インスタンス名 maru1 というムービークリップを作って,
>> maru1.gotoAndPlay(2);
>> と書き換えて動きを確かめたいと思います。

この部分だけなら,文字だけですがなんとか,ここで具体例を説明できます。
文字だけなので大変わかりにくいと思いますけど。

ひとたびは,今作られている物を全部忘れてください。
新規ドキュメントの部分から行きます。

まず,FlashMX を起動させてください。
FlashMX の場合は,勝手に「名称未定-1」とかいうものが開くと思います。
名前は何でも良いのでそのドキュメントを任意の場所に保存してください。

ステージ上に,塗りで ● を 2つ 描いてください。
1つを選択して,「挿入」→「シンボルに変換」で,グラフィックシンボルにしてください。
もう1つも同じくグラフィックシンボルにしてください。
シンボル名は何でも良いです。勝手に命名される名前で十分です。
このシンボル名はFlash作成段階でファイル管理上命名される名前で,
スクリプトとは一切関係しません。

グラフィックシンボルになった ● のうち1つを選択して,
「挿入」→「シンボルに変換」で,今度はムービークリップシンボルにしてください。
もう1つも同じくムービークリップシンボルにしてください。

これで,メインムービーのタイムラインを含めて,
3つの独立したタイムラインが作られたことになります。

ムービークリップシンボルになった ● のうち1つを選択した状態で,
下のプロパティパネルの右の方で,

 [ ムービークリップ ▼]
 [ <インスタンス名> ]

となっている, <インスタンス名> の部分に, maru1 と書いてください。
インスタンス名はとても重要で,後のスクリプトに深く関わります。

もう1つの ● も同じく,下のプロパティパネルの右の方で,
インスタンス名を付けてください。
こんどは, maru2 としておきます。

次に,
maru1 というインスタンス名が付いた ● をダブルクリックしてください。
(または,右クリック→同じ位置で編集 を選択してください。)
これで,このムービークリップ内のタイムラインの編集に入ることができます。

上に別のタイムラインが表示されていると思います。
このムービークリップ内のレイヤーを
「2レイヤー」で「30フレーム」にしてください。
タイムラインを図示すると以下のようになります。

                          30
 □ レイヤー 筆・・|○            []|
 □ レイヤー 筆・・|●            []|

● が存在する方のレイヤー(下のレイヤー)の,フレーム30 を選択し,
「右クリック」→「キーフレームに変換」でキーフレームにしてください。
そして,その フレーム30 の ● をステージ上の何処かに移動させてください。
そして, フレーム1 を選択。
「右クリック」→「モーショントゥイーンを作成」でモーショントゥイーンを作成します。

次に,上のレイヤーの フレーム30 を選択して,キーフレームにしてください。

                          30
 □ レイヤー 筆・・|○          []|○|
 □ レイヤー 筆・・|●>------------->|●|


その フレーム30 を選択した状態で,下のアクションパネルに
以下の2行を書いてください(コピペしてください)。

--------------------------
gotoAndStop(1);
_root.maru2.play();
--------------------------

この1行目は,
このムービークリップ自体を フレーム1 へ行かせて stop 。
という意味です。
2行目は,
メインムービー(_root)にある maru2 というインスタンス名のムービークリップを動かす。
という意味です。

ここまでできたら,
「編集」→「ドキュメントの編集」でメインムービー(_root)の編集画面に戻ります。
メインムービーのタイムラインを見てもらうとわかると思いますが,
メインムービーのタイムラインは何も触っていないので,1フレームのみのはずです。
明らかにさっきのタイムラインとは違うタイムラインであることが確認できると思います。

 □ レイヤー 筆・・|●|

次に,
maru2 というインスタンス名を付けたムービークリップの編集に入ります。

maru2 というインスタンス名が付いた ● をダブルクリックしてください。
(または,右クリック→同じ位置で編集 を選択してください。)
これで,このムービークリップ内のタイムラインの編集に入ることができます。

今度は,
2レイヤー,50フレームにしてください。

                             50
 □ レイヤー 筆・・|○                []|
 □ レイヤー 筆・・|●                []|


下レイヤーの ● を maru1 と同様に何処かに動かすモーショントゥイーンを作成してください。
そして,上のレイヤーの フレーム1 を選択して,
下のアクションパネルに,以下のようにかいてください。

--------------
stop();
--------------

これは,このムービークリップ自体をこのフレームでストップさせるというスクリプトです。

そして,上のレイヤーの フレーム50 を選択して,キーフレームにしてください。

                            50
 □ レイヤー 筆・・|○             []|○|
 □ レイヤー 筆・・|●>----------------->|●|


その フレーム50 を選択した状態で,下のアクションパネルに
以下の2行を書いてください(コピペしてください)。

--------------------------
gotoAndStop(1);
_root.maru1.play();
--------------------------

この1行目は,
このムービークリップ自体を フレーム1 へ行かせて stop 。
という意味です。
2行目は,
メインムービー(_root)にある maru1 というインスタンス名のムービークリップを動かす。
という意味です。

これで,完成です。
パブリッシュして,SWFファイルを確認してみてください。

maru2 は 初めのフレームに stop(); を書いているため,最初表示されたときは動きません。
maru1 は 初めのフレームに何も書かれていないので,動き始めます。
maru1 が最終フレームにたどり着くと,自分自身は フレーム1 で ストップしますが,
_root.maru2.play(); と書かれているため, maru2 を動かします。
maru2 が最終フレームにたどり着くと,自分自身は フレーム1 で ストップしますが,
_root.maru1.play(); と書かれているため, maru1 を動かします。

ファイルを閉じるまで永遠にこれを繰り返します。
これが,ムービークリップの1つの使い方です。
1つのムービーが終了した時点で,もう1つのムービーを直接動かしても良いですし,
_root に定義した function を実行しても良いわけです。

======================

これの応用をしたいのではないでしょうか。
勝手に長々と書きましたが,そうではないかと勝手に推測しました。

応用はなんとか,本などをされた上で,考えてみてください。

この回答への補足

具体例を出して丁寧に解説してくださりありがとうございました。自分で具体例のものを作ってみて動きを見ることが出来ました。
そして、質問したプログラムの方で指摘を受けたgotoAndPlayの部分を
インスタンス名 maru1 というムービークリップを作って,
maru1.gotoAndPlay(2);
と書き換えて動きを確かめてみました。
なのですが、if文でlとrの値によって指定フレームへの移動の処理をしているのに、if文通りに処理されなく、タイムラインに書かれた順番でムービーが再生されてしまいました・・・・。
なぜそうなってしまったのか、わからないのですが・・・・?

補足日時:2005/12/20 00:59
    • good
    • 0
この回答へのお礼

丁寧な説明ありがとうございました。
ひとつちょっとお聞きしたい問題があるのですが、本に書かれているのを見つけて、関数の処理を動的に切り替えるの事で、ムービー再生のタイミングができるのではないかと思ったのですが。
function maru1move() {
onEnterFrame = function() {
if (pArray[count][0] == 1)
else if(pArray[count][0] == 2){
・・・・・・・・
 }
 delete this.onEnterFrame;
};
//maru2が動く関数
maru2move(qArray[count][1]);
}
というように、それぞれの関数においてやっていけばよいかと思って実際に試してみたのですが、この関数が消えてしまい、動きもやらないような状態なのですが、エラーが出ないためどう違うのかがわからなくて解決できないのですが・・・。何かアドバイスいただけませんでしょうか?

お礼日時:2005/12/26 20:08

以前から何度も,


他カテゴリなどで御質問されているのはよく拝見させて頂いております。

いつも,最初の御質問は簡単そうなので,
回答者の方も回答されているようですが,
実際は,補足でかなりテキストでは表現できないような超難しい状況を説明されていて,
だいたい途中でどの方もわからなくなられているようです。
また,私もわからないので回答しませんでした。

今気づいたことですが,

>> レイヤーmaru1とレイヤーmaru2

と書かれている部分です。

>> gotoAndPlay("maru1",2);

>> gotoAndPlay("maru2",2);
では,レイヤーmaru1とレイヤーmaru2には行きませんよ。
と言うか,どう書いてもレイヤーmaru1とレイヤーmaru2には行きません。

gotoAndPlay("シーン名",フレーム数);

です。
同じタイムラインでは,レイヤーは必ず並行移動します。
同時進行でいろいろな物を動かすためにレイヤーがあると思ってくださって良いと思います。

難しいプログラム以前に,この点はちゃんと理解されないと,絶対にFlashは思うように動きません。

見た感じですが,しようとされていることは,ムービークリップ内ですることだと思います。
ムービークリップ内は,タイムラインが別なので,並行移動しません。

例えば,
100フレームあるムービー内に,10フレームあるムービークリップを入れて,何もスクリプトを書かなければ,
100フレームの間に,ムービークリップは10回繰り返されます。

メインのタイムラインの50フレーム目に,
stop(); と書いたとしても,
それはメインのムービーが50フレームでストップするだけで,
ムービークリップ内はあいかわらず,何度もループを繰り返します。

独立したタイムラインでは,時間軸は独立した動きをするということです。

だから,

gotoAndPlay("maru1",2);

ではなく,
インスタンス名 maru1 というムービークリップを作って,

maru1.gotoAndPlay(2);

のような感じにするべきではないでしょうか。

gotoAndPlay("maru2",2);

も同じく,

maru2.gotoAndPlay(2);

のような感じにする。
そして,ムービークリップ maru1 や maru2 の最終フレームに何かを実行させるスクリプトを書けば解決するような気がします。

以上は概念的説明です。
実際は,ムービークリップへのパスや function へのパスが必要となると思います。

>> レイヤーmaru1とレイヤーmaru2の指定フレームへ移動し

と書かれている部分が書き間違いでなければ,
ムービークリップ,パス,オブジェクト,タイムライン。
この辺のことを,最初から理解し直されることをお薦めします。

○を描いて…
それをグラフィックシンボルにして…
モーショントゥイーンで○をうごかして…
次にまた,
別の○を描いて…
それをグラフィックシンボルにして…
それをムービークリップにして…
ムービークリップの中で○をモーショントゥイーンでうごかして…

などという最初の最初から純粋なアニメーションを作られている方なら決してそういう間違いはしないのですが,
おそらく,いきなり難しいところから始められているので,最初の部分が飛んでいて,上手く行かない気がします。

さらに長いスクリプトは,いつも補足で書かれていますよね。
それが私にはさっぱり理解ができないので,回答はできないと思いますが,
私の勘違いや,補足説明がある場合は,補足してください。

この回答への補足

わかりにくい事を質問してしまい申し訳ありません。丁寧に解説いただきありがとうございます。
同じタイムラインでは,レイヤーは必ず並行移動します。
同時進行でいろいろな物を動かすためにレイヤーがあるといった事も把握できておりませんでした。
一応初めに
○を描いて…
それをグラフィックシンボルにして…
モーショントゥイーンで○をうごかして…
といった事をしてムービーを作成して、Acrionscriptを勉強していく事にしたのですが、
焦ってflashをいじり始めた為、flashの概念みたいなものがまだ良く把握できていない状況です。flashの作りといいますか、概念をきっちり固めるのにあたり何か良いwebページなどがありましたら教えていただけませんでしょうか?
また、明日
インスタンス名 maru1 というムービークリップを作って,
maru1.gotoAndPlay(2);
と書き換えて動きを確かめたいと思います。

補足日時:2005/12/18 20:06
    • good
    • 0

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