查看: 6488|回复: 9

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

[复制链接]

遠航の猫咪

梦石
3
星屑
26947
在线时间
2423 小时
注册时间
2005-10-15
回帖
987

开拓者

发表于 2016-1-26 00:33:44 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

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

×
有没有很眼馋RMVA、RMMV的“自动元件绘制迷宫”功能?
有没有很苦手RMXP绘制迷宫没有自动元件的墙壁用?(XXX图块为什么没有自动元件屋顶?抓狂!!)
有没有很纠结大量的无意义体力活浪费在填涂迷宫墙壁上?

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

脚本如下:

[pre lang="ruby"]#==============================================================================
# ■ Auto_MazeWalls
#------------------------------------------------------------------------------
#   自动生成迷宫的墙壁,默认支持的迷宫种类有:
#   农村内部(24)、教会内部(29)、城寨内部(38)、塔内部(40)、魔物城堡内部
# (42)、土之洞窟(43)、炎之洞窟(44)、冰之洞窟(45)、水之洞窟(46)、矿山
# (47)、体内(49),也就是不能用自动元件画墙壁的所有图块。
#   使用方法:
#   绘制一张只有一层(F5)层的地图,并只绘制地面的部分(即人可以走到的部分),
# 其他位置全部留空——注意是留空,不要用别的东西填充了
#   插入本脚本到Game_Temp(注意不是Main)之前,然后在末尾添加
#
#   $auto_fill = Auto_MazeWalls.new(地图编号)
#   $auto_fill = fill_wall(墙壁高度)
#   $auto_fill.save
#   exit
#
#   运行完毕后请重新打开工程或相关地图。
#   注释掉本脚本末尾的四行可以屏蔽该功能正常测试游戏。
#   注:
#   1) 地图编号不存在的话,脚本将无效直接关闭
#   2) 部分图块锁定了墙高(24、29、38),墙壁高度填写任何值都是无效的
#   3) 墙壁高度如填写为负数,则会生成悬空式迷宫,但前提是图块支持这种迷宫
#   4) 如果有多张地图需要生成墙壁,请分别执行
#   5) 如果地形有冲突(如墙高度不够),图块会重叠或空白,请手工修改冲突的地方
#==============================================================================

class Auto_MazeWalls
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------  
  def initialize(map_id)
    @filename = sprintf("Data/Map%03d.rxdata", map_id)
    if FileTest.exist?(@filename)
      @map = load_data(@filename)
      @width = @map.width
      @height = @map.height
      setup(@map.tileset_id)
    else
      exit
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 保存地图
  #--------------------------------------------------------------------------  
  def save
    save_data(@map, @filename)
  end
  
  #--------------------------------------------------------------------------
  # ● 根据图块ID获得填涂ID表
  #--------------------------------------------------------------------------  
  def setup(tileset_id)
    case tileset_id
    when 24 # 农村 内部
      @force_height = 2
      @floor = 384
      @dark = 396
      @covers = [387, 388, 389]
      @walls_low = [-419, 420, -421]
      @walls_med = [411, 412, 413]
      @walls_top = [403, 404, 405]
      @line_l = 395
      @line_r = 397
      @corner_lu = 390
      @corner_ru = 391
      @corner_lb = 398
      @corner_rb = 399
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = false
      @shades = {384 => 385, 404 => 404, 412 => 401, 420 => 409}
    when 29 # 教会 内部
      @force_height = 3
      @floor = 384
      @dark = 409
      @covers = [400, 401, 402]
      @walls_low = [440, 441, 442]
      @walls_med = [432, 433, 434]
      @walls_rim = [424, 425, 426]
      @walls_top = [416, 417, 418]
      @line_l = 408
      @line_r = 410
      @corner_lu = 403
      @corner_ru = 404
      @corner_lb = 411
      @corner_rb = 412
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = false
      @shades = {384 => 385, 417 => 417, 425 => 427, 433 => 435, 441 => 443}
    when 38 # 城寨 内部
      @force_height = 2
      @floor = 384
      @dark = 409
      @covers = [400, 401, 402]
      @walls_low = [-432, 433, -434]
      @walls_med = [424, 425, 426]
      @walls_top = [416, 417, 418]
      @line_l = 408
      @line_r = 410
      @corner_lu = 403
      @corner_ru = 404
      @corner_lb = 411
      @corner_rb = 412
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = false
      @shades = {384 => 386, 417 => 417, 425 => 419, 433 => 427}
    when 40 # 塔 内部
      @force_height = 0
      @floor = 384
      @dark = 409
      @covers = [400, 401, 402]
      @walls_low = [432, 433, 434]
      @walls_med = [424, 425, 426]
      @walls_top = [416, 417, 418]
      @line_l = 408
      @line_r = 410
      @corner_lu = 403
      @corner_ru = 404
      @corner_lb = 411
      @corner_rb = 412
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = false
      @shades = {384 => 385, 417 => 417, 425 => 427, 433 => 435}
    when 42 # 魔物城堡 内部
      @force_height = 0
      @floor = 384
      @dark = 409
      @covers = [400, 401, 402]
      @walls_low = [432, 433, 434]
      @walls_med = [424, 425, 426]
      @walls_top = [416, 417, 418]
      @line_l = 408
      @line_r = 410
      @corner_lu = 403
      @corner_ru = 404
      @corner_lb = 411
      @corner_rb = 412
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = true
      @depths = [437, 438, 439, 445, 446, 447, 453, 454, 455, 461, 462, 463, 469, 470, 471]
      @void = 393
      @flat_top = [405, 406, 407]
      @flat_l = 413
      @flat_r = 415
      @flat_bottom = [421, 422, 423]
      @d_flat1 = 0
      @d_flat2 = 0
      @flat_lu = 419
      @flat_ru = 420
      @flat_lb = 427
      @flat_rb = 428
      @shades = {384 => 385, 417 => 440, 425 => 448, 433 => 456}
    when 43..46 # 属性洞穴
      @force_height = 0
      @floor = 384
      @dark = 425
      @covers = [416, 417, 418]
      @walls_low = [448, 449, 450]
      @walls_med = [440, 441, 442]
      @walls_top = [432, 433, 434]
      @line_l = 424
      @line_r = 426
      @corner_lu = 419
      @corner_ru = 420
      @corner_lb = 427
      @corner_rb = 428
      @d_corner1 = 435
      @d_corner2 = 436
      @allow_deep = true
      @depths = [488, 489, 490, 496, 497, 498, 504, 505, 506,
                 512, 513, 514, 520, 521, 522, 528, 529, 530]
      @void = 425
      @flat_top = [421, 422, 423]
      @flat_l = 429
      @flat_r = 431
      @flat_bottom = [437, 438, 439]
      @d_flat1 = 443
      @d_flat2 = 444
      @flat_lu = 451
      @flat_ru = 452
      @flat_lb = 459
      @flat_rb = 460
      @shades = {384 => 96, 433 => 445, 441 => 453, 449 => 461}
    when 47 # 矿山
      @force_height = 0
      @floor = 384
      @dark = 409
      @covers = [400, 401, 402]
      @walls_low = [-432, -433, -434]
      @walls_med = [424, 425, 426]
      @walls_top = [416, 417, 418]
      @line_l = 408
      @line_r = 410
      @corner_lu = 403
      @corner_ru = 404
      @corner_lb = 411
      @corner_rb = 412
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = true
      @depths = [429, 430, 431, 437, 438, 439, 445, 446, 447,
                 453, 454, 455, 461, 462, 463, 469, 470, 471]
      @void = 409
      @flat_top = [405, 406, 407]
      @flat_l = 413
      @flat_r = 415
      @flat_bottom = [421, 422, 423]
      @d_flat1 = 0
      @d_flat2 = 0
      @flat_lu = 419
      @flat_ru = 420
      @flat_lb = 427
      @flat_rb = 428
      @shades = {384 => 385, 417 => 464, 425 => 472, 433 => 480}
    when 49 # 体内
      @force_height = 0
      @floor = 384
      @dark = 433
      @covers = [424, 425, 426]
      @walls_low = [-456, -457, -458]
      @walls_med = [448, 449, 450]
      @walls_top = [440, 441, 442]
      @line_l = 432
      @line_r = 434
      @corner_lu = 435
      @corner_ru = 436
      @corner_lb = 443
      @corner_rb = 444
      @d_corner1 = 0
      @d_corner2 = 0
      @allow_deep = true
      @depths = [461, 462, 463, 469, 470, 471, 477, 478, 479, 485, 486, 487, 493, 494, 495]
      @void = 433
      @flat_top = [429, 430, 431]
      @flat_l = 437
      @flat_r = 439
      @flat_bottom = [445, 446, 447]
      @d_flat1 = 0
      @d_flat2 = 0
      @flat_lu = 451
      @flat_ru = 452
      @flat_lb = 459
      @flat_rb = 460
      @shades = {384 => 385, 441 => 464, 449 => 472, 457 => 480}
    end
  end

  #--------------------------------------------------------------------------
  # ● 填涂墙壁
  #     wall_height: 墙壁高度(负值为悬空式,可能会被图块锁定)
  #--------------------------------------------------------------------------  
  def fill_wall(wall_height = 2)
    # 检查深渊地形
    if wall_height < 0
      if @allow_deep
        fill_depth
        return
      else # 图块没有深渊地形的情况下,按2格默认高度填涂墙壁
        wall_height = [2, @force_height].max
      end
    end
    # 强制墙高生效
    wall_height = @force_height if @force_height != 0
    # 勾勒地板边缘
    tile_data = Table.new(@width, @height)
    for i in 0...@width
      for j in 0...@height
        tile_data[i, j] = get_border_tile(i, j)
      end
    end
    # 填涂地板边缘和F5层(背板遮挡填在F6层)
    for i in 0...@width
      for j in 0...@height
        unless @covers.include?(tile_data[i, j])
          if tile_data[i, j] > 0
            @map.data[i, j, 0] = tile_data[i, j]
          else
            @map.data[i, j, 0] = @floor
            @map.data[i, j, 1] = -tile_data[i, j]
          end
        else
          @map.data[i, j - 1, 1] = tile_data[i, j] if j > 0
          case tile_data[i, j]
          when @covers[0]
            if j < @height - 1 and tile_data[i, j + 1] == @dark
              @map.data[i, j, 0] = @corner_lu
            else
              @map.data[i, j, 0] = @line_l
            end
          when @covers[1]
            @map.data[i, j, 0] = @dark
          when @covers[2]
            if j < @height - 1 and tile_data[i, j + 1] == @dark
              @map.data[i, j, 0] = @corner_ru
            else
              @map.data[i, j, 0] = @line_r
            end
          end
        end
      end
    end
    # 墙高及纵向墙线的增长
    wall_data = {}
    for i in 0...@width
      for j in 0...@height
        index = @walls_low.index(@map.data[i, j, 0])
        index = @walls_low.index(-@map.data[i, j, 1]) if index == nil
        if index != nil
          # 不是固定墙高3的情况下
          unless @force_height == 3
            (wall_height - 1).times do |n|
              wall_data[[i, j - n - 1]] = @walls_med[index] if j > n
            end
          else
            wall_data[[i, j - 1]] = @walls_med[index] if j > 0
            wall_data[[i, j - 2]] = @walls_rim[index] if j > 1
          end
          wall_data[[i, j - wall_height]] = @walls_top[index] if j >= wall_height
        elsif @map.data[i, j, 0] == @line_l and @map.data[i, j - 1, 0] == @dark
          (wall_height - 1).times do |n|
            wall_data[[i, j - n - 1]] = @line_l if j > n
          end
          # 交角处理
          if j >= wall_height
            if @map.data[i, j - wall_height, 0] == @corner_ru
              wall_data[[i, j - wall_height]] = @d_corner2
            else
              wall_data[[i, j - wall_height]] = @corner_lb
            end
          end
        elsif @map.data[i, j, 0] == @line_r and @map.data[i, j - 1, 0] == @dark
          (wall_height - 1).times do |n|
            wall_data[[i, j - n - 1]] = @line_r if j > n
          end
          # 交角处理
          if j >= wall_height
            if @map.data[i, j - wall_height, 0] == @corner_lu
              wall_data[[i, j - wall_height]] = @d_corner1
            else
              wall_data[[i, j - wall_height]] = @corner_rb
            end
          end
        end
      end
    end
    # 填涂墙壁
    wall_data.each do |k, v|
      @map.data[k[0], k[1], 0] = v
    end
    # 末行处理
    for i in 0...@width
      if @map.data[i, @height - 1, 0] == @floor
        @map.data[i, @height - 1, 1] = @covers[1]
      end
    end
    # 阴影处理
    @width.times do |n|
      i = @width - n
      for j in 0...@height
        # 地板的阴影
        if @map.data[i, j, 0] == @floor
          unless @map.data[i - 1, j - 1, 0] == @floor or
            @map.data[i - 1, j, 0] == @floor or
            (@map.data[i - 1, j + 1, 0] == @floor and
            @map.data[i - 1, j + 1, 1] != -@walls_low[2])
            @map.data[i, j, 0] = @shades[@floor]
          end
        end
        # 墙壁的阴影
        if @map.data[i, j, 0] == @walls_top[1]
          if @map.data[i - 1, j + 1, 0] == @line_r
            for k in 0..wall_height
              if j + k < @height
                @map.data[i, j + k, 0] = @shades[@map.data[i, j + k, 0]]
                if @map.data[i, j + k, 1] == -@walls_low[1]
                  @map.data[i, j + k, 1] = @shades[@map.data[i, j + k, 1]]
                end
              end
            end
          end
        end
      end
    end
  end

  #--------------------------------------------------------------------------
  # ● 获得勾勒墙壁图块
  #     x: 地图的 x 坐标
  #     y: 地图的 y 坐标
  #--------------------------------------------------------------------------   
  def get_border_tile(x, y)
    s = @map.data[x, y, 0]
    return s if s != 0
    case neighbor_data(x, y)
    when 0, 2, 128
      return @dark
    when 1, 3, 129, 131
      return @covers[1]
    when 16, 24, 48, 56
      return @walls_low[1]
    when 4, 6
      return @corner_ru
    when 64, 192
      return @corner_lu
    when 8, 12, 14
      return @line_r
    when 32, 96, 224
      return @line_l
    when 80, 88, 112, 120, 208, 216, 240, 248
      return @walls_low[0]
    when 20, 22, 28, 30, 52, 54, 60, 62
      return @walls_low[2]
    when 65, 67, 97, 99, 193, 195, 225, 227
      return @covers[0]
    when 5, 7, 13, 15, 133, 135, 141, 143
      return @covers[2]
    else
      return 0
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 填涂深渊
  #--------------------------------------------------------------------------  
  def fill_depth
    # 勾勒地板边缘
    tile_data = Table.new(@width, @height)
    for i in 0...@width
      for j in 0...@height
        tile_data[i, j] = get_depth_tile(i, j)
      end
    end
    # 填涂地板边缘和F5层(高台遮挡填在F6层)
    for i in 0...@width
      for j in 0...@height
        unless @flat_top.include?(tile_data[i, j])
          @map.data[i, j, 0] = tile_data[i, j]
        else
          @map.data[i, j, 1] = tile_data[i, j]
          @map.data[i, j, 0] = @void
        end
      end
    end
    # 深渊的增长
    for i in 0...@width
      for j in 0...@height
        index = @flat_bottom.index(@map.data[i, j, 0])
        if index != nil
          for k in 0...@depths.length / 3
            break if @map.data[i, j + k + 1, 0] != @void or j + k + 1 >= @height
            @map.data[i, j + k + 1, 0] = @depths[k * 3 + index]
          end
        end
      end
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 获得勾勒深渊图块
  #     x: 地图的 x 坐标
  #     y: 地图的 y 坐标
  #--------------------------------------------------------------------------   
  def get_depth_tile(x, y)
    s = @map.data[x, y, 0]
    return s if s != 0
    case neighbor_data(x, y)
    when 0
      return @void
    when 2
      return @flat_bottom[0]
    when 1, 3, 129, 131
      return @flat_bottom[1]
    when 128
      return @flat_bottom[2]
    when 8
      return @flat_top[0]
    when 16, 24, 48, 56
      return @flat_top[1]
    when 32
      return @flat_top[2]
    when 4, 6, 12, 14
      return @flat_l
    when 64, 96, 192, 224
      return @flat_r
    when 65, 67, 97, 99, 193, 195, 225, 227
      return @flat_rb
    when 5, 7, 13, 15, 133, 135, 141, 143
      return @flat_lb
    when 80, 88, 112, 120, 208, 216, 240, 248
      return @flat_ru
    when 20, 22, 28, 30, 52, 54, 60, 62
      return @flat_lu
    else
      return 0
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 获得图块的邻近值
  #     x: 地图的 x 坐标
  #     y: 地图的 y 坐标
  #--------------------------------------------------------------------------   
  def neighbor_data(x, y)
    neighbor = [0, 0, 0, 0, 0, 0, 0, 0]
    neighbor[0] = @map.data[x-1, y-1, 0] if x > 0 and y > 0
    neighbor[1] = @map.data[x-1, y, 0] if x > 0
    neighbor[2] = @map.data[x-1, y+1, 0] if x > 0 and y < @height - 1
    neighbor[3] = @map.data[x, y+1, 0] if y < @height - 1
    neighbor[4] = @map.data[x+1, y+1, 0] if x < @width - 1 and y < @height - 1
    neighbor[5] = @map.data[x+1, y, 0] if x < @width - 1
    neighbor[6] = @map.data[x+1, y-1, 0] if x < @width - 1 and y > 0
    neighbor[7] = @map.data[x, y-1, 0] if y > 0
    neighbor.collect!{|n| n > 0 ? 1 : 0}
    return neighbor.inject(0) {|v, n| v = v * 2 + n}
  end
end
# 以下为使用脚本,发布前请删除或注释
$auto_fill = Auto_MazeWalls.new(1)
$auto_fill.fill_wall
$auto_fill.save
exit[/pre]

效果如下:
Before

铺地板

铺地板

After

自动涂墙

自动涂墙

After-2

自动涂墙(高台式)

自动涂墙(高台式)

范例工程:
AutoFillMap.zip (207.12 KB, 下载次数: 224, 售价: 2 星屑)

评分

参与人数 9星屑 +983 收起 理由
89444640 + 100 画地图从此变成一种有趣的活动.
W.Q.C. + 8 可怕
lxzuz + 15 塞糖
jklpgh + 60 66666666
kuerlulu + 70 可怕
VIPArcher + 100 可怕
RyanBern + 300 已加入XP图书馆豪华套餐
喵呜喵5 + 220 前辈出现的那么突然……
MeowSnow + 110 (っ´ω`c) 厉害

查看全部评分

SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
梦石
0
星屑
12161
在线时间
4435 小时
注册时间
2014-4-11
回帖
5616

开拓者

发表于 2016-1-26 10:16:47 | 显示全部楼层
先收下了。


看1楼感觉和这个差不多吧
随机地图生成脚本 v0.80   by tonbi
#
#     汉化修改 66RPG bbschat(2006.1.2)
#
#     随机地图自动生成脚本。
#
回复

使用道具 举报

遠航の猫咪

梦石
3
星屑
26947
在线时间
2423 小时
注册时间
2005-10-15
回帖
987

开拓者

 楼主| 发表于 2016-1-26 13:33:34 来自手机 | 显示全部楼层
yang1zhi 发表于 2016-1-26 10:16
先收下了。



不一样,那个是完全凭空生成地形和相应的迷宫,需要设置一堆事件条件,是内嵌插件型脚本。
我这个是交给你自己决定迷宫的地形,脚本省去体力活填充墙壁的时间,是辅助工具型脚本。
回复

使用道具 举报

梦石
0
星屑
898
在线时间
13 小时
注册时间
2010-12-20
回帖
3
发表于 2016-5-23 02:19:29 | 显示全部楼层
求助。。提示280行错误
QQ图片20160523021840.jpg
回复

使用道具 举报

梦石
0
星屑
898
在线时间
13 小时
注册时间
2010-12-20
回帖
3
发表于 2016-5-23 02:26:22 | 显示全部楼层
yxc990831 发表于 2016-5-23 02:19
求助。。提示280行错误

还有一个问题就是范例地图测试游戏自动弹出,即闪退
回复

使用道具 举报

梦石
0
星屑
898
在线时间
13 小时
注册时间
2010-12-20
回帖
3
发表于 2016-5-23 03:27:58 | 显示全部楼层
yxc990831 发表于 2016-5-23 02:26
还有一个问题就是范例地图测试游戏自动弹出,即闪退

不好意思,,是我没仔细看{:2_254:}
回复

使用道具 举报

梦石
0
星屑
60
在线时间
19 小时
注册时间
2008-1-23
回帖
65
发表于 2016-6-5 18:58:37 | 显示全部楼层
QQ圖片20160605185727.jpg

求教,是我操作错误吗?
  1.          for k in [email]0...@depths.length[/email] / 3
复制代码
是这句
回复

使用道具 举报

梦石
0
星屑
726
在线时间
2 小时
注册时间
2016-8-4
回帖
3
发表于 2016-8-4 12:54:47 | 显示全部楼层
不会用啊

点评

编辑器下发就有 (地图ID)-002:Map002 ,你把脚本改成$auto_fill = Auto_MazeWalls.new(2) 然后 进入游戏 自动退出 不管他 点保存游戏 在重新打开工程 就OK  发表于 2016-9-6 14:29
我也不会用(以防盖太多楼找不到)  发表于 2016-9-4 14:00
回复 1 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部