ホームへ戻る

s2.6 自機に慣性を付ける


 本節では、先ほど作った自機の移動に慣性を付けてみましょう。
慣性を付けるといっても物理演算をするわけではありません。
端末を傾けてもすぐにそちらの方向に動くのではなく、ある程度前の動きを維持しつつ、
徐々に傾けている方向に動いていくようにするだけです。

そこで今回は実際に動いている向きを示す移動ベクトルと、
もう一つ、端末を傾けている向きを表すセンサーベクトルを追加します。



左:動いていない状態から
中:端末を右に傾けると、移動ベクトルもセンサーベクトルも右を指し、球は右に転がり始めます。
右:その瞬間端末を左に傾けたとすると、センサーベクトルは左を示していますが、移動ベクトルはまだ右をさし、球は右に転がります。

移動ベクトルは徐々にセンサーベクトルの方向にブレンドされ、最終的には左を向くといった感じに仕上げようと思います。

ではコードを見ていきましょう。
ベクトルを計算するために、少しメソッドを追加します。

↓Vec.java
(一部変更 
赤字部)
public class Vec {
        
        public float _x, _y;
        
        Vec(){
                _x = _y = 0;
        }
        
        Vec( float x, float y ){
                _x = x;
                _y = y;
        }
        
        //角度を取得する
        float getAngle(){
                return (float)Math.atan2(_y, _x);
        }

        //大きさを取得する
        float getLength(){
                return (float)Math.sqrt( _x*_x + _y*_y );
        }
        
        //引数の値より大きさが大きければ引数の値にする
        void setLengthCap( float maxLength ){
                float len = getLength();
                if( maxLength == 0 ){
                        return; //0割防止
                }
                if( len > maxLength ){//maxLengthより大きければ大きさをmaxLengthにする
                        float rate =len/maxLength;
                        _x /= rate;
                        _y /= rate;
                }
        }
        
        // vec方向の向きへrate率ほどブレンドする
        void blend( Vec vec, float rate ){
                float w = vec._x - _x;
                float h = vec._y - _y;
                _x += w*rate;
                _y += h*rate;
        }
        
}

ベクトルの大きさがあまりにも大きくなり過ぎないように上限を設定出来るように、
setLengthCap()を設けました。
maxLength以上の大きさにはならないようになります。

また、引数のベクトル方向に、引数のブレンド率だけ、ベクトルをブレントするメソッドである
blend()も設けました。

これらをPlayerから使ってみましょう。

↓Player.java (一部変更 
赤字部
public class Player extends Task {
        private final static float MAX_SPEED = 20;              //移動する最大スピード
        private final static float SIZE = 20;                   //自機の大きさ
        private Circle _cir = null;                     //自機の円
        private Paint _paint = new Paint();     //描画設定
        private Vec _vec     = new Vec();       //自機の移動ベクトル
        private Vec _sensorVec = new Vec();     //センサーのベクトル
        
        public Player(){
                _cir = new Circle( 240, 0, SIZE );      //(240,0)の位置にSIZEの大きさの円を作る
                _paint.setColor(Color.BLUE);            //色を青に設定
                _paint.setAntiAlias(true);                      //エイリアスをオン
        }

        // ベクトルをセットする
        private void setVec(){
                float x = -AcSensor.Inst().getX()*2;    //加速度センサーの情報を取得
                float y =  AcSensor.Inst().getY()*2;
                _sensorVec._x = x < 0 ? -x*x : x*x;     //2乗して変化を大袈裟にする
                _sensorVec._y = y < 0 ? -y*y : y*y;     //2乗すると+になるので、負ならマイナスを付ける
                _sensorVec.setLengthCap(MAX_SPEED);     //ベクトルの大きさが最大スピード以上にならないようにする           
                _vec.blend( _sensorVec, 0.05f );        //センサーのベクトル方向に実際の移動ベクトルを5%近づける
        }

        // 移動ベクトルの向いている方に動かす
        private void Move(){
                _cir._x += _vec._x;     //移動ベクトル_vecが指す方向に移動させる 
                _cir._y += _vec._y;
        }
        
        @Override
        public boolean onUpdate(){
                setVec();       //移動ベクトルをセットする
                Move();         //移動ベクトルが向いている方に動かす
                return true;
        }

        @Override
        public void onDraw( Canvas c ){
                c.drawCircle(_cir._x, _cir._y, _cir._r, _paint);
        }

}


移動ベクトルである _vec の他に、センサーの向きを表すベクトル _sensorVec を追加しました。

setVec() では実際のセンサーの傾きから、センサーのベクトルを求めています。
変化を大袈裟にするために、X2したり、2乗したりしています。
これでちょっと傾けたら大袈裟に転がるようになります。

動きが速くなり過ぎないように
setLengthCap() で上限を設定し、blendで、移動ベクトルの方向をセンサーの方向にブレンドします。
この処理は一秒間に60回行われるわけですから、5%位のブレンド率でも十分です。
この値を低くするほどもっさり、高くするほどキビキビ動きます。
ある程度もっさりしていた方が慣性が働いているように見え、リアルだと私は思います。

今回の変更は以上なので、実行してみて下さい。
先ほどより傾きに大して大袈裟に動き、かつ、慣性が働いているように見えるようになったと思います。

実行結果


傾けた向きに応じて円が移動すれば成功です。

この章のプロジェクトをダウンロード

→分からないことがあれば掲示板で質問して下さい


Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.

- Remical Soft -