2013/09/22(日) [n年前の日記]
#1 [ruby] Rubyにもtmxファイルを読み込むライブラリがあるらしい
マップエディタ
_Tiled Map Editor
の保存ファイル ―― tmxファイルを読み込んで解析するライブラリが Ruby にもあるらしいと知ったので、ちょっと試してみたり。環境は、Windows7 x64 + ruby 1.9.3p429 mingw32 版。
_tmx | RubyGems.org | your community gem host
_shawn42/tmx - GitHub
ライセンスは、MIT License の模様。
とりあえず、gem install tmx でインストールできた。 _nokogiri と _oj というライブラリも必要らしくて、一緒にインストールされる。
下のような感じで使えるみたい。勘で試したので自信無いけど。
分かった範囲で注意点が2つほど。
_dxruby_and_tmx_20130922.zip
最初、Window.drawTile() の sizex,sizey に、100,100 とか入れちゃって、めちゃくちゃ処理が重くなってしまった。画面サイズ程度を指定しないといかんのですな…。
Flixel に比べると、DXRuby は _カメラ が無い分、スクロール処理が面倒臭い印象も。
_tmx | RubyGems.org | your community gem host
_shawn42/tmx - GitHub
ライセンスは、MIT License の模様。
とりあえず、gem install tmx でインストールできた。 _nokogiri と _oj というライブラリも必要らしくて、一緒にインストールされる。
下のような感じで使えるみたい。勘で試したので自信無いけど。
#!ruby -Ks
# Tmxライブラリを利用して、Tmxを読み込んでみるサンプル
require 'tmx'
tmx = Tmx.load("./assets/maps/mylevel1.tmx")
# マップサイズ(縦横のタイル個数)を取得
puts "map size : #{tmx.width} x #{tmx.height}"
# タイル1つの縦横サイズを取得
puts "tile size : #{tmx.tilewidth} x #{tmx.tileheight}"
# レイヤー枚数を取得
puts "layers length : #{tmx.layers.length}"
# 全レイヤー(タイルレイヤー)の情報にアクセス
tmx.layers.each do |layer|
name = layer.name # レイヤー名
w = layer.width # レイヤーサイズ
h = layer.height
ltype = layer.type # レイヤー種類
data = layer.data # レイヤーのマップテーブル
puts "name = #{name} , #{w} x #{h} , type : #{ltype} , Data length : #{data.length}"
end
# オブジェクトレイヤーの情報にアクセス
tmx.object_groups.each do |objg|
puts "object layer name : #{objg.name}"
objg.objects.each do |o|
name = o.name
x = o.x
y = o.y
puts "#{name} , (#{x},#{y})"
end
end
先日作った tmx で試したら、以下の情報が得られた。これなら使えそう。
map size : 100 x 100 tile size : 32 x 32 layers length : 4 name = layer4 , 100 x 100 , type : tilelayer , Data length : 10000 name = layer3 , 100 x 100 , type : tilelayer , Data length : 10000 name = layer2 , 100 x 100 , type : tilelayer , Data length : 10000 name = layer1 , 100 x 100 , type : tilelayer , Data length : 10000 object layer name : objlayer ruby , (1281,160) ruby , (32,192) ruby , (33,351) (中略) ruby , (3135,1087) ruby , (2601,127) banana , (2592,1056) banana , (2160,2428) banana , (269,256) door , (3093,3136) playerborn , (161,119)
分かった範囲で注意点が2つほど。
- Tiled は、タイル番号0番が空白、タイル番号1番がタイルの一番左上のタイルなので、そのままではえてして使えない。フツー、その手の2Dゲーム用ライブラリは、一番左上のタイルを0番として扱うので、番号が1つずれちゃう。番号をずらしたデータを作り直す等の工夫が必要。
- このライブラリは、オブジェクトレイヤー上にタイルを置いていてもポリゴンデータとして変換してしまうようで、gid ―― タイル番号は得られない。各オブジェクトにつけた名前で種類を判断する等の工夫が必要。
◎ DXRubyで表示してみた。 :
#!ruby -Ks
# Tmxファイルを読み込んでDXRubyで描画するサンプル
require 'dxruby'
require 'tmx'
# BGマップデータ(二次元配列)を取得
def get_map_data(tmx, layer_name)
mapw = tmx.width
maph = tmx.height
mapdata = []
i = 0
tmx.layers.each do |layer|
next if layer.name != layer_name
maph.times do |my|
lines = []
mapw.times do |mx|
n = layer.data[i]
lines.push((n <= 0)? 0 : n - 1)
i += 1
end
mapdata.push(lines)
end
return mapdata
end
end
tmx = Tmx.load("mylevel1.tmx") # tmxファイルを読み込み・解析
# マップ用画像(32x32,256x768)とオブジェクト用画像(24x24,192x96)を読み込み
imgarr = Image.loadTiles("mylevel1_tiles.png", 256/32, 768/32)
objimgs = Image.loadTiles("item_mix_all.png", 192/24, 96/24)
# BGマップデータ(二次元配列)を取得
layers = []
layers.push(get_map_data(tmx, "layer4"))
layers.push(get_map_data(tmx, "layer3"))
layers.push(get_map_data(tmx, "layer2"))
# layers.push(get_map_data(tmx, "layer1")) # アタリ判定用
# BGマップのスクロール最大値を取得
bgxmax = tmx.tilewidth * tmx.width - 640
bgymax = tmx.tileheight * tmx.height - 480
# 画面縦横幅がタイル何個分かを取得
bgtw = 640 / tmx.tilewidth
bgth = 480 / tmx.tileheight
# オブジェクトレイヤー情報を取得
sprs = []
tmx.object_groups[0].objects.each do |obj|
x = obj.x + 16 - 12 # 配置したタイルの左下座標が得られる。左上座標ではない。
y = obj.y - 16 - 12
case obj.name
when "ruby"
sprs.push(Sprite.new(x, y, objimgs[6]))
when "banana"
sprs.push(Sprite.new(x, y, objimgs[8]))
when "playerborn"
sprs.push(Sprite.new(x, y, objimgs[16]))
when "door"
sprs.push(Sprite.new(x, y, objimgs[24]))
end
end
bx, by = 0, 0
font = Font.new(26)
framecount = 0
# メインループ
Window.loop do
break if Input.keyPush?(K_ESCAPE)
# キー入力でスクロール
old_bx = bx
old_by = by
spd = 8
bx -= spd if Input.keyDown?(K_LEFT)
bx += spd if Input.keyDown?(K_RIGHT)
by -= spd if Input.keyDown?(K_UP)
by += spd if Input.keyDown?(K_DOWN)
bx = 0 if bx < 0
by = 0 if by < 0
bx = bgxmax if bx > bgxmax
by = bgymax if by > bgymax
# スクロール移動量を記録しておく
bx_diff = bx - old_bx
by_diff = by - old_by
# BGマップを描画
bgspd = [0.25, 0.5, 1.0, 1.0] # 各BGレイヤーのスクロール速度
layers.each_with_index do |dt, i|
bgx = bx * bgspd[i]
bgy = by * bgspd[i]
Window.drawTile(0, 0, dt, imgarr, bgx, bgy, bgtw, bgth)
end
# オブジェクト座標をスクロール移動量で変更
sprs.each do |spr|
spr.x -= bx_diff
spr.y -= by_diff
end
# オブジェクトを描画
Sprite.draw(sprs) if (framecount & 0x04 == 0)
# メッセージ描画
Window.drawFont(4, 4, "←→↑↓でスクロール", font)
framecount += 1
end
こんな感じに。
一応画像も含めて置いときます。Public domain ってことで。_dxruby_and_tmx_20130922.zip
最初、Window.drawTile() の sizex,sizey に、100,100 とか入れちゃって、めちゃくちゃ処理が重くなってしまった。画面サイズ程度を指定しないといかんのですな…。
Flixel に比べると、DXRuby は _カメラ が無い分、スクロール処理が面倒臭い印象も。
[ ツッコむ ]
以上です。
