In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

ばね運動の係数をランダムにすると振り幅がものすごく大きくなる

ばね運動の原理を利用して摩擦係数の計算を省略して
ループの往復アニメーションを実現しようと思ったのですが
ちょっと工夫して一定のパターンのアニメーションではなく少し不規則に動かそうと思いました。
そこでばね係数?定数?を1.0未満でランダムに毎フレーム値を変えてみたところ
数秒で振り幅が想定外に大きくなってしまいます。
そこでばね係数ではなく振り幅の距離をランダムにしてみたのですが
こちらもやはり数秒で振り幅が想定外に大きくなってしまいます。
これはどういった原理でこうなってしまうのでしょうか?
ばね係数が1.0未満だったり振り幅の指定がさほど大きくなければ
ここまで大きく振れない様な気がするのですが。
Get Adobe Flash player
by Fricks 14 Jun 2011

    Talk

    bkzen at 14 Jun 2011 09:55
    係数が一定でないということは、加速度も一定にならないということです。 例えば、 y が 100 で 目標定点の y が 200 でした。 そのとき係数が 0.5 だった場合は (200 - 100) * 0.5 で加速度は 50 になります。 これが vy に 追加され、 vy が 0 だった場合は vy は50 です。 次の時も 係数が 0.5 でした。 その時加速度は (200 - 150) * 0.5 で 25 です。 また速度が上がるので vy は 75 になります。
    bkzen at 14 Jun 2011 09:55
    次の瞬間、定点(y = 200) を超えるので 次からは 加速度はマイナスになり、 速度 vy が少しずつマイナスに向かっていくのですが、 ここで 係数が 0.1 になったとします。 そうすると加速度は、 (200 - 225) * 0.1 で -2.5 になり、速度は 72.5 になります。 係数が 0.5 で固定の場合 -12.5 が加速度になるはずでした。 この差-10がの分だけ、ボールは遠くへ移動することになります。 本来係数が固定であれば、その係数がブレーキの際にも働くので、一定の範囲で動いていきます。 しかし、係数が変移する場合は、ブレーキの際、働かなくなることで差が生まれ、ふり幅が大きくなっていくというわけです。
    bkzen at 14 Jun 2011 10:05
    上の説明でイメージがわかない場合は、ブランコに乗っている最中に無重力になった時を想像してみてください。
    Fricks at 14 Jun 2011 14:43
    なるほど、計算の式だけを眺めて考えるより実際に計算を何か物に置き換えると分かりやすいですね。 上記説明でイメージが掴めました。 加速、減速ともに両方ランダムならバランスが取れるんじゃとも思ったのですが 定点に近づこうとする加速時と違って ブレーキの時はここまでに止まらなきゃいけないと決まっていない分 ブレーキが働かなくなると、どんどん遠ざかってしまう訳ですね。

    Tags

    Embed
/**
 * Copyright Fricks ( http://wonderfl.net/user/Fricks )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/aPN7
 */

//ばね運動の原理を利用して摩擦係数の計算を省略して
//ループの往復アニメーションを実現しようと思ったのですが
//ちょっと工夫して一定のパターンのアニメーションではなく少し不規則に動かそうと思いました。
//そこでばね係数?定数?を1.0未満でランダムに毎フレーム値を変えてみたところ
//数秒で振り幅がものすごく大きくなってしまいます。
//そこでばね係数ではなく振り幅の距離をランダムにしてみたのですが
//こちらもやはり数秒で振り幅がものすごく大きくなってしまいます。
//これはどういった原理でこうなってしまうのでしょうか?
//ばね係数が1.0未満だったり振り幅の指定がさほど大きくなければ
//ここまで大きく振れない様な気がするのですが。
//またもしこの原理が計算上正しい動きだとすると
//一番右のばね係数を極小値でランダムさせた時も1日とか放置すると
//同じ様に振り幅がものすごく大きくなってしまう物なのでしょうか。

package {
    
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.Graphics;
    import flash.events.Event;
    import flash.geom.Point;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    
    [SWF(backgroundColor="0xFFFFFF", frameRate="30")] 
          
    public class SpringBall extends Sprite {
        
        private var ball1:Ball;
        private var ball2:Ball;
        private var ball3:Ball;
        private var ball4:Ball;
              
        public function SpringBall() {
            //ボール配置
            this.ball1 = new Ball(0xFF0000);
            this.ball1.x = 50;
            this.ball1.y = 200;
            this.addChild(this.ball1);
            
            this.ball2 = new Ball(0x00FF00);
            this.ball2.x = 175;
            this.ball2.y = 200;
            this.addChild(this.ball2);
            
            this.ball3 = new Ball(0xFF00FF);
            this.ball3.x = 300;
            this.ball3.y = 200;
            this.addChild(this.ball3);
            
            this.ball4 = new Ball(0x00FFFF);
            this.ball4.x = 425;
            this.ball4.y = 200;
            this.addChild(this.ball4);
            
            //アニメーション開始
            this.addEventListener(Event.ENTER_FRAME,this.tick);
            
            //キャプションテキスト
            this.addTextField();
        }
        
        private function tick(e:Event):void{
            //通常
            this.ball1.vy += (this.ball1.dy - this.ball1.y) * this.ball1.spring;
            this.ball1.y += this.ball1.vy;
            
            //ばね係数ランダム
            this.ball2.spring = Math.random()*0.5;
            this.ball2.vy += (this.ball2.dy - this.ball2.y) * this.ball2.spring;
            this.ball2.y += this.ball2.vy;
            
            //距離ランダム
            this.ball3.dy = 200+Math.random()*50-25;
            this.ball3.vy += (this.ball3.dy - this.ball3.y) * this.ball3.spring;
            this.ball3.y += this.ball3.vy;
            
            //ばね係数ランダム 値極小
            this.ball4.spring = Math.random()*0.01;
            this.ball4.vy += (this.ball4.dy - this.ball4.y) * this.ball4.spring;
            this.ball4.y += this.ball4.vy;
        }
        
        private function addTextField():void
        {
            var tf:TextFormat = new TextFormat();
            tf.font = "_ゴシック";
            tf.size = 10;
            tf.leading = 1.0;
            tf.align = "center";
            
            var t1:TextField = new TextField();
            t1.defaultTextFormat = tf;
            t1.autoSize = TextFieldAutoSize.LEFT;
            t1.text = "通常";
            t1.x = this.ball1.x-t1.width*0.5;
            t1.y = 150;
            this.addChild(t1);
            
            var t2:TextField = new TextField();
            t2.defaultTextFormat = tf;
            t2.autoSize = "center";
            t2.text = "ばね係数ランダム";
            t2.x = this.ball2.x-t2.width*0.5;
            t2.y = 150;
            this.addChild(t2);
            
            var t3:TextField = new TextField();
            t3.defaultTextFormat = tf;
            t3.autoSize = "center";
            t3.text = "距離ランダム";
            t3.x = this.ball3.x-t3.width*0.5;
            t3.y = 150;
            this.addChild(t3);
            
            var t4:TextField = new TextField();
            t4.defaultTextFormat = tf;
            t4.autoSize = "center";
            t4.text = "ばね係数ランダム\n値極小";
            t4.x = this.ball4.x-t4.width*0.5;
            t4.y = 150;
            this.addChild(t4);
        }
    }
}


import flash.display.Shape;

class Ball extends Shape {
    
    public var fliction:Number = 1;
    public var spring:Number = 0.5;
    public var dy:Number = 225;
    public var vy:Number = 0;
    
    public function Ball(col:int = 0x000000) {
        this.graphics.beginFill(col);
        this.graphics.drawCircle(0,0,25);
        this.graphics.endFill();
    }
}