Murayama blog.

プログラミング教育なブログ

速度は方向が肝


ActionScript3.0アニメーションを継続する。
だんだん、習慣になってきた。いいかんじ。


本日から、5章速度と加速度に突入。一応19章まであるみたい。。


では気をとりなおして。


本日は速度について。
この本には速度とスピードは同じものではない、と書いている。
#訳のとき難しそう。。


「スピードは速度の一部であるが、速度には方向という概念も含まれる」と。


ほぉ。。


5章は全部読んだので、なんとなく言いたいことはわかります。
ASでアニメーションをするには、方向、つまり角度が重要なんだよ、ってことだと思います。


では、サンプル。
クリックすると、画面のボールが右下に進むだけです。
先に実行結果から。


そんでコード。

package
{
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  
  public class Velocity2 extends Sprite
  {
    
    private var ball:Ball;
    private var vx:Number = 3;
    private var vy:Number = 3;
    
    private var ballMove:Boolean;
    
    public function Velocity2()
    {
      init();      
    }
    
    private function init():void{
      ball = new Ball();
      ball.x = 50;
      ball.y = 100;
      addChild(ball);
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
      stage.addEventListener(MouseEvent.CLICK, onClick_stage);
    }
 
    private function onEnterFrame(evt:Event):void
    {
      if(ballMove){
        // 右下に進む
        ball.x += vx;
        ball.y += vy;
      }
    }
    private function onClick_stage(evt:MouseEvent):void
    {
      ballMove = !ballMove;
    }
  }
}
 
import flash.display.Sprite;
class Ball extends Sprite{
  
  private var color:uint;  
  private var radius:Number;
  
  public function Ball(radius:Number = 40, color:uint = 0xFF0000){
    this.radius = radius;
    this.color = color;
    init();
  }
 
  private function init():void{
    graphics.beginFill(color);
    graphics.drawCircle(0, 0, radius);
    graphics.endFill();
  }
}


後半にボールの定義が載ってるので長いけど、
全然しょぼいプログラムです。


右下に進むアニメーションは、こんなかんじです。
Event.ENTER_FRAMEイベントで動きを記述します。
ボールの座標(X, Y)を更新していっているだけです。

    private function onEnterFrame(evt:Event):void
    {
      if(ballMove){
        // 右下に進む
        ball.x += vx;
        ball.y += vy;
      }
    }


で、これだけじゃーしょうもない。
たしかに上記の記述方法でもボールを動かすことはできるんだけど、
これは、vxとvyという縦軸と横軸の速度がわかっているから、簡単にかけるんですね。


たとえば「スピードは5キロで45度の方向へ進む!」と言われたとき、
縦軸と横軸方向へのスピードがわからないですよね。
前述のやり方では途方に暮れてしまうわけです。


そこで、速度と方向(角度)がわかっている場合のコーディングの出番です。
結果はさっきと同じ右下(45度方向)に進むものです。

package
{
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  
  public class VelocityAngle extends Sprite
  {
    
    private var ball:Ball;
    private var angle:Number = 45;
    private var speed:Number = 3;
 
    private var ballMove:Boolean;
    
    public function VelocityAngle()
    {
      init();      
    }
    
    private function init():void{
      ball = new Ball();
      ball.x = 50;
      ball.y = 100;
      addChild(ball);
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
      stage.addEventListener(MouseEvent.CLICK, onClick_stage);
    }
 
    private function onEnterFrame(evt:Event):void
    {
      if(ballMove){
        var radians:Number = angle * Math.PI / 180;
        ball.x += Math.cos(radians) * speed;
        ball.y += Math.sin(radians) * speed;
      }
    }
 
    private function onClick_stage(evt:MouseEvent):void
    {
      ballMove = !ballMove;
    }
  }
}
 
import flash.display.Sprite;
class Ball extends Sprite{
  
  private var color:uint;  
  private var radius:Number;
  
  public function Ball(radius:Number = 40, color:uint = 0xFF0000){
    this.radius = radius;
    this.color = color;
    init();
  }
 
  private function init():void{
    graphics.beginFill(color);
    graphics.drawCircle(0, 0, radius);
    graphics.endFill();
  }
}


さっきと何が違うかというと、
Event.ENTER_FRAMEイベントの部分が変わっています。

    private function onEnterFrame(evt:Event):void
    {
      if(ballMove){
        var radians:Number = angle * Math.PI / 180;
        ball.x += Math.cos(radians) * speed;
        ball.y += Math.sin(radians) * speed;
      }
    }


あ、ソースにコメント付け忘れた。まーいーや。


さっきと違って縦軸、横軸へのスピードvx, vyは定義していません。
代わりに角度を示す変数angleと、単方向へのスピード変数speedを定義しています。
今、angle = 45、speed = 3というデータが格納されています。


まず、angleをラジアンに変換しています。
Math.PIをかけて180で割る。セオリー。
そん次に、求めたラジアンから横軸への速度を算出するためにMath.cos、
縦軸への速度を算出するためにMath.sinを使用しています。


こんなふうに角度がわかれば、縦軸、横軸への成分を算出できるというお話でした。

こうやって見直してみると、当たり前なんだけど、
自分としては、階段を1つ上った気分。