查看: 68|回复: 0

[转载发布] [猫儿的RMXP工具箱第七弹]自动绘制迷宫墙壁

[复制链接]
  • TA的每日心情
    开心
    前天 09:55
  • 签到天数: 37 天

    连续签到: 3 天

    [LV.5]常住居民I

    2028

    主题

    32

    回帖

    7260

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    0
    卡币
    5184
    OK点
    16
    积分
    7260
    发表于 同元一千年八月七日(秋) | 显示全部楼层 |阅读模式
    有没有很眼馋RMVA、RMMV的“自动元件绘制迷宫”功能?
    有没有很苦手RMXP绘制迷宫没有自动元件的墙壁用?(XXX图块为什么没有自动元件屋顶?抓狂!!)
    有没有很纠结大量的无意义体力活浪费在填涂迷宫墙壁上?

    这一切都结束了!
    有了这个工具脚本, 所有迷宫的绘制过程,将从
    铺地板>>涂墙壁>>局部修改>>装饰
    简化为
    铺地板>>运行脚本>>局部修改>>装饰

    脚本如下:

    RUBY 代码
    1. #==============================================================================
    2. # ■ Auto_MazeWalls
    3. #------------------------------------------------------------------------------
    4. #   自动生成迷宫的墙壁,默认支持的迷宫种类有:
    5. #   农村内部(24)、教会内部(29)、城寨内部(38)、塔内部(40)、魔物城堡内部
    6. # (42)、土之洞窟(43)、炎之洞窟(44)、冰之洞窟(45)、水之洞窟(46)、矿山
    7. # (47)、体内(49),也就是不能用自动元件画墙壁的所有图块。
    8. #   使用方法:
    9. #   绘制一张只有一层(F5)层的地图,并只绘制地面的部分(即人可以走到的部分),
    10. # 其他位置全部留空——注意是留空,不要用别的东西填充了
    11. #   插入本脚本到Game_Temp(注意不是Main)之前,然后在末尾添加
    12. #
    13. #   $auto_fill = Auto_MazeWalls.new(地图编号)
    14. #   $auto_fill = fill_wall(墙壁高度)
    15. #   $auto_fill.save
    16. #   exit
    17. #
    18. #   运行完毕后请重新打开工程或相关地图。
    19. #   注释掉本脚本末尾的四行可以屏蔽该功能正常测试游戏。
    20. #   注:
    21. #   1) 地图编号不存在的话,脚本将无效直接关闭
    22. #   2) 部分图块锁定了墙高(24、29、38),墙壁高度填写任何值都是无效的
    23. #   3) 墙壁高度如填写为负数,则会生成悬空式迷宫,但前提是图块支持这种迷宫
    24. #   4) 如果有多张地图需要生成墙壁,请分别执行
    25. #   5) 如果地形有冲突(如墙高度不够),图块会重叠或空白,请手工修改冲突的地方
    26. #==============================================================================
    27. class Auto_MazeWalls
    28.   #--------------------------------------------------------------------------
    29.   # ● 初始化对像
    30.   #--------------------------------------------------------------------------  
    31.   def initialize(map_id)
    32.     @filename = sprintf("Data/Map%03d.rxdata", map_id)
    33.     ifFileTest.exist?(@filename)
    34.       @map = load_data(@filename)
    35.       @width = @map.width
    36.       @height = @map.height
    37.       setup(@map.tileset_id)
    38.     else
    39.       exit
    40.     end
    41.   end
    42.   #--------------------------------------------------------------------------
    43.   # ● 保存地图
    44.   #--------------------------------------------------------------------------  
    45.   def save
    46.     save_data(@map, @filename)
    47.   end
    48.   #--------------------------------------------------------------------------
    49.   # ● 根据图块ID获得填涂ID表
    50.   #--------------------------------------------------------------------------  
    51.   def setup(tileset_id)
    52.     case tileset_id
    53.     when24# 农村 内部
    54.       @force_height = 2
    55.       @floor = 384
    56.       @dark = 396
    57.       @covers = [387, 388, 389]
    58.       @walls_low = [-419, 420, -421]
    59.       @walls_med = [411, 412, 413]
    60.       @walls_top = [403, 404, 405]
    61.       @line_l = 395
    62.       @line_r = 397
    63.       @corner_lu = 390
    64.       @corner_ru = 391
    65.       @corner_lb = 398
    66.       @corner_rb = 399
    67.       @d_corner1 = 0
    68.       @d_corner2 = 0
    69.       @allow_deep = false
    70.       @shades = {384 => 385, 404 => 404, 412 => 401, 420 => 409}
    71.     when29# 教会 内部
    72.       @force_height = 3
    73.       @floor = 384
    74.       @dark = 409
    75.       @covers = [400, 401, 402]
    76.       @walls_low = [440, 441, 442]
    77.       @walls_med = [432, 433, 434]
    78.       @walls_rim = [424, 425, 426]
    79.       @walls_top = [416, 417, 418]
    80.       @line_l = 408
    81.       @line_r = 410
    82.       @corner_lu = 403
    83.       @corner_ru = 404
    84.       @corner_lb = 411
    85.       @corner_rb = 412
    86.       @d_corner1 = 0
    87.       @d_corner2 = 0
    88.       @allow_deep = false
    89.       @shades = {384 => 385, 417 => 417, 425 => 427, 433 => 435, 441 => 443}
    90.     when38# 城寨 内部
    91.       @force_height = 2
    92.       @floor = 384
    93.       @dark = 409
    94.       @covers = [400, 401, 402]
    95.       @walls_low = [-432, 433, -434]
    96.       @walls_med = [424, 425, 426]
    97.       @walls_top = [416, 417, 418]
    98.       @line_l = 408
    99.       @line_r = 410
    100.       @corner_lu = 403
    101.       @corner_ru = 404
    102.       @corner_lb = 411
    103.       @corner_rb = 412
    104.       @d_corner1 = 0
    105.       @d_corner2 = 0
    106.       @allow_deep = false
    107.       @shades = {384 => 386, 417 => 417, 425 => 419, 433 => 427}
    108.     when40# 塔 内部
    109.       @force_height = 0
    110.       @floor = 384
    111.       @dark = 409
    112.       @covers = [400, 401, 402]
    113.       @walls_low = [432, 433, 434]
    114.       @walls_med = [424, 425, 426]
    115.       @walls_top = [416, 417, 418]
    116.       @line_l = 408
    117.       @line_r = 410
    118.       @corner_lu = 403
    119.       @corner_ru = 404
    120.       @corner_lb = 411
    121.       @corner_rb = 412
    122.       @d_corner1 = 0
    123.       @d_corner2 = 0
    124.       @allow_deep = false
    125.       @shades = {384 => 385, 417 => 417, 425 => 427, 433 => 435}
    126.     when42# 魔物城堡 内部
    127.       @force_height = 0
    128.       @floor = 384
    129.       @dark = 409
    130.       @covers = [400, 401, 402]
    131.       @walls_low = [432, 433, 434]
    132.       @walls_med = [424, 425, 426]
    133.       @walls_top = [416, 417, 418]
    134.       @line_l = 408
    135.       @line_r = 410
    136.       @corner_lu = 403
    137.       @corner_ru = 404
    138.       @corner_lb = 411
    139.       @corner_rb = 412
    140.       @d_corner1 = 0
    141.       @d_corner2 = 0
    142.       @allow_deep = true
    143.       @depths = [437, 438, 439, 445, 446, 447, 453, 454, 455, 461, 462, 463, 469, 470, 471]
    144.       @void = 393
    145.       @flat_top = [405, 406, 407]
    146.       @flat_l = 413
    147.       @flat_r = 415
    148.       @flat_bottom = [421, 422, 423]
    149.       @d_flat1 = 0
    150.       @d_flat2 = 0
    151.       @flat_lu = 419
    152.       @flat_ru = 420
    153.       @flat_lb = 427
    154.       @flat_rb = 428
    155.       @shades = {384 => 385, 417 => 440, 425 => 448, 433 => 456}
    156.     when43..46# 属性洞穴
    157.       @force_height = 0
    158.       @floor = 384
    159.       @dark = 425
    160.       @covers = [416, 417, 418]
    161.       @walls_low = [448, 449, 450]
    162.       @walls_med = [440, 441, 442]
    163.       @walls_top = [432, 433, 434]
    164.       @line_l = 424
    165.       @line_r = 426
    166.       @corner_lu = 419
    167.       @corner_ru = 420
    168.       @corner_lb = 427
    169.       @corner_rb = 428
    170.       @d_corner1 = 435
    171.       @d_corner2 = 436
    172.       @allow_deep = true
    173.       @depths = [488, 489, 490, 496, 497, 498, 504, 505, 506,
    174.                  512, 513, 514, 520, 521, 522, 528, 529, 530]
    175.       @void = 425
    176.       @flat_top = [421, 422, 423]
    177.       @flat_l = 429
    178.       @flat_r = 431
    179.       @flat_bottom = [437, 438, 439]
    180.       @d_flat1 = 443
    181.       @d_flat2 = 444
    182.       @flat_lu = 451
    183.       @flat_ru = 452
    184.       @flat_lb = 459
    185.       @flat_rb = 460
    186.       @shades = {384 => 96, 433 => 445, 441 => 453, 449 => 461}
    187.     when47# 矿山
    188.       @force_height = 0
    189.       @floor = 384
    190.       @dark = 409
    191.       @covers = [400, 401, 402]
    192.       @walls_low = [-432, -433, -434]
    193.       @walls_med = [424, 425, 426]
    194.       @walls_top = [416, 417, 418]
    195.       @line_l = 408
    196.       @line_r = 410
    197.       @corner_lu = 403
    198.       @corner_ru = 404
    199.       @corner_lb = 411
    200.       @corner_rb = 412
    201.       @d_corner1 = 0
    202.       @d_corner2 = 0
    203.       @allow_deep = true
    204.       @depths = [429, 430, 431, 437, 438, 439, 445, 446, 447,
    205.                  453, 454, 455, 461, 462, 463, 469, 470, 471]
    206.       @void = 409
    207.       @flat_top = [405, 406, 407]
    208.       @flat_l = 413
    209.       @flat_r = 415
    210.       @flat_bottom = [421, 422, 423]
    211.       @d_flat1 = 0
    212.       @d_flat2 = 0
    213.       @flat_lu = 419
    214.       @flat_ru = 420
    215.       @flat_lb = 427
    216.       @flat_rb = 428
    217.       @shades = {384 => 385, 417 => 464, 425 => 472, 433 => 480}
    218.     when49# 体内
    219.       @force_height = 0
    220.       @floor = 384
    221.       @dark = 433
    222.       @covers = [424, 425, 426]
    223.       @walls_low = [-456, -457, -458]
    224.       @walls_med = [448, 449, 450]
    225.       @walls_top = [440, 441, 442]
    226.       @line_l = 432
    227.       @line_r = 434
    228.       @corner_lu = 435
    229.       @corner_ru = 436
    230.       @corner_lb = 443
    231.       @corner_rb = 444
    232.       @d_corner1 = 0
    233.       @d_corner2 = 0
    234.       @allow_deep = true
    235.       @depths = [461, 462, 463, 469, 470, 471, 477, 478, 479, 485, 486, 487, 493, 494, 495]
    236.       @void = 433
    237.       @flat_top = [429, 430, 431]
    238.       @flat_l = 437
    239.       @flat_r = 439
    240.       @flat_bottom = [445, 446, 447]
    241.       @d_flat1 = 0
    242.       @d_flat2 = 0
    243.       @flat_lu = 451
    244.       @flat_ru = 452
    245.       @flat_lb = 459
    246.       @flat_rb = 460
    247.       @shades = {384 => 385, 441 => 464, 449 => 472, 457 => 480}
    248.     end
    249.   end
    250.   #--------------------------------------------------------------------------
    251.   # ● 填涂墙壁
    252.   #     wall_height: 墙壁高度(负值为悬空式,可能会被图块锁定)
    253.   #--------------------------------------------------------------------------  
    254.   def fill_wall(wall_height = 2)
    255.     # 检查深渊地形
    256.     if wall_height < 0
    257.       if@allow_deep
    258.         fill_depth
    259.         return
    260.       else# 图块没有深渊地形的情况下,按2格默认高度填涂墙壁
    261.         wall_height = [2, @force_height].max
    262.       end
    263.     end
    264.     # 强制墙高生效
    265.     wall_height = @force_heightif@force_height != 0
    266.     # 勾勒地板边缘
    267.     tile_data = Table.new(@width, @height)
    268.     for i in0...@width
    269.       for j in0...@height
    270.         tile_data[i, j] = get_border_tile(i, j)
    271.       end
    272.     end
    273.     # 填涂地板边缘和F5层(背板遮挡填在F6层)
    274.     for i in0...@width
    275.       for j in0...@height
    276.         unless@covers.include?(tile_data[i, j])
    277.           if tile_data[i, j] > 0
    278.             @map.data[i, j, 0] = tile_data[i, j]
    279.           else
    280.             @map.data[i, j, 0] = @floor
    281.             @map.data[i, j, 1] = -tile_data[i, j]
    282.           end
    283.         else
    284.           @map.data[i, j - 1, 1] = tile_data[i, j]if j > 0
    285.           case tile_data[i, j]
    286.           when@covers[0]
    287.             if j < @height - 1and tile_data[i, j + 1] == @dark
    288.               @map.data[i, j, 0] = @corner_lu
    289.             else
    290.               @map.data[i, j, 0] = @line_l
    291.             end
    292.           when@covers[1]
    293.             @map.data[i, j, 0] = @dark
    294.           when@covers[2]
    295.             if j < @height - 1and tile_data[i, j + 1] == @dark
    296.               @map.data[i, j, 0] = @corner_ru
    297.             else
    298.               @map.data[i, j, 0] = @line_r
    299.             end
    300.           end
    301.         end
    302.       end
    303.     end
    304.     # 墙高及纵向墙线的增长
    305.     wall_data = {}
    306.     for i in0...@width
    307.       for j in0...@height
    308.         index = @walls_low.index(@map.data[i, j, 0])
    309.         index = @walls_low.index([email]-@map.data[/email][i, j, 1])if index == nil
    310.         if index != nil
    311.           # 不是固定墙高3的情况下
    312.           unless@force_height == 3
    313.             (wall_height - 1).timesdo |n|
    314.               wall_data[[i, j - n - 1]] = @walls_med[index]if j > n
    315.             end
    316.           else
    317.             wall_data[[i, j - 1]] = @walls_med[index]if j > 0
    318.             wall_data[[i, j - 2]] = @walls_rim[index]if j > 1
    319.           end
    320.           wall_data[[i, j - wall_height]] = @walls_top[index]if j >= wall_height
    321.         elsif@map.data[i, j, 0] == @line_land@map.data[i, j - 1, 0] == @dark
    322.           (wall_height - 1).timesdo |n|
    323.             wall_data[[i, j - n - 1]] = @line_lif j > n
    324.           end
    325.           # 交角处理
    326.           if j >= wall_height
    327.             if@map.data[i, j - wall_height, 0] == @corner_ru
    328.               wall_data[[i, j - wall_height]] = @d_corner2
    329.             else
    330.               wall_data[[i, j - wall_height]] = @corner_lb
    331.             end
    332.           end
    333.         elsif@map.data[i, j, 0] == @line_rand@map.data[i, j - 1, 0] == @dark
    334.           (wall_height - 1).timesdo |n|
    335.             wall_data[[i, j - n - 1]] = @line_rif j > n
    336.           end
    337.           # 交角处理
    338.           if j >= wall_height
    339.             if@map.data[i, j - wall_height, 0] == @corner_lu
    340.               wall_data[[i, j - wall_height]] = @d_corner1
    341.             else
    342.               wall_data[[i, j - wall_height]] = @corner_rb
    343.             end
    344.           end
    345.         end
    346.       end
    347.     end
    348.     # 填涂墙壁
    349.     wall_data.eachdo |k, v|
    350.       @map.data[k[0], k[1], 0] = v
    351.     end
    352.     # 末行处理
    353.     for i in0...@width
    354.       if@map.data[i, @height - 1, 0] == @floor
    355.         @map.data[i, @height - 1, 1] = @covers[1]
    356.       end
    357.     end
    358.     # 阴影处理
    359.     @width.timesdo |n|
    360.       i = @width - n
    361.       for j in0...@height
    362.         # 地板的阴影
    363.         if@map.data[i, j, 0] == @floor
    364.           unless@map.data[i - 1, j - 1, 0] == @flooror
    365.             @map.data[i - 1, j, 0] == @flooror
    366.             (@map.data[i - 1, j + 1, 0] == @floorand
    367.             @map.data[i - 1, j + 1, 1] != -@walls_low[2])
    368.             @map.data[i, j, 0] = @shades[@floor]
    369.           end
    370.         end
    371.         # 墙壁的阴影
    372.         if@map.data[i, j, 0] == @walls_top[1]
    373.           if@map.data[i - 1, j + 1, 0] == @line_r
    374.             for k in0..wall_height
    375.               if j + k < @height
    376.                 @map.data[i, j + k, 0] = @shades[@map.data[i, j + k, 0]]
    377.                 if@map.data[i, j + k, 1] == -@walls_low[1]
    378.                   @map.data[i, j + k, 1] = @shades[@map.data[i, j + k, 1]]
    379.                 end
    380.               end
    381.             end
    382.           end
    383.         end
    384.       end
    385.     end
    386.   end
    387.   #--------------------------------------------------------------------------
    388.   # ● 获得勾勒墙壁图块
    389.   #     x: 地图的 x 坐标
    390.   #     y: 地图的 y 坐标
    391.   #--------------------------------------------------------------------------   
    392.   def get_border_tile(x, y)
    393.     s = @map.data[x, y, 0]
    394.     return s if s != 0
    395.     case neighbor_data(x, y)
    396.     when0, 2, 128
    397.       return@dark
    398.     when1, 3, 129, 131
    399.       return@covers[1]
    400.     when16, 24, 48, 56
    401.       return@walls_low[1]
    402.     when4, 6
    403.       return@corner_ru
    404.     when64, 192
    405.       return@corner_lu
    406.     when8, 12, 14
    407.       return@line_r
    408.     when32, 96, 224
    409.       return@line_l
    410.     when80, 88, 112, 120, 208, 216, 240, 248
    411.       return@walls_low[0]
    412.     when20, 22, 28, 30, 52, 54, 60, 62
    413.       return@walls_low[2]
    414.     when65, 67, 97, 99, 193, 195, 225, 227
    415.       return@covers[0]
    416.     when5, 7, 13, 15, 133, 135, 141, 143
    417.       return@covers[2]
    418.     else
    419.       return0
    420.     end
    421.   end
    422.   #--------------------------------------------------------------------------
    423.   # ● 填涂深渊
    424.   #--------------------------------------------------------------------------  
    425.   def fill_depth
    426.     # 勾勒地板边缘
    427.     tile_data = Table.new(@width, @height)
    428.     for i in0...@width
    429.       for j in0...@height
    430.         tile_data[i, j] = get_depth_tile(i, j)
    431.       end
    432.     end
    433.     # 填涂地板边缘和F5层(高台遮挡填在F6层)
    434.     for i in0...@width
    435.       for j in0...@height
    436.         unless@flat_top.include?(tile_data[i, j])
    437.           @map.data[i, j, 0] = tile_data[i, j]
    438.         else
    439.           @map.data[i, j, 1] = tile_data[i, j]
    440.           @map.data[i, j, 0] = @void
    441.         end
    442.       end
    443.     end
    444.     # 深渊的增长
    445.     for i in0...@width
    446.       for j in0...@height
    447.         index = @flat_bottom.index(@map.data[i, j, 0])
    448.         if index != nil
    449.           for k in[email]0...@depths.length[/email] / 3
    450.             breakif@map.data[i, j + k + 1, 0] != @voidor j + k + 1 >= @height
    451.             @map.data[i, j + k + 1, 0] = @depths[k * 3 + index]
    452.           end
    453.         end
    454.       end
    455.     end
    456.   end
    457.   #--------------------------------------------------------------------------
    458.   # ● 获得勾勒深渊图块
    459.   #     x: 地图的 x 坐标
    460.   #     y: 地图的 y 坐标
    461.   #--------------------------------------------------------------------------   
    462.   def get_depth_tile(x, y)
    463.     s = @map.data[x, y, 0]
    464.     return s if s != 0
    465.     case neighbor_data(x, y)
    466.     when0
    467.       return@void
    468.     when2
    469.       return@flat_bottom[0]
    470.     when1, 3, 129, 131
    471.       return@flat_bottom[1]
    472.     when128
    473.       return@flat_bottom[2]
    474.     when8
    475.       return@flat_top[0]
    476.     when16, 24, 48, 56
    477.       return@flat_top[1]
    478.     when32
    479.       return@flat_top[2]
    480.     when4, 6, 12, 14
    481.       return@flat_l
    482.     when64, 96, 192, 224
    483.       return@flat_r
    484.     when65, 67, 97, 99, 193, 195, 225, 227
    485.       return@flat_rb
    486.     when5, 7, 13, 15, 133, 135, 141, 143
    487.       return@flat_lb
    488.     when80, 88, 112, 120, 208, 216, 240, 248
    489.       return@flat_ru
    490.     when20, 22, 28, 30, 52, 54, 60, 62
    491.       return@flat_lu
    492.     else
    493.       return0
    494.     end
    495.   end
    496.   #--------------------------------------------------------------------------
    497.   # ● 获得图块的邻近值
    498.   #     x: 地图的 x 坐标
    499.   #     y: 地图的 y 坐标
    500.   #--------------------------------------------------------------------------   
    501.   def neighbor_data(x, y)
    502.     neighbor = [0, 0, 0, 0, 0, 0, 0, 0]
    503.     neighbor[0] = @map.data[x-1, y-1, 0]if x > 0and y > 0
    504.     neighbor[1] = @map.data[x-1, y, 0]if x > 0
    505.     neighbor[2] = @map.data[x-1, y+1, 0]if x > 0and y < @height - 1
    506.     neighbor[3] = @map.data[x, y+1, 0]if y < @height - 1
    507.     neighbor[4] = @map.data[x+1, y+1, 0]if x < @width - 1and y < @height - 1
    508.     neighbor[5] = @map.data[x+1, y, 0]if x < @width - 1
    509.     neighbor[6] = @map.data[x+1, y-1, 0]if x < @width - 1and y > 0
    510.     neighbor[7] = @map.data[x, y-1, 0]if y > 0
    511.     neighbor.collect!{|n| n > 0 ? 1 : 0}
    512.     return neighbor.inject(0){|v, n| v = v * 2 + n}
    513.   end
    514. end
    515. # 以下为使用脚本,发布前请删除或注释
    516. $auto_fill = Auto_MazeWalls.new(1)
    517. $auto_fill.fill_wall
    518. $auto_fill.save
    519. exit
    复制代码


    效果如下:
    Before

    After

    After-2

    范例工程:



                 本帖来自P1论坛作者yang1zhi,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=388732  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    天天去同能,天天有童年!
    回复 论坛版权

    使用道具 举报

    ahome_bigavatar:guest
    ahome_bigavatar:welcomelogin
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2024-5-12 21:29 , Processed in 0.059898 second(s), 44 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表