摩擦 リアルな計算Ver
久しぶりにASの勉強も少し。。
3日サボるとだいぶ勘が鈍りますね。はい、そうですね。
本日は摩擦の勉強。
激しく地味なサンプルです。起動してすぐはボールが動いてるんですけど、摩擦によって止まります。
最初は動いてたんですよ、このボール。よかったらリロードしてみてください。
そんでコード。
地味に摩擦の計算をする部分のコードがかっこいい。誰も見ないだろうけど。
package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; public class Friction1 extends Sprite { private var ball:Ball; private var vx:Number = 0; private var vy:Number = 0; private var fliction:Number = 0.1; public function Friction1() { init(); } private function init():void{ stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; ball = new Ball; ball.x = 200; ball.y = 200; vx = Math.random() * 10 - 5; vy = Math.random() * 10 - 5; addChild(ball); addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(evt:Event):void { // 縦横のスピードから1方向のなスピードと角度を求める var speed:Number = Math.sqrt(vx * vx + vy * vy); var radians:Number = Math.atan2(vy, vx); // 摩擦によるスピードの減速 if(speed > fliction){ speed -= fliction; }else{ speed = 0; } // 縦横のスピードに戻す vx = Math.cos(radians) * speed; vy = Math.sin(radians) * speed; ball.x += vx; ball.y += vy; } } } import flash.display.Sprite; class Ball extends Sprite { public var radious:Number; public var color:uint; public var vx:Number; public var vy:Number; public function Ball(radius:Number = 40, color:uint = 0xff0000) { this.radious = radius; this.color = color; init(); } private function init():void{ graphics.beginFill(color); graphics.drawCircle(0, 0, radious); graphics.endFill(); } }
ボールには縦横のスピードがあって、それがvx、vyという変数に格納されています。
で、摩擦は変数flictionに0.1って値が入ってます、と。
仮にvxに5、vyに3みたいな数値が格納されているとして、
単純に摩擦をデクリメントすると、
vxが4.9、vyが2.9になってしまいます。
一見、問題なさそうですが、これだと先にvy縦のスピードが0になってしまって横に滑る変な動きになっちゃいます。
#この例だと、摩擦による0.1のデクリメントをあと29回繰り返せば、vxが2.0、vyが0になってしまいます。
なんで摩擦を縦横のスピードにちょうどいいかんじに割り当てるには、
ピタゴラスの定理で縦横のスピードを1方向のスピードに変換します。
あわせて、角度も取得します。
// 縦横のスピードから1方向のなスピードと角度を求める var speed:Number = Math.sqrt(vx * vx + vy * vy); var radians:Number = Math.atan2(vy, vx); // 摩擦によるスピードの減速 if(speed > fliction){ speed -= fliction; }else{ speed = 0; }
純粋な1方向のスピードに摩擦をかけたら、
もとの縦横のスピードに戻します。
このとき、あらかじめ取得しておいた角度を使用します。
// 縦横のスピードに戻す
vx = Math.cos(radians) * speed;
vy = Math.sin(radians) * speed;
ball.x += vx;
ball.y += vy;
こんなかんじにすれば、ちょうどよい摩擦をかけることができます。