ドット絵エディタを作る(ブレゼンハムで直線だ編)

ねみぃ…

前回は線を引いてみようと思ったんだけど,なんと線がつながらねー.
まぁ,そりゃそうなわけで…
そういうわけで(?),今回は「ブレゼンハムのアルゴリズム」というのを使って直線を引こう.

ブレゼンハムを使った直線描画っていうのは,簡単に言うと,始点と終点を指定すると,その間の直線を引いてくれるっていうもんで,このアルゴリズムの優れたところは,加減算と比較しか使わないので高速!っていうとこ.
かなーり有名なアルゴリズムなので,知らないとモグリかと思われてしまうかも…(そうなんかー?)

しかもこれ,応用によっちゃぁ 直線以外にも円や渦もかけたりして結構便利.
線を引く以外にも,ゲームでキャラの移動にも使えるしね.

さて,プログラムではこんな感じになりました.


  // fromX, fromY : 始点
  // toX, toY     : 終点
  // x, y         : 色を塗るピクセル座標
  // dX, dY       : 始点から終点への距離


  //距離を求める(dx,dy がそれぞれの軸の距離になります)

  dx  := toX - fromX ;
  dy  := toY - fromY ;
  if ( dx < 0 ) then ax := -1 else ax := 1 ;
  if ( dy < 0 ) then ay := -1 else ay := 1 ;
  dx := abs( dx ); //絶対値
  dy := abs( dy );


  // 表示先のピクセル座標を求める.

  count := 0 ;
  x := fromX ;
  y := fromY ;

  // X方向とY方向とで距離に応じて場合分け.

  if ( dX >= dY ) then begin

    i := 0 ;
    while ( i < dX ) do begin

      // この段階での x, y が直線上の点になるので,
      // この座標上に色を塗ればOK.
      // 例えば,FBackBmp.Canvas.Pixcels[x,y] := RGB(0,0,0);
 
      inc( x, aX );
      inc( count, dY );
      if ( count >= dX ) then begin
        inc( y, aY );
        dec( count, dX );
      end;

      inc( i );
    end;

  end else begin

    i := 0 ;
    while ( i < dY ) do begin

      // この段階での x, y が直線上の点になるので,
      // この座標上に色を塗ればOK.
      // 例えば,FBackBmp.Canvas.Pixcels[x,y] := RGB(0,0,0);
      
      inc( y, aY );
      inc( count, dX );
      if ( count >= dY ) then begin
        inc( x, aX );
        dec( count, dY );
      end;

      inc( i );
    end;

  end;
む,むぅ…
Delphiは確かにステキじゃが,begin と end になじめねぇ…
それに,for文が使いづれぇ…
うっかり
for i:=1 to 0 do
begin
  ・・・
end;
なんて書こうもんなら,カナリやばいねー.半暴走だねー.
それに,iの増分は1以外のときは使えないしぃ.
おかげで,Delphiではforの代わりにwhile使う癖がついてしまった…
せめて,for 文だけはC言語の構文がよかったにゃー

試しに上のをC言語で書いてみると…


  // fromX, fromY : 始点
  // toX, toY     : 終点
  // x, y         : 色を塗るピクセル座標
  // dX, dY       : 始点から終点への距離


  //距離を求める(dx,dy がそれぞれの軸の距離になります)

  dx  = toX - fromX ;
  dy  = toY - fromY ;
  ax  = ( dx < 0 )? -1 : 1 ;
  ay  = ( dy < 0 )? -1 : 1 ;
  dx  = abs( dx ); //絶対値
  dy  = abs( dy );


  // 表示先のピクセル座標を求める.

  int count = 0 ;
  int x  = fromX ;
  int y  = fromY ;

  // X方向とY方向とで距離に応じて場合分け.

  if ( dX >= dY ) 
  {
    for ( i=0 ; i < dX ; ++i ) 
    {
      // この段階での x, y が直線上の点になるので,
      // この座標上に色を塗ればOK.
      // 例えば,FBackBmp.Canvas.Pixcels[x,y] := RGB(0,0,0);
 
      x     += aX ;
      count += dY ;
 
      if ( count >= dX ){
         y     += aY ;
         count += dX ;
      }
    }
  }
  else
  {
    for ( i=0 ; i < dY ; ++i )
    {
      // この段階での x, y が直線上の点になるので,
      // この座標上に色を塗ればOK.
      // 例えば,FBackBmp.Canvas.Pixcels[x,y] := RGB(0,0,0);
      
      y     += aY ;
      count += dX ;

      if ( count >= dY ) {
         x     += aX ;
         count += dY ;
      }
    }
  }
むおぉお,すっきりー

やっぱり,begin,end はイラねぇんじゃないかなー…なんてね.(毒)


…というわけで,ちゃんと線が引けるようになりましたとさ.
えーと,次回は何しよっかなー.



<< Back to Diary...