Project1

标题: 【加工】PNG Map Extractor for XP-地图PNG图片导出器Ver 1.3 [打印本页]

作者: RyanBern    时间: 2014-12-6 01:21
标题: 【加工】PNG Map Extractor for XP-地图PNG图片导出器Ver 1.3
本帖最后由 RyanBern 于 2016-7-10 16:02 编辑

深夜忙到很晚搞出来这个东西,这个脚本的功能就是导出游戏地图,把它制作成一个PNG文件。
类似的脚本在论坛上已经出现过,不过时间过于久远,而且不能直接在XP上使用。昨天在提问区看到一个提问帖,就拿来做了。用的是之前论坛上的脚本。
做的很仓促,所以有瑕疵的地方我会尽力改正。主要修复的问题就是自动元件描绘的问题,大家都知道只有XP才有自动元件,而且由于自动元件是程序自动生成,我们看不到源码,所以画起来十分麻烦,代码中大家也可以看到写得不是很简洁,不过我已经尽力了。
还有一个问题,就是地图导出会比较慢,所以尽量不要使用太大的地图。
感觉这玩意还可以配合ULDS系统进行截图。
使用前请下载这个DLL,并把它复制到工程的根目录下:
MGC_PNG.rar (87.39 KB, 下载次数: 354)
  1. #==============================================================================
  2. # PNG Map Extractor Ver 1.3
  3. #------------------------------------------------------------------------------
  4. # Modified By :RyanBern
  5. # 注:此脚本为部分原创,增加了一个描绘自动元件的功能(原版本无法描绘自动元件)
  6. #     引用的DLL: MGC_PNG(By MGC),使用前请将MGC_PNG.dll复制到根目录下。
  7. #------------------------------------------------------------------------------
  8. # 功能:可以将地图导出成 PNG 文件格式(不含主角和事件)
  9. #       也有直接将 Bitmap 对象输出为图片的功能
  10. #------------------------------------------------------------------------------
  11. # 使用方法:
  12. #   对 Bitmap 对象使用 save_as_png(filename) 即可在指定目标文件夹中生成 PNG 文件。
  13. #   直接调用 Picture_Map.make_all 即可生成全部地图的 PNG 文件
  14. #   如果想单独生成某一ID的地图可以调用 Picture_Map.make_one(id[, layers])
  15. #   后面的layers为指定图层,默认为整个地图,如果只需要生成1号地图第1层和第2层
  16. #   的PNG,可以用 Picture_Map.make_one(1, [0, 1]),注意图层的顺序不要反了。
  17. #   有关设置请改 module Picture_Map下的常量
  18. #------------------------------------------------------------------------------
  19. # 友情提示:
  20. #   当地图很大时,处理会比较慢,建议不要放置过大的地图。否则程序会因长时间没有
  21. #   响应而终止。
  22. #   输出的文件名统一为Map+3位地图ID的形式。
  23. #------------------------------------------------------------------------------
  24. # 更新记录:
  25. #   Ver 1.1 :采用外接DLL,生成PNG更迅速
  26. #   Ver 1.2 :增加分层描绘功能
  27. #   Ver 1.3 :修复BUG(感谢pjy612的测试)
  28. #==============================================================================
  29. module Picture_Map
  30.   
  31.   # 是否自动缩放,如果设置为 true ,则输出的png不会超过以下的宽和高
  32.   AUTO_CHANGE = false
  33.   
  34.   # 自动缩放的宽度
  35.   AUTO_WIDTH = 800
  36.   
  37.   # 自动缩放的高度
  38.   AUTO_HEIGHT = 1024
  39.   
  40.   # 输出的文件夹(英文名称)
  41.   DIR_OUT = "OutMaps/"
  42.   def self.make_all
  43.     mapinfos = load_data("Data/MapInfos.rxdata")
  44.     for id in 1...mapinfos.size+1
  45.       next if mapinfos[id] == nil
  46.       out_filename = sprintf("Map%03d.png", id)
  47.       bitmap = make_map_bitmap(id)
  48.       if bitmap != nil
  49.         bitmap.save_as_png(DIR_OUT + out_filename)
  50.         bitmap.dispose
  51.       end
  52.     end
  53.   end
  54.   def self.make_one(id, layers = [0, 1, 2])
  55.     mapinfos = load_data("Data/MapInfos.rxdata")
  56.     return if mapinfos[id] == nil
  57.     out_filename = sprintf("Map%03d.png", id)
  58.     bitmap = make_map_bitmap(id, layers)
  59.     if bitmap != nil
  60.       bitmap.save_as_png(DIR_OUT + out_filename)
  61.       bitmap.dispose
  62.     end
  63.   end
  64.   def self.make_map_bitmap(id, layers = [0, 1, 2])
  65.     if FileTest.exist?(sprintf("#{DIR_OUT}Map%03d.png", id))        
  66.       return nil
  67.     end
  68.     filename = sprintf("Data/Map%03d.rxdata", id)
  69.     return nil unless FileTest.exist?(filename)
  70.     map = load_data(filename)
  71.     map_data = map.data
  72.     tilesets = $data_tilesets[map.tileset_id]
  73.     tileset_name = tilesets.tileset_name
  74.     tileset = RPG::Cache.tileset(tileset_name)
  75.     autotiles = []
  76.     for i in 0..6
  77.       autotile_name = tilesets.autotile_names[i]
  78.       autotiles[i] = RPG::Cache.autotile(autotile_name)        
  79.     end
  80.     map_bitmap = Bitmap.new(map.width * 32, map.height * 32)
  81.     for y in 0...map.height
  82.       for x in 0...map.width
  83.         new_orders = []
  84.         layers.each do |z|
  85.           new_orders << map_data[x, y, z]
  86.         end
  87.         for j in 1...new_orders.size
  88.           k = j - 1
  89.           temp = new_orders[j]
  90.           while k >= 0
  91.             if tilesets.priorities[new_orders[k]] > tilesets.priorities[temp]
  92.               new_orders[k+1] = new_orders[k]
  93.               k -= 1
  94.             else
  95.               break
  96.             end
  97.           end
  98.           new_orders[k+1] = temp if k != j - 1
  99.         end
  100.         new_orders.each do |tile_num|
  101.           begin
  102.             next if tile_num == nil
  103.             if tile_num < 384
  104.               if tile_num >= 48    #48  
  105.                 self.make_autotile(x * 32, y * 32, map_bitmap, autotiles[tile_num / 48 - 1], tile_num % 48)
  106.               end
  107.             else
  108.               tile_num -= 384
  109.               src_rect = Rect.new(tile_num % 8 * 32, tile_num / 8 * 32, 32, 32)
  110.               map_bitmap.blt(x * 32, y * 32, tileset, src_rect)
  111.             end     
  112.           rescue Hangup
  113.             p 1
  114.           end
  115.         end
  116.       end
  117.     end
  118.     if AUTO_CHANGE and (map_bitmap.width > AUTO_WIDTH or map_bitmap.height > AUTO_HEIGHT)
  119.       zoom1 = map_bitmap.width.to_f / AUTO_WIDTH.to_f
  120.       zoom2 = map_bitmap.height.to_f / AUTO_HEIGHT.to_f
  121.       zoom = zoom1 > zoom2 ? zoom1 : zoom2
  122.       w = map_bitmap.width / zoom
  123.       h = map_bitmap.height / zoom
  124.       ret_bitmap = Bitmap.new(w, h)
  125.       src_rect = Rect.new(0, 0, map_bitmap.width, map_bitmap.height)
  126.       dest_rect = Rect.new(0, 0, w, h)
  127.       ret_bitmap.stretch_blt(dest_rect, map_bitmap, src_rect)
  128.       map_bitmap = ret_bitmap
  129.     end
  130.     return map_bitmap
  131.   end
  132.   def self.make_autotile(x, y, target_bitmap, tile_bitmap, tile_num)
  133.     if tile_bitmap == nil
  134.       return
  135.     end
  136.     case tile_num
  137.     when 0...16
  138.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(32, 64, 32, 32))
  139.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 0, 16, 16)) if tile_num & 0x01 != 0
  140.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 0, 16, 16)) if tile_num & 0x02 != 0
  141.       target_bitmap.blt(x+16, y+16, tile_bitmap, Rect.new(80, 16, 16, 16)) if tile_num & 0x04 != 0
  142.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(64, 16, 16, 16)) if tile_num & 0x08 != 0
  143.     when 16...20
  144.       bit = tile_num - 16
  145.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 64, 32, 32))
  146.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 0, 16, 16)) if bit & 0x01 != 0
  147.       target_bitmap.blt(x+16, y+16, tile_bitmap, Rect.new(80, 16, 16, 16)) if bit & 0x02 != 0
  148.     when 20...24
  149.       bit = tile_num - 20
  150.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(32, 32, 32, 32))
  151.       target_bitmap.blt(x+16, y+16, tile_bitmap, Rect.new(80, 16, 16, 16)) if bit & 0x01 != 0
  152.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(64, 16, 16, 16)) if bit & 0x02 != 0
  153.     when 24...28
  154.       bit = tile_num - 24
  155.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 64, 32, 32))
  156.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(64, 16, 16, 16)) if bit & 0x01 != 0
  157.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 0, 16, 16)) if bit & 0x02 != 0
  158.     when 28...32
  159.       bit = tile_num - 28
  160.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(32, 96, 32, 32))
  161.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 0, 16, 16)) if bit & 0x01 != 0
  162.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 0, 16, 16)) if bit & 0x02 != 0
  163.     when 32
  164.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 64, 16, 32))
  165.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 64, 16, 32))
  166.     when 33
  167.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(32, 32, 32, 16))
  168.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(32, 112, 32, 16))
  169.     when 34...36
  170.       bit = tile_num - 34
  171.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 32, 32, 32))
  172.       target_bitmap.blt(x+16, y+16, tile_bitmap, Rect.new(80, 16, 16, 16)) if tile_num & 0x01 != 0
  173.     when 36...38
  174.       bit = tile_num - 36
  175.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 32, 32, 32))
  176.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(64, 16, 16, 16)) if tile_num & 0x01 != 0
  177.     when 38...40
  178.       bit = tile_num - 38
  179.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 96, 32, 32))
  180.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 0, 16, 16)) if tile_num & 0x01 != 0
  181.     when 40...42
  182.       bit = tile_num - 40
  183.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 96, 32, 32))
  184.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 0, 16, 16)) if tile_num & 0x01 != 0
  185.     when 42
  186.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 32, 16, 32))
  187.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 32, 16, 32))
  188.     when 43
  189.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 32, 32, 16))
  190.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(0, 112, 32, 16))
  191.     when 44
  192.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 96, 16, 32))
  193.       target_bitmap.blt(x+16, y, tile_bitmap, Rect.new(80, 96, 16, 32))
  194.     when 45
  195.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(64, 32, 32, 16))
  196.       target_bitmap.blt(x, y+16, tile_bitmap, Rect.new(64, 112, 32, 16))
  197.     when 46
  198.       target_bitmap.blt(x, y, tile_bitmap, Rect.new(0, 0, 32, 32))
  199.     end
  200.   end
  201. end
  202. #==============================================================================
  203. # ■ Bitmap
  204. #------------------------------------------------------------------------------
  205. #  关联到Bitmap。
  206. #==============================================================================
  207. class Bitmap
  208.   #--------------------------------------------------------------------------
  209.   # * Constantes
  210.   #--------------------------------------------------------------------------
  211.   CREATE_PNG = Win32API.new("MGC_PNG", "createPNG", "ll", "l")
  212.   #--------------------------------------------------------------------------
  213.   # * Méthode d'appel pour créer un fichier PNG
  214.   #     chemin : chemin + nom du fichier à créer
  215.   #--------------------------------------------------------------------------
  216.   def save_as_png(chemin)
  217.     unless chemin[/\//] then chemin = './' << chemin end
  218.     CREATE_PNG.call(self.__id__, chemin.__id__)
  219.   end
  220. end
复制代码

作者: 路路    时间: 2014-12-6 02:04
提示: 作者被禁止或删除 内容自动屏蔽
作者: chd114    时间: 2014-12-6 08:08
就是截一张世界地图的意思?
作者: stevenrock    时间: 2014-12-6 18:20
可以用来偷地图?
作者: 越前リョーマ    时间: 2014-12-6 19:32
不需要一个一个地图进去“截图”而是启动就自动导出吗?
作者: pjy612    时间: 2014-12-8 08:52
(ΦωΦ)多谢大大!~ 其实就是类似做攻略啊 或者 其他什么的用的说~不一定要事件和角色都截取~ 太感谢了~
作者: pjy612    时间: 2014-12-8 09:08
本帖最后由 pjy612 于 2014-12-8 09:58 编辑

恩 导出了前几个地图~速度不慢的赶脚~
全导出的时候
小瑕疵修正
Q1:
导出全部时 提示参数不足
62.  def self.make_map_bitmap(id, mapinfos)
自解决:
62.  def self.make_map_bitmap(id, mapinfos, layers = [0, 1, 2])

Q2:地图名称如果包含中文可能导致程序停止工作
自解决:
换成Map+数字 fileName=sprintf("#{DIR_OUT}Map%03d.png", id)

Q3:
if tilesets.priorities[new_orders[k-1]] > tilesets.priorities[temp]
小概率出现 '>': comparison of Fixnum with nil failed (ArgumentError) 问题。。。
自解决:
前部分插入
break if tilesets.priorities[new_orders[k-1]].nil?
break if tilesets.priorities[temp].nil?
不过效果不理想 可能会 ”备份脚本“
期待LZ尝试优化。。。

其他自行优化部分:
PS1:
导出全部地图时可以尝试加入
45.插入
      fileName=sprintf("#{DIR_OUT}Map%03d.png", id)
      if File.exists?(fileName)        
        next if File.size(fileName)>100
      end
51.替换
bitmap.save_as_png(fileName)
避免中途出错后重复导出


PS2:
make_map_bitmap函数 第三行
可以改成
map = load_data(fileName=sprintf("Data/Map%03d.rxdata", id)) rescue return
兼容 如果 MapInfo有 ID 但是实际上没有MapXXX文件的情况
{:2_264:}
因为有时候MapInfo坏掉了。。。为了以防万一,就手动生成一个999的MapInfo。。。
多么痛的领悟。。。

其他的 在测试测试~ Σ(っ °Д °;)っ竟然发现LZ秒回!醉了~


作者: 精灵使者    时间: 2014-12-8 16:54
这个脚本可以做小地图脚本的预备脚本,来读取所有小地图用。
作者: 墨凌羽    时间: 2014-12-8 21:19
能不能同时输出每个图块相位置的通行?
感觉可以用RM画地图 然后分层输出 将导出的地图用作其他引擎的开发。。。。(不知道这算不算一个这个脚本的用法)
作者: 畫很多    时间: 2016-7-9 19:50
不好意思,可以具体说明一下使用方法吗?
老实说我不是很清楚"对 Bitmap 对象使用 save_as_png(filename)"的意思
作者: RyanBern    时间: 2016-7-9 21:52
畫很多 发表于 2016-7-9 19:50
不好意思,可以具体说明一下使用方法吗?
老实说我不是很清楚"对 Bitmap 对象使用 save_as_png(filename)"的 ...

假如变量 bmp 是一个 Bitmap 类的对象,那么调用
  1. bmp.save_as_png("1.png")
复制代码

就会将这个变量表示的图形以PNG文件的形式存储在你的硬盘上。

因此这个脚本的原理就是利用游戏内部数据制作一个 Bitmap 类型的对象,然后再利用save_as_png将其变为可以保存并查看的PNG图片。

具体的用法在说明中已经给出。
  1. Picture_Map.make_all
复制代码

将上面这句写在事件脚本里,可以导出全部的地图为PNG文件。

  1. Picture_Map.make_one(1, [0, 1])
复制代码

将上面这句写在事件脚本里,可以导出1号地图的第一层和第二层地图。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1