- ベストアンサー
AS3.0で地面にバウンドするように落下させたい
浩太と申します。 FLASHQ&Aで紹介されたNo.904↓ http://hfm-kenchan.com/Lesson/contents/index.htm ※No.904を、クリックして頂ければと思います。 を、AS3.0で対応したいのですが、どうしてもうまくいきません。 ↓ように、記述してみましたが、stopせずに、永遠とバウンドしたままとなってしまいます。 どうかご教授下さい。 addEventListener(Event.ENTER_FRAME, onEnterframe); stop(); function onEnterframe(event:Event):void { //初期Y座標配置幅 var yPos = 300; //初期速度 var spd = 5; //重力 var g = 2.5; //跳ね返り係数 var k = 0.9; //空気抵抗 var t = 0.99; //地面のY座標値 var base = 250; var dy = Math.floor(Math.random()*190); ball.y = dy; base = base-stage.stageHeight/2; spd = spd*t+g; dy += spd; if (dy >= base) { dy = base; spd = -spd*k; } }
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
#1の方ではありませんが... > 下記のように記述したら、解決しました! それは何よりです。 > もし、下記の記述方法を、よりコンパクトに出来る等ありましたら、 サンプルのオリジナルになるべく近い形で直訳っぽいことをすると次のようになります。 まず,各ボールのムービークリップ(以下MCと略します)自体に書いてあるスクリプトを全て消します。 (onClipEvent(load){…} や onClipEvent(enterFrame){…} など全部です。) 当然ですが,パブリッシュ設定でFlashタブより ActionScript の バージョンを ActionScript 3.0 に設定しておきます。 そして,各ボールを選択した状態でプロパティパネルより 各MC1つ1つに別々のインスタンス名を付けます。 ここでは,5つのボールMCがあったとして, それぞれに 「mc0」 「mc1」 「mc2」 「mc3」 「mc4」 というインスタンス名を付けることにします。 それら 「mc0」~「mc4」 が存在するタイムライン(例:rootのタイムライン)のキーフレームに 次のようなスクリプトを書けば(コピペすれば)完成です。 ------------------------------------- //フレームは1つなのであってもなくても良い) //this.stop(); // 「mc0」~「mc?」の ? の数を設定(例:「mc4」まで) var last:int = 4; // 初期Y座標配置幅 var yPos:Number = 300; // 初期速度 var spd:Number = 5; // 重力 var g:Number = 2.5; // 跳ね返り係数 var k:Number = 0.9; // 空気抵抗 var t:Number = 0.99; // 地面のY座標値 var base:Number = 250; // バウンドさせる関数「boundBall」を定義 function boundBall(evt:Event):void{ evt.target.spd = evt.target.spd*t+g; evt.target.dy += evt.target.spd; if (evt.target.dy >= evt.target.base) { evt.target.dy = evt.target.base; evt.target.spd = -evt.target.spd*k; } evt.target.y = evt.target.dy; } // 「mc0」~「mc?」に関するループ for(var i:int = 0; i<=last; i++){ this["mc"+i].y = this["mc"+i].dy=-Math.floor(Math.random()*yPos); this["mc"+i].spd = spd; this["mc"+i].base = base-this["mc"+i].height/2; this["mc"+i].addEventListener(Event.ENTER_FRAME,boundBall); } -------------------------------- スクリプトはコレ↑1つだけですから, 元のサンプルのように複雑ではありません。 例えば20個のボール「mc0」~「mc19」作成した場合は, 最初の行の, // 「mc0」~「mc?」の ? の数を設定(例:「mc4」まで) var last:int = 4; の部分を // 「mc0」~「mc?」の ? の数を設定 var last:int = 19; に変更すれば良いだけです。 =*=*=*=*=*=*=*=*=*=*=*=*= 【参考図↓】
その他の回答 (2)
- H240S18B73
- ベストアンサー率65% (190/288)
解決したようなところにおせっかいですが 1の方への返答に書かれたコード 同じようなものを作った事があるんですが これだと重力の値が高いとき地面でガタガタしません? たとえば地面に接触している時を考えた時 地面に接触しているのに重力分加速して 地面からはねることになるはずです 簡単に言うと 地面にぶつかって押し戻された分 つまり、なかったことにされた時間の分まで 加速されているから永遠に止まらない ってことです これを回避するには 簡単な方法だと速度がある程度以下なら 0にしてしまい、加速もしないようにする ある程度ちゃんとするなら 本来すすむはずだった距離と 押し戻された距離を考慮して 重力加速を減算する というようにやれば良いかとおもいます おせっかいスイマセン
お礼
ありがとうございます! 参考にさせてもらいます。。
- 15mm
- ベストアンサー率65% (65/100)
解説サイトを見てもわかるように、 onClipEvent (load) { 最初に、初期設定 と onClipEvent (enterFrame) { 毎フレーム以下を繰り返し実行 は区別されています。 質問文中のコードはenterframeの中で初期化を行っていますので、 初期化をずっと繰り返すだけとなり「永遠とバウンドしたまま」です。 //初期化処理群 var yPos=300,spd=5,・・・ addEventListener() function onEnterframe(event:Event):void { //バウンドの計算処理のみ } の形に入れ替えてあげれば大丈夫でしょう。
補足
ありがとうございます。 下記のように記述したら、解決しました! もし、下記の記述方法を、よりコンパクトに出来る等ありましたら、 教えて頂けましたら、幸いです。 // 初期Y座標配置幅 var yPos:Number = 300; // 初期速度 var spd :uint = 5; // 重力 var g:Number = 2.5; // 跳ね返り係数 var k:Number = 0.9; // 空気抵抗 var t:Number = 0.99; // 地面のY座標 var base:Number = 250; var dy:Number; ball_a.y = dy = -Math.floor(Math.random()*yPos); ball_a.spd = spd; ball_a.g = g; ball_a.k = k; ball_a.t = t; ball_a.base = base-ball_a.height/2; ball_b.y = dy2 = -Math.floor(Math.random()*yPos); ball_b.spd = spd; ball_b.g = g; ball_b.k = k; ball_b.t = t; ball_b.base = base-ball_b.height/2; ball_c.y = dy3 = -Math.floor(Math.random()*yPos); ball_c.spd = spd; ball_c.g = g; ball_c.k = k; ball_c.t = t; ball_c.base = base-ball_c.height/2; ball_d.y = dy4 = -Math.floor(Math.random()*yPos); ball_d.spd = spd; ball_d.g = g; ball_d.k = k; ball_d.t = t; ball_d.base = base-ball_d.height/2; ball_e.y = dy5 = -Math.floor(Math.random()*yPos); ball_e.spd = spd; ball_e.g = g; ball_e.k = k; ball_e.t = t; ball_e.base = base-ball_e.height/2; ball_a.addEventListener(Event.ENTER_FRAME,xEnterframe,false,0,true); ball_b.addEventListener(Event.ENTER_FRAME,xEnterframe2,false,0,true); ball_c.addEventListener(Event.ENTER_FRAME,xEnterframe3,false,0,true); ball_d.addEventListener(Event.ENTER_FRAME,xEnterframe4,false,0,true); ball_e.addEventListener(Event.ENTER_FRAME,xEnterframe5,false,0,true); stop(); function xEnterframe(e:Event):void { e.target.spd = e.target.spd * e.target.t + e.target.g; dy += e.target.spd; if (dy >= e.target.base) { dy = e.target.base; e.target.spd = -e.target.spd * e.target.k; } e.target.y = dy; } function xEnterframe2(e:Event):void { e.target.spd = e.target.spd * e.target.t + e.target.g; dy2 += e.target.spd; if (dy2 >= e.target.base) { dy2 = e.target.base; e.target.spd = -e.target.spd * e.target.k; } e.target.y = dy2; } function xEnterframe3(e:Event):void { e.target.spd = e.target.spd * e.target.t + e.target.g; dy3 += e.target.spd; if (dy3 >= e.target.base) { dy3 = e.target.base; e.target.spd = -e.target.spd * e.target.k; } e.target.y = dy3; } function xEnterframe4(e:Event):void { e.target.spd = e.target.spd * e.target.t + e.target.g; dy4 += e.target.spd; if (dy4 >= e.target.base) { dy4 = e.target.base; e.target.spd = -e.target.spd * e.target.k; } e.target.y = dy4; } function xEnterframe5(e:Event):void { e.target.spd = e.target.spd * e.target.t + e.target.g; dy5 += e.target.spd; if (dy5 >= e.target.base) { dy5 = e.target.base; e.target.spd = -e.target.spd * e.target.k; } e.target.y = dy5; } // replayボタンがクリックされたら再度movieを実行 replay.addEventListener(MouseEvent.MOUSE_UP, playMovie); function playMovie(event:MouseEvent):void { play(); }
お礼
本当に丁寧な解説、ありがとうございます!! 理解できました。 this["mc"+i] といった形にして、ループさせる方法は、勉強不足の為に、思いつきませんでした。。 ありがとうございました!!