2014/12/13(土) [n年前の日記]
#1 [dxruby] DXRubyとBMFont
ゲーム制作時に使うビットマップフォントのフォーマットの一つに、BMFont?ってのがあるのですけど。Unityあたりでも使えたりする、のかな。たしかそのはず。
_Bitmap Font Generator 、もしくは、 _ShoeBox で作ることができる。以下の2種類のファイルで構成されているのですが。
_mplus1p_heavy_0-export.fnt
コイツを、DXRuby で表示してみたい、と思ったわけです。
とりあえず、ShoeBox で BMFont画像と .fnt を作成してから、 _SFontぽいもの - mirichiの日記 を参考にしつつソースを書いてみました。参考にというか、丸写しですけど。
_bmfont.rb
こんな感じの表示に。
他のスクリプトから呼ぶときは、以下のような感じ。
_main.rb
とりあえず、ファイル一式を置いときます。
_bmfontsupport_20141213.zip
同梱のBMFont画像は、M+フォントで作ったので、たぶん自由に使えるはず。
スクリプトソースは、DXRuby作者様のソースを丸写しに近いのでライセンスはよくわかりませんが、たぶん自由に使っていいんじゃないかなと。DXRubyのヘルプファイルにも、
_Bitmap Font Generator 、もしくは、 _ShoeBox で作ることができる。以下の2種類のファイルで構成されているのですが。
- 文字をギッシリ詰めたテクスチャ画像。
- どこに何の文字があるかを列挙した .fntファイル。(中身はテキストファイル)
_mplus1p_heavy_0-export.fnt
info face="C:\home\Pictures\_work\bitmapfont\mplus1p_heavy_0-export" size=32 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 common lineHeight=80 base=26 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="C:\home\Pictures\_work\bitmapfont\mplus1p_heavy_0-export.png" chars count=96 char id=33 x=175 y=149 width=13 height=24 xoffset=0 yoffset=56 xadvance=14 page=0 chnl=0 letter="!" char id=34 x=156 y=173 width=18 height=15 xoffset=0 yoffset=55 xadvance=19 page=0 chnl=0 letter=""" char id=35 x=26 y=151 width=23 height=24 xoffset=0 yoffset=56 xadvance=24 page=0 chnl=0 letter="#" char id=36 x=95 y=125 width=20 height=29 xoffset=0 yoffset=54 xadvance=21 page=0 chnl=0 letter="$" ... ... ... char id=125 x=156 y=122 width=18 height=30 xoffset=0 yoffset=55 xadvance=19 page=0 chnl=0 letter="}" char id=126 x=50 y=159 width=22 height=13 xoffset=0 yoffset=63 xadvance=23 page=0 chnl=0 letter="~" char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=0 letter=" " char id=9 x=0 y=0 width=0 height=0 xoffset=0 yoffset=0 xadvance=160 page=0 chnl=0 letter=" " kernings count=0
コイツを、DXRuby で表示してみたい、と思ったわけです。
とりあえず、ShoeBox で BMFont画像と .fnt を作成してから、 _SFontぽいもの - mirichiの日記 を参考にしつつソースを書いてみました。参考にというか、丸写しですけど。
_bmfont.rb
require 'dxruby' # DXRuby BMFont 描画用クラス # # ShoeBox で作成したビットマップフォントを描画する # @see http://renderhjs.net/shoebox/ # # @example # require 'dxruby' # require_relative 'bmfont' # bmfont = BMFont.new("bmfont.png", "bmfont.fnt") # Window.loop do # Window.draw_bmfont(100, 20, "Hello BMFont", bmfont) # end # # @version 0.0.2 # class BMFont # フォントの各文字を格納する構造体 BMFontData = Struct.new(:image, :w, :h, :xofs, :yofs, :xadvance) # @return [Integer] 文字間スペース(単位はドット) attr_accessor :spacing # @return [Integer] フォント縦幅(単位はドット) attr_reader :height # @return [Integer] フォント縦幅調整値(単位はドット) attr_reader :line_height # @return [Integer] フォントベースライン位置 attr_reader :baseofs # コンストラクタ # @param [String] imgfilename 画像ファイル名 # @param [String] fntfilename 文字配置情報(.fnt)ファイル名 # @param [Integer] spacing 文字間スペース def initialize(imgfilename, fntfilename, spacing = 0) img = Image.load(imgfilename) @bmfont_array = {} @spacing = spacing @height = 0 @line_height = 0 @baseofs = 0 @chars_count = 0 cnt = 0 # .fntファイルを1行ずつ読み込んで処理 open(fntfilename) {|file| while l = file.gets l.chomp! if l =~ /^chars count=(\d+)$/ # 文字数取得 @chars_count = $1.to_i elsif l =~ /^common (.+)$/ # フォントの縦幅やベースライン位置を取得 p = $1 p.split(' ').each do |s| if s=~ /^(\S+)=(\d+)$/ case $1 when "lineHeight" @line_height = $2.to_i when "base" @baseofs = $2.to_i end end end elsif l =~ /^char (.+) letter=\"(.)\"$/ # 1文字分の情報を取得 str, c = $1, $2 p = {} str.split(' ').each do |s| p[$1] = $2.to_i if s =~ /^(\S+)=(\d+)$/ end id, x, y, w, h = p["id"], p["x"], p["y"], p["width"], p["height"] xs, ys, xa = p["xoffset"], p["yoffset"], p["xadvance"] cimg = img.slice(x, y, w, h) # 画像切り出し @bmfont_array[id] = BMFontData.new(cimg, w, h, xs, ys, xa) @height = h if @height < h cnt += 1 end end } img.dispose end # 配列として指定した際に、BMFont情報の構造体を返す # @param [Integer] index 配列添字 def [](index) return @bmfont_array[index] end end # Windowクラスに追加するBMFont描画用メソッド module Window # BMFontを描画 # @param [Number] x 描画x座標 # @param [Number] y 描画y座標 # @param [String] str 描画文字列 # @param [Object] bmfont BMFontクラス # @param [Number] z 描画優先順位 def self.draw_bmfont(x, y, str, bmfont, z = 0) str.each_byte do |code| x1 = x + bmfont[code].xofs y1 = y + bmfont[code].yofs - bmfont.line_height + bmfont.baseofs Window.draw(x1, y1, bmfont[code].image, z) # Window.drawBoxFill(x, y, x+2, y+2, C_RED) x += bmfont[code].xadvance + bmfont.spacing end end end # Imageクラスに追加するBMFont描画用メソッド class Image # BMFontを描画 # @param [Number] x 描画x座標 # @param [Number] y 描画y座標 # @param [String] str 描画文字列 # @param [Object] bmfont BMFontクラス def draw_bmfont(x, y, str, bmfont) str.each_byte do |code| x1 = x + bmfont[code].xofs y1 = y + bmfont[code].yofs - bmfont.line_height + bmfont.baseofs self.draw(x1, y1, bmfont[code].image) x += bmfont[code].xadvance + bmfont.spacing end end end if $0 == __FILE__ #テストコード lst = [ "!\"\#$%&'()*+,-./0", "123456789:;<=>?@", "A B C D EFGHIJKLMNOP", "QRSTUVWXYZ[\]^_`", "abcdefghijklmnop", "qrstuvwxyz{|}~" ] # BMFontクラスを生成 bmfont = BMFont.new('mplus1p_heavy_0-export.png', 'mplus1p_heavy_0-export.fnt') # 画像に描画してみる例 image = Image.new(640, 240) x, y = 0, 0 lst.each do |s| image.draw_bmfont(x, y, s, bmfont) y += bmfont.height end Window.bgcolor = [96, 96, 96] Window.loop do break if Input.keyPush?(K_ESCAPE) # 画面に描画してみる例 x, y = 0, 0 lst.each do |s| Window.draw_bmfont(x, y, s, bmfont) y += bmfont.height end Window.draw(0, 240, image) end end
こんな感じの表示に。
他のスクリプトから呼ぶときは、以下のような感じ。
_main.rb
require 'dxruby' require_relative 'bmfont' bmfont = BMFont.new("mplus1p_heavy_0-export.png", "mplus1p_heavy_0-export.fnt") Window.loop do y = 20 Window.draw_bmfont(100, y, "Hello DXRuby", bmfont) y += bmfont.height Window.draw_bmfont(100, y, " & BMFont", bmfont) end
とりあえず、ファイル一式を置いときます。
_bmfontsupport_20141213.zip
同梱のBMFont画像は、M+フォントで作ったので、たぶん自由に使えるはず。
スクリプトソースは、DXRuby作者様のソースを丸写しに近いのでライセンスはよくわかりませんが、たぶん自由に使っていいんじゃないかなと。DXRubyのヘルプファイルにも、
添付のサンプルスクリプト及びドキュメント内のスクリプトは全てパブリックドメインとします。著作者人格権は行使しません。そのまま使うなり、改造するなり、著作権表示など一切いりませんのでご自由にどうぞ。と書いてありますし…。
[ ツッコむ ]
以上です。