マップ描画

開発版でWindow.draw_tileを少し書き直した。
いままで描画するマップチップの数だけ描画予約をしていたのを、1つだけ予約して描画時にループして画面を作るようにした。描画予約のキューが大幅に減り、メモリの利用効率が上がったはずだ。ループ処理や演算も減ったから速くなっただろうと思ってベンチマークを取ってみたらほとんど変わらなかった。
んでも、描画予約キューが減ることでソート処理は高速化できているから、マップ描画はいまどき複数レイヤで描画するもんだし、そういう意味では確実に効果はあるだろう。と言ってもどうせ1フレームに多くて数回しか動かさないんだから、性能に対するインパクトは結局少ない。


マップ描画については現在でもサンプルには1つ入っているが、ちょっとしょぼすぎるのでなんか見た目に衝撃的なものが作れないだろうか、と考えていた。とか言っても絵も描けないし、マップエディタもないし、せいぜいツクール用の素材を拾ってきてマップを描画してみせるぐらいしかないのかなーと。
ということで少しコードを書いてみた。
画像とマップデータは First Seed Materialさま。
http://www.tekepon.net/fsm/

やっていることは昔懐かしいFreeRGSSのTilemapクラスのコードをRubyに書き直しただけで、半分ぐらいしかできていないので微妙なうえ、もとのFreeRGSSのTilemapも中途半端な品なので更に中途半端なものになっている。とりあえず水タイルの描画は面倒すぎて作っていない。複数レイヤも作っていない。ちなみにFreeRGSSのコードは影の処理とテーブルの処理ができていない。
ツクールのマップ描画は非常にややこしいことをしているから、Rubyで書くのは現実的ではない。少なくともDXRubyでRPGの背景描画をするなら独自の形式にするべきだろう。
かなり作りかけっていうかテキトーに書き捨てコードだがこんな感じになるという意味でコードを置いて置く。
これをサンプルに入れることは無いだろう。すなわちボツ。

#!ruby -Ks
require 'dxruby'
require './map013'

image = Image.load_to_array("./system/TileA1.png", 32, 24) +
        Image.load_to_array("./system/TileA2.png", 32, 24) +
        Image.load_to_array("./system/TileA3.png", 32, 16) +
        Image.load_to_array("./system/TileA4.png", 32, 30) +
        Image.load_to_array("./system/TileA5.png", 16, 32) +
        Image.load_to_array("./system/TileB.png" , 32, 32) +
        Image.load_to_array("./system/TileC.png" , 32, 32) +
        Image.load_to_array("./system/TileD.png" , 32, 32) +
        Image.load_to_array("./system/TileE.png" , 32, 32)

map = Array.new(Map.size) do Array.new(Map[0].size*2) do Array.new(Map[0][0].size*2) end end

pat_00 = [0, 0]
pat_01 = [1, 0]
pat_02 = [2, 0]
pat_03 = [3, 0]
pat_04 = [0, 1]
pat_05 = [1, 1]
pat_06 = [2, 1]
pat_07 = [3, 1]
pat_08 = [0, 2]
pat_09 = [1, 2]
pat_10 = [2, 2]
pat_11 = [3, 2]
pat_12 = [0, 3]
pat_13 = [1, 3]
pat_14 = [2, 3]
pat_15 = [3, 3]
pat_16 = [0, 4]
pat_17 = [1, 4]
pat_18 = [2, 4]
pat_19 = [3, 4]
pat_20 = [0, 5]
pat_21 = [1, 5]
pat_22 = [2, 5]
pat_23 = [3, 5]

# 基本48パターン 左上/右上/左下/右下
basic = [
    [pat_18, pat_17, pat_14, pat_13], # 0 
    [pat_02, pat_17, pat_14, pat_13], # 1 
    [pat_18, pat_03, pat_14, pat_13], # 2 
    [pat_02, pat_03, pat_14, pat_13], # 3 
    [pat_18, pat_17, pat_14, pat_07], # 4 
    [pat_02, pat_17, pat_14, pat_07], # 5 
    [pat_18, pat_03, pat_14, pat_07], # 6 
    [pat_02, pat_03, pat_14, pat_07], # 7 

    [pat_18, pat_17, pat_06, pat_13], # 8 
    [pat_02, pat_17, pat_06, pat_13], # 9 
    [pat_18, pat_03, pat_06, pat_13], # 10 
    [pat_02, pat_03, pat_06, pat_13], # 11 
    [pat_18, pat_17, pat_06, pat_07], # 12 
    [pat_02, pat_17, pat_06, pat_07], # 13 
    [pat_18, pat_03, pat_06, pat_07], # 14 
    [pat_02, pat_03, pat_06, pat_07], # 15 角境界のみパターンここまで

    [pat_16, pat_17, pat_12, pat_13], # 16 左境界パターン
    [pat_16, pat_03, pat_12, pat_13], # 17 
    [pat_16, pat_17, pat_12, pat_07], # 18 
    [pat_16, pat_03, pat_12, pat_13], # 19 

    [pat_10, pat_09, pat_14, pat_13], # 20 上境界パターン
    [pat_10, pat_09, pat_14, pat_07], # 21 
    [pat_10, pat_09, pat_06, pat_13], # 22 
    [pat_10, pat_09, pat_06, pat_07], # 23 

    [pat_18, pat_19, pat_14, pat_15], # 24 右境界パターン 
    [pat_18, pat_19, pat_06, pat_15], # 25 
    [pat_02, pat_19, pat_14, pat_15], # 26 
    [pat_02, pat_19, pat_06, pat_15], # 27 

    [pat_18, pat_17, pat_22, pat_21], # 28 下境界パターン 
    [pat_02, pat_17, pat_22, pat_21], # 29 
    [pat_18, pat_03, pat_22, pat_21], # 30 
    [pat_02, pat_03, pat_22, pat_21], # 31 

    [pat_16, pat_19, pat_12, pat_15], # 32 左右境界 
    [pat_10, pat_09, pat_22, pat_21], # 33 上下境界 

    [pat_08, pat_09, pat_12, pat_13], # 34 左・上境界
    [pat_08, pat_09, pat_12, pat_07], # 35 左・上、右下角境界

    [pat_10, pat_11, pat_14, pat_15], # 36 右・上境界
    [pat_10, pat_11, pat_06, pat_15], # 37 右・上、左下角境界

    [pat_18, pat_19, pat_22, pat_23], # 38 右・下境界
    [pat_02, pat_19, pat_22, pat_23], # 39 右・下、左上角境界

    [pat_16, pat_17, pat_20, pat_21], # 40 左・下境界
    [pat_16, pat_03, pat_20, pat_21], # 41 左・下、右上角境界

    [pat_08, pat_11, pat_12, pat_15], # 42 左・上・右境界
    [pat_08, pat_09, pat_20, pat_21], # 43 左・上・下境界
    [pat_16, pat_19, pat_20, pat_23], # 44 左・右・下境界
    [pat_10, pat_11, pat_22, pat_23], # 45 上・右・下境界

    [pat_08, pat_11, pat_20, pat_23], # 46 上下左右境界

    [[0,0],[0,0],[0,0],[0,0]]
]

# 集合16パターン、左上/右上/左下/右下、x/y
sbasic = [
    [pat_10, pat_09, pat_06, pat_05],# 0
    [pat_08, pat_09, pat_04, pat_05],# 1
    [pat_02, pat_01, pat_06, pat_05],# 2
    [pat_00, pat_01, pat_04, pat_05],# 3
    [pat_10, pat_11, pat_06, pat_07],# 4
    [pat_08, pat_11, pat_04, pat_07],# 5
    [pat_02, pat_03, pat_06, pat_07],# 6
    [pat_00, pat_03, pat_04, pat_07],# 7
    [pat_10, pat_09, pat_14, pat_13],# 8
    [pat_08, pat_09, pat_12, pat_13],# 9
    [pat_02, pat_01, pat_14, pat_13],# 10
    [pat_00, pat_01, pat_12, pat_13],# 11
    [pat_10, pat_11, pat_14, pat_15],# 12
    [pat_08, pat_11, pat_12, pat_15],# 13
    [pat_02, pat_03, pat_14, pat_15],# 14
    [pat_00, pat_03, pat_12, pat_15],# 15
]

hash = {}

(0...Map.size).each do |z|
  (0...Map[z].size).each do |y|
    (0...Map[z][y].size).each do |x|
      data = Map[z][y][x]
      if data < 256 # TileB
        map[z][y*2][x*2]     = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64
        map[z][y*2][x*2+1]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1
        map[z][y*2+1][x*2]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 32
        map[z][y*2+1][x*2+1] = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1 + 32
      elsif data < 512 # TileC
        data -= 256
        map[z][y*2][x*2]     = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64
        map[z][y*2][x*2+1]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1
        map[z][y*2+1][x*2]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 32
        map[z][y*2+1][x*2+1] = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1 + 32
      elsif data < 768 # TileD
        data -= 512
        map[z][y*2][x*2]     = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 2 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64
        map[z][y*2][x*2+1]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 2 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1
        map[z][y*2+1][x*2]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 2 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 32
        map[z][y*2+1][x*2+1] = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 2 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1 + 32
      elsif data < 1024 # TileE
        data -= 768
        map[z][y*2][x*2]     = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 3 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64
        map[z][y*2][x*2+1]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 3 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1
        map[z][y*2+1][x*2]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 3 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 32
        map[z][y*2+1][x*2+1] = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + 16 * 32 + 32 * 32 * 3 + (data/128)*16 + (data%8)*2 + (data % 128) / 8 * 64 + 1 + 32
      elsif 1536 <= data && data < 1664 # TileA5 床タイル
        data -= 1538
        map[z][y*2][x*2]     = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + (data%8)*2 + data / 8 * 32
        map[z][y*2][x*2+1]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + (data%8)*2 + data / 8 * 32 + 1
        map[z][y*2+1][x*2]   = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + (data%8)*2 + data / 8 * 32 + 16
        map[z][y*2+1][x*2+1] = 32 * 24 + 32 * 24 + 32 * 16 + 32 * 30 + (data%8)*2 + data / 8 * 32 + 1 + 16
      elsif 2816 <= data and data < 4352 # TileA2 地形タイル
        offset = (data - 2816) / 48
        pattern = (data - 2816) % 48
        map[z][y*2][x*2]     = basic[pattern][0][0] + basic[pattern][0][1] * 32 + (offset % 8) * 4 + (offset / 8) * 6 * 32 + 32 * 24
        map[z][y*2][x*2+1]   = basic[pattern][1][0] + basic[pattern][1][1] * 32 + (offset % 8) * 4 + (offset / 8) * 6 * 32 + 32 * 24
        map[z][y*2+1][x*2]   = basic[pattern][2][0] + basic[pattern][2][1] * 32 + (offset % 8) * 4 + (offset / 8) * 6 * 32 + 32 * 24
        map[z][y*2+1][x*2+1] = basic[pattern][3][0] + basic[pattern][3][1] * 32 + (offset % 8) * 4 + (offset / 8) * 6 * 32 + 32 * 24
      elsif 4352 <= data && data < 5888 # TileA3 壁タイル
        offset = (data - 4352) / 48
        pattern = (data - 4352) % 48
        map[z][y*2][x*2]     = sbasic[pattern][0][0] + sbasic[pattern][0][1] * 32 + (offset % 8) * 4 + (offset / 8) * 4 * 32 + 32 * 24 + 32 * 24
        map[z][y*2][x*2+1]   = sbasic[pattern][1][0] + sbasic[pattern][1][1] * 32 + (offset % 8) * 4 + (offset / 8) * 4 * 32 + 32 * 24 + 32 * 24
        map[z][y*2+1][x*2]   = sbasic[pattern][2][0] + sbasic[pattern][2][1] * 32 + (offset % 8) * 4 + (offset / 8) * 4 * 32 + 32 * 24 + 32 * 24
        map[z][y*2+1][x*2+1] = sbasic[pattern][3][0] + sbasic[pattern][3][1] * 32 + (offset % 8) * 4 + (offset / 8) * 4 * 32 + 32 * 24 + 32 * 24
      elsif 5888 <= data # TileA4 壁タイル
        offset = (data - 5888) / 48
        pattern = (data - 5888) % 48
        if (offset / 8) % 2 == 0
          map[z][y*2][x*2]     = basic[pattern][0][0] + basic[pattern][0][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 32 * 24 + 32 * 24 + 32 * 16
          map[z][y*2][x*2+1]   = basic[pattern][1][0] + basic[pattern][1][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 32 * 24 + 32 * 24 + 32 * 16
          map[z][y*2+1][x*2]   = basic[pattern][2][0] + basic[pattern][2][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 32 * 24 + 32 * 24 + 32 * 16
          map[z][y*2+1][x*2+1] = basic[pattern][3][0] + basic[pattern][3][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 32 * 24 + 32 * 24 + 32 * 16
        else
          map[z][y*2][x*2]     = sbasic[pattern][0][0] + sbasic[pattern][0][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 6 * 32 + 32 * 24 + 32 * 24 + 32 * 16
          map[z][y*2][x*2+1]   = sbasic[pattern][1][0] + sbasic[pattern][1][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 6 * 32 + 32 * 24 + 32 * 24 + 32 * 16
          map[z][y*2+1][x*2]   = sbasic[pattern][2][0] + sbasic[pattern][2][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 6 * 32 + 32 * 24 + 32 * 24 + 32 * 16
          map[z][y*2+1][x*2+1] = sbasic[pattern][3][0] + sbasic[pattern][3][1] * 32 + (offset % 8) * 4 + (offset / 16) * 10 * 32 + 6 * 32 + 32 * 24 + 32 * 24 + 32 * 16
        end
      else
        hash[data] = 1
      end
      
    end
  end
end

x = 0
y = 0
Window.loop do
x += 1
y += 1
  (0..2).each do |z|
    Window.draw_tile(0, 0, map[z], image, x, y, 40, 30, z)
  end
end

「require './map013'」というのはサンプルマップデータをFreeRGSSでMarshal.loadしてTable→Array化して出力したデータ。
こういうときぐらいしか使い道がないライブラリであるが、ひょっとしたらVX Aceを買ってRGSS3互換を目指しちゃったりするかもしれないし、しないかもしれない。
変わったのか変わってないのかすらわからんからやっぱり買わないと思う。