-- / --
--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

12 / 23
Mon

間違えて 5 時に起きてしまった Ziphil です。

もともと私が Rubyist だったということもあって、 JRuby を導入してみました。 およそ 4 時間くらいかけて、 Kotlin で書かれているプログラムを JRuby に移植して、 早速実行! 動いた! Ruby は動的言語なので、 十分な速度が出るかどうか不安でしたが、 実用可能レベルでした。 Java とか Kotlin とかよりは少し遅いけど。

ちょっと JRuby のコードを見てましょう。

def draw_tilemap(tilemap, cx, cy, width, height, mode, observer)
  previous_color = self.color
  previous_font = self.font
  images = tilemap.images
  for x in 0...width
    for y in 0..height
      if tilemap.contain?(x + cx, y + cy)
        data = tilemap[x + cx, y + cy]
        if mode == 0 || (mode == 1 && tilemap.wall?(x + cx, y + cy)) || (mode == 2 && tilemap.floor?(x + cx, y + cy))
          if images.key?(data)
            if tilemap.autotile?(x + cx, y + cy)
              numbers = tilemap.autotile_number(x + cx, y + cy)
              numbers.each_with_index do |number, i|
                draw_image(images[data],
                           24 * x + i % 2 * 12, 24 * y + i / 2 * 12 - 12, 24 * x + i % 2 * 12 + 12, 24 * y + i / 2 * 12,
                           number % 4 * 12, number / 4 * 12, number % 4 * 12 + 12, number / 4 * 12 + 12,
                           observer)
              end
            else
              draw_image(images[data], 24 * x, 24 * y, observer)
            end
          else
            self.color = Color.new(68, 17, 17)
            fill_rect(24 * x, 24 * y, 24, 24)
            self.color = Color.new(102, 51, 51)
            draw_line(24 * x, 24 * y, 24 * x + 23, 24 * y + 23)
            draw_line(24 * x + 23, 24 * y, 24 * x, 24 * y + 23)
            self.color = Color.new(187, 136, 136)
            self.font = Font.new(self.font.font_name, 0, 9)
            draw_string(data.to_s, 24 * x + 2, 24 * y + 22)
          end
        end
      end
    end
  end
  self.color = previous_color
  self.font = previous_font
end

RPG では欠かせないマップの描画を行う部分のコードです。 getColor(newColor) とするところを color = new_color と、 代入文のように書けるのとか、 スマートでかなり良いです。 余分なカッコもなくなるので、 コードが見やすくなります。 ただし、 Ruby (JRuby) は動的型付けなので、 静的型付けの Kotlin などに比べて安全性は落ちます。

さて、 1 つだけ困った点があったので、 書いておきます。 以下のコードです。

class MainPanel < JPanel 
  def paint_component(graphics)
    super
    # 処理
  end
end

関係ないところは省いています。 JPanel クラスを継承した MainPanel クラスを作って、 paint_component メソッドをオーバーライドしました。 ちなみに、 JRuby は Java のキャメルケース (paintComponent みたいな) のメソッド名に対して、 スネークケース (paint_component みたいな) の Ruby らしい名前のメソッドを自動的に定義してくれます。 で、 これを実行してみると、 repaint メソッドを読んでも paint_component メソッドが呼ばれない。 おかしいなぁ・・・。

ということで調べてみると、 どうやらオーバーライドはキャメルケースのメソッド名で行わないといけないらしいです。 まあ、 そうすれば良いんですが、 キャメルケースのメソッド名は Ruby の慣習に反しますし、 キャメルケースとスネークケースが混ざるのが美しくない。 ということで、 良い感じに書けるように補助メソッドを作成してみました。

class String
  def camel_case
    name = split("_")
    ([name.first] + name[1, name.size - 1].map{|i| i.capitalize}).join
  end
end
class Module
  def def_java(*names)
    names.each do |name|
      class_eval("alias :#{name.to_s.camel_case} :#{name} ")
    end
  end
end

String クラスに、 スネークケースをキャメルケースに変換する camel_case メソッドを追加し、 さらに Module クラスに def_java メソッドを追加します。 こうすると、 こんな風に書くことで、 キャメルケースのメソッドが作られ、 オーバーライドが成功します。

class MainPanel < JPanel 
  def paint_component(graphics)
    super
    # 処理
  end
  def_java :paint_component
end

いちいち追加するのは面倒ですが、 途中でキャメルケースが混ざるよりも Ruby らしいコードが書けるような気がします。

さーて、 これで StarRuby とか Ruby/SDL に頼らなくてもゲームが作れるぞー。

スポンサーサイト

comment ×0
コメント
管理者にだけ表示を許可する
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。