Murayama blog.

プログラミングと、その次の話

摩擦 簡易Ver


おっと、もうこんな時間。そろそろ帰らねば。。


摩擦の計算方法には、もうちょっと簡単なテクニックがあります。
さっきの例では、縦、横のスピードから1方向のスピードを算出して、
摩擦を適用したのだけれど、こんなかんじでもいけます。

vx *= 摩擦(0.9とか1に近い値)
vy *= 摩擦(0.9とか1に近い値)


上記の処理をENTER_FRAMEイベント内で繰り返すことで、
徐々にスピードを減速させることができます。


こないだの宇宙船のサンプルを拡張したのが6章のまとめ。左キー、右キー、上キーで動きます。まずクリックしてね。


コードはこんなかんじ。ちょっと長いけど前とほとんど同じ。

package
{
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.events.KeyboardEvent;
  import flash.ui.Keyboard;
  
  public class ShipSimFriction extends Sprite
  {
    private var ship:Ship;
    private var thrust:Number = 0
    private var vr:Number = 0;
    private var vx:Number = 0;
    private var vy:Number = 0;
    
    private var friction:Number = 0.97;
    
    public function ShipSimFriction()
    {
      init();
    }
    private function init():void{
      
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      
      ship = new Ship;
      //ship.x = stage.stageWidth / 2;
      //ship.y = stage.stageHeight / 2;
      ship.x = 100;
      ship.y = 100;
      ship.scaleX = ship.scaleY = 2;
      
      addChild(ship);
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
      stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown_stage);
      stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp_stage);
    }
 
    private function onEnterFrame(evt:Event):void
    {
      ship.rotation += vr;
      var radians:Number = ship.rotation * Math.PI / 180;
      
      // 加速の計算
      var ax:Number = Math.cos(radians) * thrust;
      var ay:Number = Math.sin(radians) * thrust;
      vx += ax;
      vy += ay;
 
      // 簡易な摩擦(乗算してもそれっぽい動きになる)
      // 縦スピード * 0.97, 横スピード * 0.97
      vx *= friction;
      vy *= friction;
      
      ship.x += vx;
      ship.y += vy;
      
      var left:Number = 0;
      var right:Number = stage.stageWidth;
      var top:Number = 0;
      var bottom:Number = stage.stageHeight;
      
      if(ship.x - ship.width /2 > right){
        ship.x = left - ship.width / 2;
      }else if(ship.x + ship.width / 2 < left){
        ship.x = right + ship.width / 2;
      }
      
      if(ship.y - ship.height / 2 > bottom){
        ship.y = top - ship.height / 2;
      }else if(ship.y + ship.height / 2 < top){
        ship.y = bottom + ship.height / 2;
      }
    }
 
    private function onKeyDown_stage(evt:KeyboardEvent):void
    {
      if(evt.keyCode == Keyboard.LEFT){
        vr = -5;
      }else if(evt.keyCode == Keyboard.RIGHT){
        vr = +5;      
      }else if(evt.keyCode == Keyboard.UP){
        thrust += 0.2
        ship.draw(true);
      }
    }
 
    private function onKeyUp_stage(evt:KeyboardEvent):void
    {
      thrust = 0;
      vr = 0;
      ship.draw(false);
    }
  }
}
 
import flash.display.Sprite;
 
class Ship extends Sprite
{
  public function Ship()
  {
    draw(false);
  }
  
  public function draw(showFlame:Boolean):void{
    graphics.clear();
    graphics.beginFill(0x00FFFF);
    graphics.lineStyle(1, 0xFFFFFF);
    graphics.moveTo(10, 0);
    graphics.lineTo(-10, 10);
    graphics.lineTo(-5, 0);
    graphics.lineTo(-10, -10);
    graphics.lineTo(10, 0);
    graphics.endFill();
    
    if(showFlame){
      graphics.beginFill(0x990000);
      graphics.lineStyle(1, 0xFF0000);
      graphics.moveTo(-7.5, -5);
      graphics.lineTo(-15, 0);
      graphics.lineTo(-7.5, 5);
      graphics.endFill();
    }
  }
}


最初にも書いたように大事な部分は

      // 簡易な摩擦(乗算してもそれっぽい動きになる)
      // 縦スピード * 0.97, 横スピード * 0.97
      vx *= friction;
      vy *= friction;
      
      ship.x += vx;
      ship.y += vy;

こんなふうに摩擦を表現することもできます。
しっておくと良いテクニックだと思う。


以上、6章おしまい。