schwarzの雑記 このページをアンテナに追加 RSSフィード

06/06/07 (Wed)6月7日の雑記

[] 09:55 6月7日の雑記 - schwarzの雑記 を含むブックマーク

なんとか作れたことは作れたものの、バカに重いのでやはり先人の知恵にすがることになりました。


とりあえず、こんな感じになるようです。

しかしこれでもまだ重いので要高速化です。

class Bitmap
  #---------------------------------------------------------
  # ● 指定した座標と隣接し同じ色の部分をcolorで塗りつぶす
  #   sx, sy : x, y座標
  #   color  : 色
  #----------------------------------------------------------
  def fill(sx, sy, color)
    
    # 塗りはじめの点を格納するスタック
    points = [ [sx, sy] ]
    
    # 塗りつぶしていく部分の色
    before_color = get_pixel(sx, sy)
    
    # スタックの中身がある限り繰り返し
    until points.empty?
      
      # 末尾要素を1つ取り出す
      x, y = points.pop
      
      # もう塗られていれば飛ばす
      if get_pixel(x, y) == color
        next
      end

      # 左方向の境界の位置をしらべる
      x_left = x
      while x_left >= 0 && get_pixel(x_left, y) == before_color
        x_left -= 1
      end
      x_left += 1
      # 右方向の境界の位置をしらべる
      x_right = x
      while x_right < self.width && get_pixel(x_right, y) == before_color
        x_right += 1
      end
      x_right -= 1

      #----------------------------------------------------
      # ● x軸に平行な直線の描画
      #  xl, xr  : 左端、右端のx座標
      #  y       : y座標
      #  color   : 直線の色
      #-----------------------------------------------------
      def draw_line_x(xl, xr, y, color)
        for x in xl..xr
          set_pixel(x, y, color)
        end
      end
      
      # ラインを描画
      draw_line_x(x_left, x_right, y, color)

      #----------------------------------------------------
      # ● x_rightからx_leftまで、境界線の1つ手前の座標をスタックに積む
      #-----------------------------------------------------
      def scan_line(xl, xr, y, color, stack)
        # yが範囲外なら除外
        if y < 0 || y > self.height
          return
        end
        # 境界線を探索
        while xl <= xr
          # 非領域色を飛ばす
          while xl < xr
            if get_pixel(xl, y) == color
              break
            end
            xl += 1
          end
          if get_pixel(xl, y) != color
            break
          end
          # 領域色を飛ばす
          while xl <= xr
            if get_pixel(xl, y) != color
              break
            end
            xl += 1
          end
          stack << [xl-1, y]
        end
      end
      
      scan_line(x_left, x_right, y-1, before_color, points)
      scan_line(x_left, x_right, y+1, before_color, points)
      
    end
    
  end

end

ここで、例えばこんな感じに使ってみると、某OSのロゴっぽいものが描けます。

sprite = Sprite.new
sprite.bitmap = Bitmap.new(640, 480)

color = Color.new(255, 64, 0)
sprite.bitmap.draw_polygon(200,150, 300,150, 250,250, 150,250, color)
sprite.bitmap.fill(250, 200, color)
color = Color.new(64, 255, 0)
sprite.bitmap.draw_polygon(310,150, 410,150, 360,250, 260,250, color)
sprite.bitmap.fill(350, 200, color)
color = Color.new(64, 64, 255)
sprite.bitmap.draw_polygon(145,260, 245,260, 195,360, 95,360, color)
sprite.bitmap.fill(200, 300, color)
color = Color.new(255, 255, 32)
sprite.bitmap.draw_polygon(255,260, 355,260, 305,360, 205,360, color)
sprite.bitmap.fill(300, 300, color)

loop{
  Graphics.update
}

cyrosscyross2006/06/08 01:15はじめまして。
このエントリとは内容が違うので恐縮です。
Miyako作ってMiyakoの記事書いたサイロスです。
シーンの箇所、参考にしていただいてありがとうございす。
丁度、APIをいくらか拡張したv0.7を公開いたしましたので、ご参考にどうぞ。

SchwarzSchwarz2006/06/08 20:48これはこれは、はじめまして。更新お疲れ様です。
最近暇を見てはMiyakoに触っておりますが、新たな発見の連続です。
ありがとうございます。
陰ながら、応援させていただきます。