设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 8893|回复: 43
打印 上一主题 下一主题

[原创发布] 【加工】PNG Map Extractor for XP-地图PNG图片导出器Ver 1.3

[复制链接]

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

跳转到指定楼层
1
发表于 2014-12-6 01:21:31 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

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

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

x
本帖最后由 RyanBern 于 2016-7-10 16:02 编辑

深夜忙到很晚搞出来这个东西,这个脚本的功能就是导出游戏地图,把它制作成一个PNG文件。
类似的脚本在论坛上已经出现过,不过时间过于久远,而且不能直接在XP上使用。昨天在提问区看到一个提问帖,就拿来做了。用的是之前论坛上的脚本。
做的很仓促,所以有瑕疵的地方我会尽力改正。主要修复的问题就是自动元件描绘的问题,大家都知道只有XP才有自动元件,而且由于自动元件是程序自动生成,我们看不到源码,所以画起来十分麻烦,代码中大家也可以看到写得不是很简洁,不过我已经尽力了。
还有一个问题,就是地图导出会比较慢,所以尽量不要使用太大的地图。
感觉这玩意还可以配合ULDS系统进行截图。
使用前请下载这个DLL,并把它复制到工程的根目录下:
MGC_PNG.rar (87.39 KB, 下载次数: 359)
  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
复制代码

评分

参与人数 3星屑 +333 收起 理由
VIPArcher + 120 只有XP有自动元件..... =。=
taroxd + 200 辛苦
DivineCrow + 13 航拍OAO&quot; (吗?

查看全部评分

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

11
 楼主| 发表于 2016-7-9 21:52:16 | 只看该作者
畫很多 发表于 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号地图的第一层和第二层地图。

点评

這次可以了,谢谢~  发表于 2016-7-10 16:14
应该是论坛刚恢复然后代码框的程序异常,我稍微调整了一下,请再复制主楼的代码试试看。  发表于 2016-7-10 16:03
直接写在事件脚本上会出现"执行脚本时发生了TypeError。cannot convort Array into string"的出错@@  发表于 2016-7-10 10:41
直接写在事件脚本上会出现"执行脚本时发生了TypeError。cannot convort Array into string"的出错@@  发表于 2016-7-10 10:39
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
779
在线时间
244 小时
注册时间
2013-8-25
帖子
11
10
发表于 2016-7-9 19:50:39 | 只看该作者
不好意思,可以具体说明一下使用方法吗?
老实说我不是很清楚"对 Bitmap 对象使用 save_as_png(filename)"的意思
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
48
在线时间
784 小时
注册时间
2013-1-4
帖子
1102
9
发表于 2014-12-8 21:19:33 | 只看该作者
能不能同时输出每个图块相位置的通行?
感觉可以用RM画地图 然后分层输出 将导出的地图用作其他引擎的开发。。。。(不知道这算不算一个这个脚本的用法)
RM-GUI延期。。。最近被黑心老板压迫T_T
二次元少女的shitake,长着长脸,身高165,蓝色卷双马尾,FCUP,瞳色黑色,病气和御宅属性,是天才少女。
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (暗夜天使)

精灵族の天使

梦石
0
星屑
1697
在线时间
3038 小时
注册时间
2007-3-16
帖子
33731

开拓者贵宾

8
发表于 2014-12-8 16:54:42 | 只看该作者
这个脚本可以做小地图脚本的预备脚本,来读取所有小地图用。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
82
在线时间
26 小时
注册时间
2010-12-3
帖子
16
7
发表于 2014-12-8 09:08:57 | 只看该作者
本帖最后由 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秒回!醉了~

评分

参与人数 1星屑 +60 收起 理由
RyanBern + 60 塞糖

查看全部评分

回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
82
在线时间
26 小时
注册时间
2010-12-3
帖子
16
6
发表于 2014-12-8 08:52:27 | 只看该作者
(ΦωΦ)多谢大大!~ 其实就是类似做攻略啊 或者 其他什么的用的说~不一定要事件和角色都截取~ 太感谢了~
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (暗夜天使)

名侦探小柯

梦石
0
星屑
3299
在线时间
3619 小时
注册时间
2006-9-6
帖子
37400

开拓者贵宾第3届短篇游戏大赛主流游戏组亚军第5届短篇游戏比赛亚军

5
发表于 2014-12-6 19:32:38 | 只看该作者
不需要一个一个地图进去“截图”而是启动就自动导出吗?
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
211
在线时间
905 小时
注册时间
2010-9-6
帖子
3229
4
发表于 2014-12-6 18:20:45 | 只看该作者
可以用来偷地图?
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
9280
在线时间
2504 小时
注册时间
2011-5-20
帖子
15389

开拓者

3
发表于 2014-12-6 08:08:17 | 只看该作者
就是截一张世界地图的意思?
[img]http://service.t.sina.com.cn/widget/qmd/5339802982/c02e16bd/7.png
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-28 02:24

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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