- ベストアンサー
Actionscriptで座標指定
- Actionscriptを使用して座標指定を行う方法について教えてください。
- 特定のボタンにマウスが乗ると指定した座標にスライド移動し、ムービーのスクロールが一定時間停止するような動きを実現したいです。
- また、ボタンからマウスが離れた場合にはスクロールが再開されるようにしたいです。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
#1です。 >> ボタンからrolloutした時に、タイミングによって >> 停止するところが変わってしまうのですが、 >> 毎回時間をリセットしてrolloverするとそこから時間をカウントする方法はあるのでしょうか? そうですね。 その毎回時間をリセットしてrolloverするとそこから時間をカウントするという方向性で合っています。 でもちょっと難しいでしょう。 getTimer(); はヘルプにもある通り, ムービーの再生を開始してからの経過時間をミリ秒単位で返します。 つまり,いつセットしても,ムービーの再生を開始してからの経過時間しか出ません。 Date.getTime で時間を取得するのと同じです。 Date.getTime の場合は 1970 年 1 月 1 日午前 0 時 (世界時) 以降のミリ秒数を返します。 日常生活でも,普通は時計しかありません。 しかし,タイマーはなくても時刻を表示する時計さえあれば, 任意の時刻からの経過時間を求められます。 例えば, 家を出るときに時計を見て 8:50 であることを確認する。 目的地に着いたときに時計を見て 10:10 であることを確認する。 家から目的地に着くまでの経過時間は 10:10 - 8:50 =1時間20分 という具合に。 Flash でも同様です。 1回目の getTimer(); でその時点でのムービーの再生を開始してからの経過時間を求め,メモしておき, 2回目の getTimer(); でその時点でのムービーの再生を開始してからの経過時間を求め, 差分を求めれば1回目の getTimer(); から,2回目の getTimer(); の経過時間がわかります。 以上のように考えて,それをスクリプトに組み込むと次のようになります。 ※インデントを付けるためスクリプトの各行の前には 全角空白文字をたくさん入れています。 コピペされる場合は,全角空白文字を, ""(何もなし)か," "(半角空白文字)に 置換してください。 _root のムービークリップ Slide に書くスクリプト -------------------------------------------- // このムービークリップが表示されたとき onClipEvent (load) { // 変数Y_Pos の初期値を null にする。 Y_Pos = null; //変数time_flag の初期値を 0 にする time_flag = 0; // 関数replace の定義 function replace() { // 変数time を 3 で割った余りが 0 であれば if (time%3 == 0) { // 動かさない this._y = this._y; // 変数time を 3 で割った余りが 0 でなければ } else { if (this._y>=-1680) { this._y -= 2; } else if (this._y<-1680) { this._y = 0; } } } // 関数transfer の定義 function transfer() { this._y += (Y_Pos-this._y)*0.6; } } onClipEvent (enterFrame) { // 変数time_flag の値が 0 であれば if (time_flag == 0) { //変数time1 にタイマーをセット time1 = getTimer(); // 変数time_flag の値を 1 にする time_flag = 1; } //変数time2 にタイマーをセット time2 = getTimer(); // 変数time に time1 から time2 の経過時間の整数部分を代入 time = Math.floor((time2-time1)/1000); // 変数Y_Pos が null であれば if (Y_Pos == null) { // 関数replace を実行 replace(); // 変数Y_Pos が null でなければ } else { // 関数transfer を実行 transfer(); } } -------------------------------------------- ボタンに書くスクリプト -------------------------------------------- on (rollOver) { //_root.Slide の変数Y_Pos を 4 にする _root.Slide.Y_Pos = 4; } on (rollOut) { //_root.Slide の変数Y_Pos を null に戻す _root.Slide.Y_Pos = null; //_root.Slide の変数time_flag を 0 に戻す _root.Slide.time_flag = 0; } -------------------------------------------- 長々と全体を書きましたが,変えたところは 上の onClipEvent (load) {} 内の //変数time_flag の初期値を 0 にする time_flag = 0; の1行と 下の onClipEvent (enterFrame) {} 内の, // 変数time_flag の値が 0 であれば if (time_flag == 0) { //変数time1 にタイマーをセット time1 = getTimer(); // 変数time_flag の値を 1 にする time_flag = 1; } //変数time2 にタイマーをセット time2 = getTimer(); // 変数time に time1 から time2 の経過時間の整数部分を代入 time = Math.floor((time2-time1)/1000); の部分と, ボタンのスクリプト //_root.Slide の変数time_flag を 0 に戻す _root.Slide.time_flag = 0; だけです。 ~~~流れ~~~ ボタンからロールアウトしたときに, Slide 内の変数 time_flag を 0 にします。 Slide 内の変数 time_flag を 0 であるときだけ, if (time_flag == 0) が True の状態になるので, 変数 time1 にその時の getTimer(); の値が記録されます。 そしてすぐに time_flag の値を 1 に切り替えます。 これで,if (time_flag == 0) は False になるので,何度も変数 time1が変わることはありません。 次に time2 に 常に最新の getTimer(); の値が入ります。 time2-time1が,ボタンからロールアウトしてからの経過時間になります。 それで, time = Math.floor((time2-time1)/1000); これで time には,ボタンからロールアウトしてからの経過時間の整数部分が入ります。 あとは同じです。 という感じです。 わかってしまえば難しくはないですね。 日常生活で自分自身がしていることを,Flash にさせれば良いだけです。
その他の回答 (1)
すごく考え込んでいらっしゃるようで,理解不能な部分が多いですが, わざわざ複雑にして,ますます迷宮に入り込んでいらっしゃるのではないですか。 かなり重傷入っている気がしますが,大丈夫ですか? (って大丈夫じゃないから質問されているわけですよね…。) まず確認です。 >> レイヤー1に[a_mc]のMCを配置。インスタンス名はSlideにしています。 と書かれているところから, 頻繁に登場する[a_mc]というのは,シンボル名か,勝手に決めニックネームか何かで, スクリプト上は存在しないものなのですよね。 スクリプト上は _root の Slide というインスタンス名のムービークリップなのですよね。 そう考えると,Slide の フレーム1 のスクリプト, Y_dif = (Y_Pos-_y)*0.6; _root.Slide._y = Number(Y_dif)+Number(_y); この,Number(_y) というのは,_root.Slide._y と同じということになります。 だから,結局上の2行はこうなります↓。 _root.Slide._y = (Y_Pos-_y)*0.6+_root.Slide._y; そしてこうなるわけです↓。 _root.Slide._y += (Y_Pos-_root.Slide._y)*0.6; ↑もしくは↓ this._y += (Y_Pos-this._y)*0.6; (「+=」は加算後代入演算子です。) 意味があれば別ですが, 何も意味がないのに相対パスと絶対パスを混在させると, 作っている自分自身がわけがわからなくなるだけですよ。 そして,他の物のことは一切考えず,これに関してだけ考えると, Slide 内のタイムラインで フレーム1 と フレーム2 をループさせる必要は全くなく, ムービークリップSlide に, ------------------------------- onClipEvent (enterFrame) { this._y += (Y_Pos-this._y)*0.6; } ------------------------------- と書けば良いだけのことになります。 フレーム1 と フレーム2 のループは取った方が良いです。 他を enterFrame で動かす上に,さらにフレームでループさせる必要性を全く感じませんし, そういうことをすると,自分的にもプログラム的にも複雑になるだけで良いことはありません。 フレームのループでスクリプトの連続実行をさせるのも良いですが, そうするのならそれだけに徹して onClipEvent (enterFrame) {} は使わない。 onClipEvent (enterFrame) {} を使うのならフレームのループでスクリプトの連続実行をしない。 どっちかにしないとややこしくなるだけです。 (それと,Slide 内タイムラインのグルグルループと, Slide自体に書いているonClipEventハンドラのスクリプトの書き方に 5年くらいの時代的差を感じるのは気のせいでしょうか…) また,書かれているスクリプトでは,onClipEvent (load) {} の中に function として関数を定義してありますから, それに従うと,これも onClipEvent (load) {} の中に入れた方が良いので, 適当な関数名である transfer というものを onClipEvent (load) {} の中に入れます。 ------------------------------- function transfer() { this._y += (Y_Pos-this._y)*0.6; } ------------------------------- というわけで,上記を前提にして, 書かれているスクリプトを書き直すと次のようになります。 { }が入れ子状態になって見にくいのでインデントを付けます。 ※インデントを付けるためスクリプトの各行の前には 全角空白文字をたくさん入れています。 コピペされる場合は,全角空白文字を, ""(何もなし)か," "(半角空白文字)に 置換してください。 全角空白文字があるとシンタックスエラーになります。 _root のムービークリップ Slide に書くスクリプト ----------------------- //このムービークリップが表示されたとき onClipEvent (load) { //変数Y_Pos の初期値を null にする。 Y_Pos = null; //関数replace の定義 function replace() { if (this._y>=-1680) { this._y -= 2; } else if (this._y<-1680) { this._y = 0; } } //関数transfer の定義 function transfer() { this._y += (Y_Pos-this._y)*0.6; } } //1フレーム進む時間毎に1回以下を実行 onClipEvent (enterFrame) { //変数Y_Pos が null であれば if (Y_Pos == null) { //関数replace を実行 replace(); //変数Y_Pos が null でなければ } else { //関数transfer を実行 transfer(); } } ---------------------- ボタンに書くスクリプト ---------------------- on (rollOver) { //_root.Slide の変数Y_Pos を 4 にする _root.Slide.Y_Pos = 4; } on (rollOut) { //_root.Slide の変数Y_Pos を null に戻す _root.Slide.Y_Pos = null; } ---------------------- ボタンのスクリプトで,Slide の変数Y_Pos を 4 か null に切り換えているだけです。 4 か null に切り換えるとそれによって, Slide内の関数 replace と transfer の連続実行が切り替わります。 Slide内の変数 Y_Pos は最初 null で始まりますから, ボタンにロールオーバーされるまで, this._y -= 2; が実行され続けます。 つまり,徐々に上に上がります。 ボタンにロールオーバーすると, Slide内の変数 Y_Pos は null ではなくなるので, this._y += (Y_Pos-this._y)*0.6; が実行されます。 つまり,どういう根拠で出てくる 4 なのかはわかりませんが, とにかく _y=4 を目指してピョーンと移動します。 何度も書きますが,上のスクリプトが動作するのは Slide の タイムラインのフレーム1 と フレーム2 のループは取った場合です。 付けたままだとうまく動作しません。 以上が, >> rolloutすると続きがスクロールする方法はどうやるのでしょうか? の回答です。 ======================================== 次が >> ムービーのスクロールをB秒止める方法 です。 そうですね。 時間制限は setInterval関数 などもありますが, この場合は書かれている getTimer() の方が簡単で,いろいろ融通がきくと思います。 説明の前に,スクリプトを書いてしまします。 上のスクリプトをさらに場合分けしているだけです。 ※スクリプトの各行の前には全角空白文字をたくさん入れています。 _root のムービークリップ Slide に書くスクリプト ----------------------- //このムービークリップが表示されたとき onClipEvent (load) { //変数Y_Pos の初期値を null にする。 Y_Pos = null; //関数replace の定義 function replace() { //変数time を 3 で割った余りが 0 であれば if (time%3 == 0) { //動かさない this._y = this._y; //変数time を 3 で割った余りが 0 でなければ } else { if (this._y>=-1680) { this._y -= 2; } else if (this._y<-1680) { this._y = 0; } } } //関数transfer の定義 function transfer() { this._y += (Y_Pos-this._y)*0.6; } } onClipEvent (enterFrame) { //変数time に経過時間の整数部分を代入 time = Math.floor(getTimer()/1000); //変数Y_Pos が null であれば if (Y_Pos == null) { //関数replace を実行 replace(); //変数Y_Pos が null でなければ } else { //関数transfer を実行 transfer(); } } ---------------------- ボタンのスクリプトはそのままで変更なしです。 増えた部分が,時間制限の部分です。 下の onClipEvent (enterFrame) {} 内から説明します。 //変数time に経過時間の整数部分を代入 time = Math.floor(getTimer()/1000); getTimer() で得られる数は SWF が表示されてからの経過時間ミリ秒です。 getTimer()/1000 でミリ秒単位を秒単位に変更しています。 Math.floor(getTimer()/1000) でその整数部分だけを取り出しています。 つまり,変数 time には 0,1,2,3,4,… という経過時間が整数で入るわけです。 その値を持って,関数replace を連続動作に移ります。 //変数time を 3 で割った余りが 0 であれば if (time%3 == 0) % は剰余の演算子です。 time÷3 の余りが 0 であれば this._y = this._y; が実行されます。つまり動きません。 time÷3 の余りが 0 でなければ this._y -= 2; が実行されます。つまり上に2ずつ移動します。 0 1 2 3 4 5 6 7 ←timeの値 ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 止 動 動 止 動 動 止 動 ということですね。 2秒動いては1秒止まり,また2秒動いては1秒止まる… を繰り返します。 仮に,「4秒動いては1秒止まる。」というパターンにしたければ, if (time%5 == 0) にすればいいわけです。 仮に,「4秒動いては2秒止まる。」というパターンにしたければ, if (time%3 == 0) これはこのままで, time = Math.floor(getTimer()/500); にすれば良いです。 また動く時間の方を長くして,止まっている時間が短くしたい場合は, if文の else より前と後を逆にすれば良いです。 ご質問されているのは 「1つのオブジェクトに対する座標移動」です。 1つのオブジェクトを動かすのに, いろいろな物を混在させても,プログラムが全く動かないか,または暴走するだけです。 ご質問で書かれている状態は, 正に「船頭多くて船山に上る」状態ですよ。 どういうときにどうしたいのか,場合分けを考えて, その各場合によって,狙い通りにスクリプトが動作するように仕組むことが肝腎です。
補足
本当に丁寧な回答ありがとうございます。 すごく分かりやすかったです!! ほとんど思い通りの動きが出来ました!! 分からない事をネットや書籍で色々調べながらの作っていたので、分かりづらい書き方をしていたんですね。まだまだ勉強頑張ります。 あと一つお聞きしたいのですが、 ボタンからrolloutした時に、タイミングによって 停止するところが変わってしまうのですが、 毎回時間をリセットしてrolloverするとそこから時間をカウントする方法はあるのでしょうか? 度々申し訳ありませんが、お時間がありましたら教えていただければ嬉しいです。
お礼
ありがとうございます! またまたすごく分かりやすく説明していただいて光栄です。 これで希望通りのものが作れそうです!! ほんとありがとうございました!!