查看: 18188|回复: 8

[教程] RMXP-地图教程ChapterⅩ-光影篇

[复制链接]
梦石
0
星屑
2383
在线时间
647 小时
注册时间
2013-8-11
回帖
814
发表于 2017-9-9 17:29:02 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 进击の虎叔 于 2017-9-9 17:39 编辑

前言.png
当今,「光影」一词已经不再陌生,层出不穷的各类游戏的光影渲染确实给画面带来很大的改观。
当然对于环境的塑造、气氛的烘托,同样是不可缺少的一个关键元素。
个人对这个概念的研究其实毫无头绪,先前还是主要把精力放在怎么把画面和光影结合起来... ...
也就是说只看重过程和结果,当然收获还是有的。
趁这个机会,最后分享一下自己的心得。


P.S. 教程算上这个算是只有三期(主要太懒...加上自己某些主题的地图也是苦手),也没什么技术含量...请多多包涵> <...
       演示的地图为室内房间。室外参考室内的做法,其实室外主要用现成的雾图形(线性光)/更改画面色调基本可以得到
    可观的画面。



Title.png

【需要材料/软件】
① RPG Maker XP(需要「航拍」脚本)
② Adobe Photoshop CS4及以上(不会太要求复杂的操作...其实新加的功能都还没用过...)
③ (其实这个非必需)高光素材...(一般来说不商用的话基本可以在百度上找...但是为了安全起见还是自己做比较好,个人对于做高光也是...白痴阶段...)用于特殊的、重要的光源。
④ 数位板(对于绘制更自然的光影有很大帮助)



需要的航拍脚本
注:第一次是在幻想天空时看到熊叔分享的...帮了很大的忙
注2:引入航拍脚本应为测试状态,如果游戏发布请删除,此脚本对于数据库里Tilesets的设置有影响(遮挡错乱-实质为影响优先度)
注3:使用时只需测试游戏中按下F6即可完成截图的输出,输出源位于游戏根目录

[fold=航拍脚本]
  1. #==============================================================================
  2. # ** Map Screenshot
  3. #==============================================================================
  4. #
  5. # - Credits: Cycleby for Bitmap to PNG
  6. #            SephirothSpawn for Tilemap
  7. #
  8. #
  9. # To take a screenshot simply be on the map and press F6. The file will be
  10. # created in your game directory under the maps name.
  11. #
  12. #==============================================================================


  13. #==============================================================================
  14. # ** Spriteset_Map
  15. #==============================================================================
  16. class Spriteset_Map
  17.   #--------------------------------------------------------------------------
  18.   # * Update
  19.   #--------------------------------------------------------------------------
  20.   alias :bit_to_png_up :update
  21.   def update
  22.     bit_to_png_up
  23.     if Input.trigger?(Input::F6)
  24.       map_infos = load_data("Data/MapInfos.rxdata")
  25.       bit = @tilemap.bitmap
  26.       exp_time = (bit.height * bit.width) * 0.00000664
  27.       string = "Taking screenshot please wait.... \n" +
  28.                "Number of pixels: #{bit.height * bit.width} \n" +
  29.                "Estamated time: #{exp_time} seconds."
  30.       print("#{string}")
  31.       old_time = Time.now
  32.       bit.make_png("#{map_infos[$game_map.map_id].name}")
  33.       string = "#{map_infos[$game_map.map_id].name}.png was created. \n" +
  34.                "File size: width #{bit.width}, height #{bit.height}. \n" +
  35.                "Time taken: #{Time.now - old_time} seconds."
  36.       print("#{string}")
  37.     end
  38.   end
  39. end

  40. #==============================================================================
  41. #                        Bitmap to PNG By Cycleby
  42. #==============================================================================
  43. #
  44. # Direct use of the Bitmap object.
  45. #     bitmap_obj.make_png(name[, path])
  46. #
  47. # Name: Save the file name
  48. # Path: path to save the
  49. #
  50. # Thanks 66, Shana, gold Guizi reminder and help!
  51. #==============================================================================
  52. module Zlib
  53.   class Png_File < GzipWriter
  54.     #--------------------------------------------------------------------------
  55.     # ● Main
  56.     #--------------------------------------------------------------------------
  57.     def make_png(bitmap_Fx,mode)
  58.       @mode = mode
  59.       @bitmap_Fx = bitmap_Fx
  60.       self.write(make_header)
  61.       self.write(make_ihdr)
  62.       self.write(make_idat)
  63.       self.write(make_iend)
  64.     end
  65.     #--------------------------------------------------------------------------
  66.     # ● PNG file header block
  67.     #--------------------------------------------------------------------------
  68.     def make_header
  69.       return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
  70.     end
  71.     #--------------------------------------------------------------------------
  72.     # ● PNG file data block header information (IHDR)
  73.     #--------------------------------------------------------------------------
  74.     def make_ihdr
  75.       ih_size = [13].pack("N")
  76.       ih_sign = "IHDR"
  77.       ih_width = [@bitmap_Fx.width].pack("N")
  78.       ih_height = [@bitmap_Fx.height].pack("N")
  79.       ih_bit_depth = [8].pack("C")
  80.       ih_color_type = [6].pack("C")
  81.       ih_compression_method = [0].pack("C")
  82.       ih_filter_method = [0].pack("C")
  83.       ih_interlace_method = [0].pack("C")
  84.       string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
  85.                ih_compression_method + ih_filter_method + ih_interlace_method
  86.       ih_crc = [Zlib.crc32(string)].pack("N")
  87.       return ih_size + string + ih_crc
  88.     end
  89.     #--------------------------------------------------------------------------
  90.     # ● Generated image data (IDAT)
  91.     #--------------------------------------------------------------------------
  92.     def make_idat
  93.       header = "\x49\x44\x41\x54"
  94.       case @mode # please 54 ~
  95.       when 1
  96.         data = make_bitmap_data # 1
  97.       else
  98.         data = make_bitmap_data
  99.       end
  100.       data = Zlib::Deflate.deflate(data, 8)
  101.       crc = [Zlib.crc32(header + data)].pack("N")
  102.       size = [data.length].pack("N")
  103.       return size + header + data + crc
  104.     end
  105.     #--------------------------------------------------------------------------
  106.     # ● Requests from the Bitmap object 54 to generate image data in mode 1
  107.     # (please 54 ~)
  108.     #--------------------------------------------------------------------------
  109.     def make_bitmap_data1
  110.       w = @bitmap_Fx.width
  111.       h = @bitmap_Fx.height
  112.       data = []
  113.       for y in 0...h
  114.         data.push(0)
  115.         for x in 0...w
  116.           color = @bitmap_Fx.get_pixel(x, y)
  117.           red = color.red
  118.           green = color.green
  119.           blue = color.blue
  120.           alpha = color.alpha
  121.           data.push(red)
  122.           data.push(green)
  123.           data.push(blue)
  124.           data.push(alpha)
  125.         end
  126.       end
  127.       return data.pack("C*")
  128.     end
  129.     #--------------------------------------------------------------------------
  130.     # ● Bitmap object from the image data generated in mode 0
  131.     #--------------------------------------------------------------------------
  132.     def make_bitmap_data
  133.       gz = Zlib::GzipWriter.open('hoge.gz')
  134.       t_Fx = 0
  135.       w = @bitmap_Fx.width
  136.       h = @bitmap_Fx.height
  137.       data = []
  138.       for y in 0...h
  139.         data.push(0)
  140.         for x in 0...w
  141.           t_Fx += 1
  142.           if t_Fx % 10000 == 0
  143.             Graphics.update
  144.           end
  145.           if t_Fx % 100000 == 0
  146.             s = data.pack("C*")
  147.             gz.write(s)
  148.             data.clear
  149.             #GC.start
  150.           end
  151.           color = @bitmap_Fx.get_pixel(x, y)
  152.           red = color.red
  153.           green = color.green
  154.           blue = color.blue
  155.           alpha = color.alpha
  156.           data.push(red)
  157.           data.push(green)
  158.           data.push(blue)
  159.           data.push(alpha)
  160.         end
  161.       end
  162.       s = data.pack("C*")
  163.       gz.write(s)
  164.       gz.close   
  165.       data.clear
  166.       gz = Zlib::GzipReader.open('hoge.gz')
  167.       data = gz.read
  168.       gz.close
  169.       File.delete('hoge.gz')
  170.       return data
  171.     end
  172.     #--------------------------------------------------------------------------
  173.     # ● PNG end of the file data blocks (IEND)
  174.     #--------------------------------------------------------------------------
  175.     def make_iend
  176.       ie_size = [0].pack("N")
  177.       ie_sign = "IEND"
  178.       ie_crc = [Zlib.crc32(ie_sign)].pack("N")
  179.       return ie_size + ie_sign + ie_crc
  180.     end
  181.   end
  182. end
  183. #==============================================================================
  184. # ■ Bitmap
  185. #------------------------------------------------------------------------------
  186. # Related to the Bitmap.
  187. #==============================================================================
  188. class Bitmap
  189.   #--------------------------------------------------------------------------
  190.   # ● Related
  191.   #--------------------------------------------------------------------------
  192.   def make_png(name="like", path="",mode=0)
  193.     make_dir(path) if path != ""
  194.     Zlib::Png_File.open("temp.gz") {|gz|
  195.       gz.make_png(self,mode)
  196.     }
  197.     Zlib::GzipReader.open("temp.gz") {|gz|
  198.       $read = gz.read
  199.     }
  200.     f = File.open(path + name + ".png","wb")
  201.     f.write($read)
  202.     f.close
  203.     File.delete('temp.gz')
  204.     end
  205.   #--------------------------------------------------------------------------
  206.   # ● Save the path generated
  207.   #--------------------------------------------------------------------------
  208.   def make_dir(path)
  209.     dir = path.split("/")
  210.     for i in 0...dir.size
  211.       unless dir == "."
  212.         add_dir = dir[0..i].join("/")
  213.         begin
  214.           Dir.mkdir(add_dir)
  215.         rescue
  216.         end
  217.       end
  218.     end
  219.   end
  220. end

  221. module Tilemap_Options
  222.   #--------------------------------------------------------------------------
  223.   # * Tilemap Options
  224.   #
  225.   #
  226.   #   Print Error Reports when not enough information set to tilemap
  227.   #    - Print_Error_Logs          = true or false
  228.   #
  229.   #   Number of autotiles to refresh at edge of viewport
  230.   #   Number of Frames Before Redrawing Animated Autotiles
  231.   #    - Animated_Autotiles_Frames = 16
  232.   #
  233.   #    - Viewport_Padding          = n
  234.   #
  235.   #   When maps are switch, automatically set
  236.   #   $game_map.tileset_settings.flash_data (Recommended : False unless using
  237.   #   flash_data)
  238.   #    - Autoset_Flash_data        = true or false
  239.   #
  240.   #   Duration Between Flash Data Flashes
  241.   #    - Flash_Duration            = n
  242.   #
  243.   #   Color of bitmap (Recommended to use low opacity value)
  244.   #    - Flash_Bitmap_C            = Color.new(255, 255, 255, 50)
  245.   #
  246.   #   Update Flashtiles Default Setting
  247.   #   Explanation : In the Flash Data Addition, because of lag, you may wish
  248.   #   to toggle whether flash tiles flash or not. This is the default state.
  249.   #    - Default_Update_Flashtiles = false
  250.   #--------------------------------------------------------------------------
  251.   Print_Error_Logs          = true
  252.   Animated_Autotiles_Frames = 16
  253.   Autoset_Flash_data        = true
  254.   Viewport_Padding          = 2
  255.   Flash_Duration            = 40
  256.   Flash_Bitmap_C            = Color.new(255, 255, 255, 50)
  257.   Default_Update_Flashtiles = false
  258. end

  259. #==============================================================================
  260. # ** RPG::Cache
  261. #==============================================================================
  262. module RPG::Cache
  263.   #--------------------------------------------------------------------------
  264.   # * Auto-Tiles
  265.   #
  266.   #   Auto-Tile 48 : First Auto-Tile, Constructed of tiles 27, 28, 33, 34
  267.   #--------------------------------------------------------------------------
  268.   Autotiles = [
  269.     [[27, 28, 33, 34], [ 5, 28, 33, 34], [27,  6, 33, 34], [ 5,  6, 33, 34],
  270.      [27, 28, 33, 12], [ 5, 28, 33, 12], [27,  6, 33, 12], [ 5,  6, 33, 12]],
  271.     [[27, 28, 11, 34], [ 5, 28, 11, 34], [27,  6, 11, 34], [ 5,  6, 11, 34],
  272.      [27, 28, 11, 12], [ 5, 28, 11, 12], [27,  6, 11, 12], [ 5,  6, 11, 12]],
  273.     [[25, 26, 31, 32], [25,  6, 31, 32], [25, 26, 31, 12], [25,  6, 31, 12],
  274.      [15, 16, 21, 22], [15, 16, 21, 12], [15, 16, 11, 22], [15, 16, 11, 12]],
  275.     [[29, 30, 35, 36], [29, 30, 11, 36], [ 5, 30, 35, 36], [ 5, 30, 11, 36],
  276.      [39, 40, 45, 46], [ 5, 40, 45, 46], [39,  6, 45, 46], [ 5,  6, 45, 46]],
  277.     [[25, 30, 31, 36], [15, 16, 45, 46], [13, 14, 19, 20], [13, 14, 19, 12],
  278.      [17, 18, 23, 24], [17, 18, 11, 24], [41, 42, 47, 48], [ 5, 42, 47, 48]],
  279.     [[37, 38, 43, 44], [37,  6, 43, 44], [13, 18, 19, 24], [13, 14, 43, 44],
  280.      [37, 42, 43, 48], [17, 18, 47, 48], [13, 18, 43, 48], [ 1,  2,  7,  8]]
  281.   ]
  282.   #--------------------------------------------------------------------------
  283.   # * Autotile Cache
  284.   #
  285.   #   @autotile_cache = {
  286.   #     filename => { [autotile_id, frame_id, hue] => bitmap, ... },
  287.   #     ...
  288.   #    }
  289.   #--------------------------------------------------------------------------
  290.   @autotile_cache = {}
  291.   #--------------------------------------------------------------------------
  292.   # * Autotile Tile
  293.   #--------------------------------------------------------------------------
  294.   def self.autotile_tile(filename, tile_id, hue = 0, frame_id = nil)
  295.     # Gets Autotile Bitmap
  296.     autotile = self.autotile(filename)
  297.     # Configures Frame ID if not specified
  298.     if frame_id.nil?
  299.       # Animated Tiles
  300.       frames = autotile.width / 96
  301.       # Configures Animation Offset
  302.       fc = Graphics.frame_count / Tilemap_Options::Animated_Autotiles_Frames
  303.       frame_id = (fc) % frames * 96
  304.     end
  305.     # Creates list if already not created
  306.     @autotile_cache[filename] = {} unless @autotile_cache.has_key?(filename)
  307.     # Gets Key
  308.     key = [tile_id, frame_id, hue]
  309.     # If Key Not Found
  310.     unless @autotile_cache[filename].has_key?(key)
  311.       # Reconfigure Tile ID
  312.       tile_id %= 48
  313.       # Creates Bitmap
  314.       bitmap = Bitmap.new(32, 32)
  315.       # Collects Auto-Tile Tile Layout
  316.       tiles = Autotiles[tile_id / 8][tile_id % 8]
  317.       # Draws Auto-Tile Rects
  318.       for i in 0...4
  319.         tile_position = tiles[i] - 1
  320.         src_rect = Rect.new(tile_position % 6 * 16 + frame_id,
  321.           tile_position / 6 * 16, 16, 16)
  322.         bitmap.blt(i % 2 * 16, i / 2 * 16, autotile, src_rect)
  323.       end
  324.       # Saves Autotile to Cache
  325.       @autotile_cache[filename][key] = bitmap
  326.       # Change Hue
  327.       @autotile_cache[filename][key].hue_change(hue)
  328.     end
  329.     # Return Autotile
  330.     return @autotile_cache[filename][key]
  331.   end
  332. end

  333. #==============================================================================
  334. # ** Spriteset_Map
  335. #==============================================================================
  336. class Spriteset_Map
  337.   #--------------------------------------------------------------------------
  338.   # * Object Initialization
  339.   #--------------------------------------------------------------------------
  340.   def initialize
  341.     # Make viewports
  342.     @viewport1 = Viewport.new(0, 0, 640, 480)
  343.     @viewport2 = Viewport.new(0, 0, 640, 480)
  344.     @viewport3 = Viewport.new(0, 0, 640, 480)
  345.     @viewport2.z = 200
  346.     @viewport3.z = 5000
  347.     # Make tilemap
  348.     # Make tilemap
  349.     @tilemap = Tilemap.new(@viewport1)
  350.     @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name)
  351.     for i in 0..6
  352.       autotile_name = $game_map.autotile_names[i]
  353.       @tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name)
  354.     end
  355.     @tilemap.map_data = $game_map.data.dup
  356.     @tilemap.priorities = $game_map.priorities
  357.     # Set Tilemap Settings
  358.     @tilemap.tileset_name = $game_map.tileset_name
  359.     for i in 0..6
  360.       @tilemap.autotiles_name[i] = $game_map.autotile_names[i]
  361.     end
  362.     @tilemap.tilemap_settings = $game_map.tilemap_settings
  363.     # Setup Flash Data
  364.     @tilemap.flash_data = $game_map.tilemap_settings.flash_data
  365.     # Run Tilemap Setup
  366.     @tilemap.setup
  367.     # Make panorama plane
  368.     [url=home.php?mod=space&uid=2658185]@Panorama[/url] = Plane.new(@viewport1)
  369.     @panorama.z = -1000
  370.     # Make fog plane
  371.     [url=home.php?mod=space&uid=14217]@fog[/url] = Plane.new(@viewport1)
  372.     @fog.z = 3000
  373.     # Make character sprites
  374.     @character_sprites = []
  375.     for i in $game_map.events.keys.sort
  376.       sprite = Sprite_Character.new(@viewport1, $game_map.events[i])
  377.       @character_sprites.push(sprite)
  378.     end
  379.     @character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
  380.     # Make weather
  381.     @weather = RPG::Weather.new(@viewport1)
  382.     # Make picture sprites
  383.     @picture_sprites = []
  384.     for i in 1..50
  385.       @picture_sprites.push(Sprite_Picture.new(@viewport2,
  386.         $game_screen.pictures[i]))
  387.     end
  388.     # Make timer sprite
  389.     @timer_sprite = Sprite_Timer.new
  390.     # Frame update
  391.     update
  392.   end
  393. end

  394. #==============================================================================
  395. # ** Tilemap_Settings
  396. #==============================================================================
  397. class Tilemap_Settings
  398.   #--------------------------------------------------------------------------
  399.   # * Public Instance Variables
  400.   #--------------------------------------------------------------------------
  401.   attr_accessor :map
  402.   attr_accessor :is_a_plane
  403.   attr_accessor :tone
  404.   attr_accessor :hue
  405.   attr_accessor :zoom_x
  406.   attr_accessor :zoom_y
  407.   attr_accessor :tile_size
  408.   attr_accessor :flash_data
  409.   #--------------------------------------------------------------------------
  410.   # * Object Initialization
  411.   #--------------------------------------------------------------------------
  412.   def initialize(map = nil)
  413.     # Set Instance Variables
  414.     @map, @is_a_plane, @tone, @hue, @zoom_x, @zoom_y, @tile_size,
  415.       @flash_data = map, false, nil, 0, 1.0, 1.0, 32, nil
  416.   end
  417. end

  418. #==============================================================================
  419. # ** Game_Map
  420. #==============================================================================
  421. class Game_Map
  422.   #--------------------------------------------------------------------------
  423.   # * Public Instance Variables
  424.   #--------------------------------------------------------------------------
  425.   attr_accessor :tilemap_settings
  426.   #--------------------------------------------------------------------------
  427.   # * Alias Listings
  428.   #--------------------------------------------------------------------------
  429.   alias_method :seph_tilemap_gmap_init, :initialize
  430.   #--------------------------------------------------------------------------
  431.   # * Object Initialization
  432.   #--------------------------------------------------------------------------
  433.   def initialize
  434.     # Original Initialization
  435.     seph_tilemap_gmap_init
  436.     # Create Tilemap Settings
  437.     @tilemap_settings = Tilemap_Settings.new
  438.   end
  439.   #--------------------------------------------------------------------------
  440.   # * Load Map Data
  441.   #--------------------------------------------------------------------------
  442.   def setup_load
  443.     # Reset Tilemap Flash Data
  444.     if Tilemap_Options::Autoset_Flash_data
  445.       @tilemap_settings.flash_data = Table.new(@map.width, @map.height)
  446.     end
  447.     @tilemap_settings.map = @map
  448.   end
  449. end

  450. #==============================================================================
  451. # ** Tilemap
  452. #==============================================================================
  453. class Tilemap
  454.   #--------------------------------------------------------------------------
  455.   # * Public Instance Variables
  456.   #--------------------------------------------------------------------------
  457.   attr_reader   :layers
  458.   attr_accessor :tileset
  459.   attr_accessor :tileset_name
  460.   attr_accessor :autotiles
  461.   attr_accessor :autotiles_name
  462.   attr_accessor :map_data
  463.   attr_accessor :flash_data
  464.   attr_accessor :priorities
  465.   attr_accessor :visible
  466.   attr_accessor :ox
  467.   attr_accessor :oy
  468.   attr_accessor :tilemap_settings
  469.   attr_accessor :refresh_autotiles
  470.   #--------------------------------------------------------------------------
  471.   # * Object Initialization
  472.   #--------------------------------------------------------------------------
  473.   def initialize(viewport)
  474.     # Saves Viewport
  475.     @viewport = viewport
  476.     # Creates Blank Instance Variables
  477.     @layers            = []    # Refers to Array of Sprites or Planes
  478.     @tileset           = nil   # Refers to Tileset Bitmap
  479.     @tileset_name      = ''    # Refers to Tileset Filename
  480.     @autotiles         = []    # Refers to Array of Autotile Bitmaps
  481.     @autotiles_name    = []    # Refers to Array of Autotile Filenames
  482.     @map_data          = nil   # Refers to 3D Array Of Tile Settings
  483.     @flash_data        = nil   # Refers to 3D Array of Tile Flashdata
  484.     @priorities        = nil   # Refers to Tileset Priorities
  485.     @visible           = true  # Refers to Tilest Visibleness
  486.     @ox                = 0     # Bitmap Offsets         
  487.     @oy                = 0     # Bitmap Offsets
  488.     @tilemap_settings  = nil   # Special Tilemap Settings
  489.     @dispose           = false # Disposed Flag
  490.     @refresh_autotiles = true  # Refresh Autotile Flag
  491.   end
  492.   #--------------------------------------------------------------------------
  493.   # * Setup
  494.   #--------------------------------------------------------------------------
  495.   def setup
  496.     # Print Error if Tilemap Settings not Found
  497.     if Tilemap_Options::Print_Error_Logs
  498.       if @tilemap_settings.nil?
  499.         p 'Tilemap Settings have not been set. System will not crash.'
  500.       end
  501.       if @map_data.nil?
  502.         p 'Map Data has not been set. System will crash.'
  503.       end
  504.     end
  505.     # Creates Layers
  506.     @layers = []
  507.     for l in 0...3
  508.       layer = @tilemap_settings.nil? || !@tilemap_settings.is_a_plane ?
  509.         Sprite.new(@viewport) : Plane.new(@viewport)
  510.       layer.bitmap = Bitmap.new(@map_data.xsize * 32, @map_data.ysize * 32)
  511.       layer.z = l * 150
  512.       layer.zoom_x = @tilemap_settings.nil? ? 1.0 : @tilemap_settings.zoom_x
  513.       layer.zoom_y = @tilemap_settings.nil? ? 1.0 : @tilemap_settings.zoom_y
  514.       unless @tilemap_settings.nil? || @tilemap_settings.tone.nil?
  515.         layer.tone = @tilemap_settings.tone
  516.       end
  517.       @layers << layer
  518.     end
  519.     # Update Flags
  520.     @refresh_data = nil
  521.     @zoom_x   = @tilemap_settings.nil? ? 1.0 : @tilemap_settings.zoom_x
  522.     @zoom_y   = @tilemap_settings.nil? ? 1.0 : @tilemap_settings.zoom_y
  523.     @tone     = @tilemap_settings.nil? ? nil : @tilemap_settings.tone
  524.     @hue      = @tilemap_settings.nil? ? 0   : @tilemap_settings.hue
  525.     @tilesize = @tilemap_settings.nil? ? 32  : @tilemap_settings.tile_size
  526.   end
  527.   #--------------------------------------------------------------------------
  528.   # * Dispose
  529.   #--------------------------------------------------------------------------
  530.   def dispose
  531.     # Dispose Layers (Sprites)
  532.     @layers.each { |layer| layer.dispose }
  533.     # Set Disposed Flag to True
  534.     @disposed = true
  535.   end
  536.   #--------------------------------------------------------------------------
  537.   # * Disposed?
  538.   #--------------------------------------------------------------------------
  539.   def disposed?
  540.     return @disposed
  541.   end
  542.   #--------------------------------------------------------------------------
  543.   # * Viewport
  544.   #--------------------------------------------------------------------------
  545.   def viewport
  546.     return @viewport
  547.   end
  548.   #--------------------------------------------------------------------------
  549.   # * Frame Update
  550.   #--------------------------------------------------------------------------
  551.   def update
  552.     # Set Refreshed Flag to On
  553.     needs_refresh = true
  554.     # If Map Data, Tilesize or HueChanges
  555.     if @map_data != @refresh_data || (@tilemap_settings != false &&
  556.        @hue != @tilemap_settings.hue) || (@tilemap_settings != false &&
  557.        @tilesize != @tilemap_settings.tile_size)
  558.       # Refresh Bitmaps
  559.       refresh
  560.       # Turns Refresh Flag to OFF
  561.       needs_refresh = false
  562.     end
  563.     # Zoom X, Zoom Y, and Tone Changes
  564.     unless @tilemap_settings.nil?
  565.       if @zoom_x != @tilemap_settings.zoom_x
  566.         @zoom_x = @tilemap_settings.zoom_x
  567.         @layers.each {|layer| layer.zoom_x = @zoom_x}
  568.       end
  569.       if @zoom_y != @tilemap_settings.zoom_y
  570.         @zoom_y = @tilemap_settings.zoom_y
  571.         @layers.each {|layer| layer.zoom_y = @zoom_y}
  572.       end
  573.       if @tone != @tilemap_settings.tone
  574.         @tone = @tilemap_settings.tone.nil? ?
  575.           Tone.new(0, 0, 0, 0) : @tilemap_settings.tone
  576.         @layers.each {|layer| layer.tone = @tone}
  577.       end
  578.     end
  579.     # Update layer Position offsets
  580.     for layer in @layers
  581.       layer.ox = @ox
  582.       layer.oy = @oy
  583.     end
  584.     # If Refresh Autotiles, Needs Refreshed & Autotile Reset Frame
  585.     if @refresh_autotiles && needs_refresh &&
  586.        Graphics.frame_count % Tilemap_Options::Animated_Autotiles_Frames == 0
  587.       # Refresh Autotiles
  588.       refresh_autotiles
  589.     end
  590.   end
  591.   #--------------------------------------------------------------------------
  592.   # * Refresh
  593.   #--------------------------------------------------------------------------
  594.   def refresh
  595.     # Saves Map Data & Tilesize
  596.     @refresh_data = @map_data
  597.     @hue      = @tilemap_settings.nil? ? 0  : @tilemap_settings.hue
  598.     @tilesize = @tilemap_settings.nil? ? 32 : @tilemap_settings.tile_size
  599.     # Passes Through Layers
  600.     for z in 0...@map_data.zsize
  601.       # Passes Through X Coordinates
  602.       for x in 0...@map_data.xsize
  603.         # Passes Through Z Coordinates
  604.         for y in 0...@map_data.ysize
  605.           # Collects Tile ID
  606.           id = @map_data[x, y, z]
  607.           # Skip if 0 tile
  608.           next if id == 0
  609.           # Passes Through All Priorities
  610.           for p in 0..5
  611.             # Skip If Priority Doesn't Match
  612.             next unless p == @priorities[id]
  613.             # Cap Priority to Layer 3
  614.             p = 2 if p > 2
  615.             # Draw Tile
  616.             id < 384 ? draw_autotile(x, y, p, id) : draw_tile(x, y, p, id)
  617.           end
  618.         end
  619.       end
  620.     end
  621.   end   
  622.   #--------------------------------------------------------------------------
  623.   # * Refresh Auto-Tiles
  624.   #--------------------------------------------------------------------------
  625.   def refresh_autotiles
  626.     # Auto-Tile Locations
  627.     autotile_locations = Table.new(@map_data.xsize, @map_data.ysize,
  628.       @map_data.zsize)
  629.     # Get X Tiles
  630.     x1 = [@ox / @tilesize - Tilemap_Options::Viewport_Padding, 0].max.round
  631.     x2 = [@viewport.rect.width / @tilesize +
  632.           Tilemap_Options::Viewport_Padding, @map_data.xsize].min.round
  633.     # Get Y Tiles
  634.     y1 = [@oy / @tilesize - Tilemap_Options::Viewport_Padding, 0].max.round
  635.     y2 = [@viewport.rect.height / @tilesize +
  636.           Tilemap_Options::Viewport_Padding, @map_data.ysize].min.round
  637.     # Passes Through Layers
  638.     for z in 0...@map_data.zsize
  639.       # Passes Through X Coordinates
  640.       for x in x1...x2
  641.         # Passes Through Y Coordinates
  642.         for y in y1...y2
  643.           # Collects Tile ID
  644.           id = @map_data[x, y, z]
  645.           # Skip if 0 tile
  646.           next if id == 0
  647.           # Skip If Non-Animated Tile
  648.           next unless @autotiles[id / 48 - 1].width / 96 > 1 if id < 384
  649.           # Passes Through All Priorities
  650.           for p in 0..5
  651.             # Skip If Priority Doesn't Match
  652.             next unless p == @priorities[id]
  653.             # Cap Priority to Layer 3
  654.             p = 2 if p > 2
  655.             # If Autotile
  656.             if id < 384
  657.               # Draw Auto-Tile
  658.               draw_autotile(x, y, p, id)
  659.               # Draw Higher Tiles
  660.               for l in 0...@map_data.zsize
  661.                 id_l = @map_data[x, y, l]
  662.                 draw_tile(x, y, p, id_l)
  663.               end
  664.               # Save Autotile Location
  665.               autotile_locations[x, y, z] = 1
  666.             # If Normal Tile
  667.             else
  668.               # If Autotile Drawn
  669.               if autotile_locations[x, y, z] == 1
  670.                 # Redraw Normal Tile
  671.                 draw_tile(x, y, p, id)
  672.                 # Draw Higher Tiles
  673.                 for l in 0...@map_data.zsize
  674.                   id_l = @map_data[x, y, l]
  675.                   draw_tile(x, y, p, id_l)
  676.                 end
  677.               end
  678.             end
  679.           end
  680.         end
  681.       end
  682.     end
  683.   end      
  684.   #--------------------------------------------------------------------------
  685.   # * Draw Tile
  686.   #--------------------------------------------------------------------------
  687.   def draw_tile(x, y, z, id)
  688.     # Gets Tile Bitmap
  689.     bitmap = RPG::Cache.tile(@tileset_name, id, @hue)
  690.     # Calculates Tile Coordinates
  691.     x *= @tilesize
  692.     y *= @tilesize
  693.     # Draw Tile
  694.     if @tilesize == 32
  695.       @layers[z].bitmap.blt(x, y, bitmap, Rect.new(0, 0, 32, 32))
  696.     else
  697.       rect = Rect.new(x, y, @tilesize, @tilesize)
  698.       @layers[z].bitmap.stretch_blt(rect, bitmap, Rect.new(0, 0, 32, 32))
  699.     end
  700.   end
  701.   #--------------------------------------------------------------------------
  702.   # * Draw Auto-Tile
  703.   #--------------------------------------------------------------------------
  704.   def draw_autotile(x, y, z, tile_id)
  705.     # Gets Autotile Filename
  706.     filename = @autotiles_name[tile_id / 48 - 1]
  707.     # Reconfigure Tile ID
  708.     tile_id %= 48
  709.     # Gets Generated Autotile Bitmap Section
  710.     bitmap = RPG::Cache.autotile_tile(filename, tile_id, @hue)
  711.     # Calculates Tile Coordinates
  712.     x *= @tilesize
  713.     y *= @tilesize
  714.     # If Normal Tile
  715.     if @tilesize == 32
  716.       @layers[z].bitmap.blt(x, y, bitmap, Rect.new(0, 0, 32, 32))
  717.     # If Altered Dimensions
  718.     else
  719.       dest_rect = Rect.new(x, y, @tilesize, @tilesize)
  720.       @layers[z].bitmap.stretch_blt(dest_rect, bitmap, Rect.new(0, 0, 32, 32))
  721.     end
  722.   end
  723.   #--------------------------------------------------------------------------
  724.   # * Collect Bitmap
  725.   #--------------------------------------------------------------------------
  726.   def bitmap
  727.     # Creates New Blank Bitmap
  728.     bitmap = Bitmap.new(@layers[0].bitmap.width, @layers[0].bitmap.height)
  729.     # Passes Through All Layers
  730.     for layer in @layers
  731.       bitmap.blt(0, 0, layer.bitmap,
  732.         Rect.new(0, 0, bitmap.width, bitmap.height))
  733.     end
  734.     # Return Bitmap
  735.     return bitmap
  736.   end
  737. end
  738. #==============================================================================
  739. # ■ 航拍 v 1.1 by 各种压力的猫君
  740. #------------------------------------------------------------------------------
  741. #   本脚本为 Map Screenshot by mr_wiggles 的汉化&加强,
  742. #   并未取得原作者允许,并未附加原脚本内容,需要原脚本的支持。
  743. #   【换言之本脚本不能单独使用】
  744. #------------------------------------------------------------------------------
  745. #   Map Screenshot by mr_wiggles 的发布网址:
  746. #   http://gameface101.playogame.com/t920-map-screen-shot-rmxp
  747. #------------------------------------------------------------------------------
  748. #   使用方法:
  749. #   ① 将 Map Screenshot by mr_wiggles 插入 MAIN 之上;
  750. #   ② 将本脚本插入上面脚本之下,MAIN 之上;
  751. #   ③ 运行游戏,在需要截图的地图上按F6。
  752. #------------------------------------------------------------------------------
  753. #   更新记录:
  754. #   2012-01-21 v 1.1 支持行走图的色相、透明度以及合成方式(加减法)
  755. #   2012-01-21 v 1.0 修正行走图传送区域错误
  756. #   2012-01-21 v 0.9 初版
  757. #------------------------------------------------------------------------------
  758. #   更新预告:
  759. #   下一版将加入 设定部分暂未实现的功能
  760. #   下一版将加入 超过Bitmap上限自动分割的功能
  761. #==============================================================================

  762. #==============================================================================
  763. # ■ 设定部分
  764. #------------------------------------------------------------------------------
  765. #  本汉化加强版脚本的设定。
  766. #==============================================================================

  767. # 截图类型
  768. #  - 0 仅图块(原脚本类型)
  769. #  - 1 图块 + 事件(事件名称以NPC开头的以及主角除外)
  770. #  - 2 图块 + 全事件(1的基础上包括NPC和主角)
  771. #  - 3 图块 + 远景图 + 雾(暂未实现)
  772. #  - 4 图块 + 远景图 + 雾 + 事件(暂未实现)
  773. #  - 5 图块 + 远景图 + 雾 + 全事件(暂未实现)

  774. Aerial_Photography_TPYE = 2

  775. #==============================================================================
  776. # ■ 汉化部分
  777. #------------------------------------------------------------------------------
  778. #  对原脚本提示信息的汉化。
  779. #==============================================================================
  780. class Spriteset_Map
  781.   def update
  782.     bit_to_png_up
  783.     if Input.trigger?(Input::F6)
  784.       map_infos = load_data("Data/MapInfos.rxdata")
  785.       bit = @tilemap.bitmap
  786.       exp_time = (bit.height * bit.width) * 0.00000664
  787.       string = "航拍图已创建完成\n" +
  788.               "像素数: #{bit.height * bit.width} \n" +
  789.               "预计输出PNG用时: #{exp_time} 秒\n\n" +
  790.               "按确定键开始输出PNG"
  791.       print("#{string}")
  792.       old_time = Time.now
  793.       bit.make_png("#{map_infos[$game_map.map_id].name}")
  794.       string = "#{map_infos[$game_map.map_id].name}.png 已被创建 \n" +
  795.               "尺寸:宽 #{bit.width}, 高 #{bit.height} \n" +
  796.               "耗时:#{Time.now - old_time} 秒"
  797.       print("#{string}")
  798.     end
  799.   end
  800. end

  801. #==============================================================================
  802. # ■ 加强部分
  803. #------------------------------------------------------------------------------
  804. #  对原脚本功能的加强。
  805. #==============================================================================

  806. class Game_Event < Game_Character
  807.   def name
  808.     return @event.name
  809.   end
  810. end

  811. class Sprite_Character < RPG::Sprite
  812.   attr_reader   :tile_id                  # 元件 ID  (0 为无效)
  813. end

  814. class Tilemap
  815.   #--------------------------------------------------------------------------
  816.   # * Collect Bitmap
  817.   #--------------------------------------------------------------------------
  818.   def bitmap
  819.     # Creates New Blank Bitmap
  820.     bitmap = Bitmap.new(@layers[0].bitmap.width, @layers[0].bitmap.height)
  821.     # Passes Through All Layers
  822.     for layer in @layers
  823.       bitmap.blt(0, 0, layer.bitmap,
  824.         Rect.new(0, 0, bitmap.width, bitmap.height))
  825.     end
  826.       
  827.   #--------------------------------------------------------------------------
  828.   # 绘制事件行走图
  829.   #--------------------------------------------------------------------------
  830.   if Aerial_Photography_TPYE == 1 or
  831.      Aerial_Photography_TPYE == 2 or
  832.      Aerial_Photography_TPYE == 4 or
  833.      Aerial_Photography_TPYE == 5
  834.     # 生成角色活动块
  835.     character_sprites = []
  836.     for i in $game_map.events.keys.sort
  837.       # 排除NPC
  838.       if Aerial_Photography_TPYE == 1 or
  839.          Aerial_Photography_TPYE == 4
  840.         next if $game_map.events[i].name.slice(/^NPC/)
  841.       end
  842.       sprite = Sprite_Character.new(@viewport1, $game_map.events[i])
  843.       character_sprites.push(sprite)
  844.     end
  845.     # 排除主角
  846.     unless Aerial_Photography_TPYE == 1 or
  847.            Aerial_Photography_TPYE == 4
  848.       character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
  849.     end
  850.     # 绘制
  851.     for npc4map in character_sprites
  852.       rx = npc4map.x + $game_map.display_x / 4 - npc4map.ox
  853.       ry = npc4map.y + $game_map.display_y / 4 - npc4map.oy
  854.       o = npc4map.opacity
  855.       r = npc4map.src_rect
  856.       # 合成方式的处理
  857.       if npc4map.blend_type == 0
  858.         b = npc4map.bitmap.clone
  859.       else
  860.         # 将行走图切一块过来
  861.         sb = Bitmap.new(r.width, r.height)
  862.         sb.blt(0, 0, npc4map.bitmap, r, o)
  863.         # 同样地,将底部图片切一块过来
  864.         ub = Bitmap.new(r.width, r.height)
  865.         sr = Rect.new(rx, ry, r.width, r.height)
  866.         ub.stretch_blt(ub.rect, bitmap, sr)
  867.         # 获取颜色值
  868.         ubc = []
  869.         sbc = []
  870.         bc  = []
  871.         for y in 0..(ub.height - 1)
  872.           for x in 0..(ub.width - 1)
  873.             ubc.push ub.get_pixel(x, y)
  874.             sbc.push sb.get_pixel(x, y)
  875.           end
  876.         end
  877.         @tc = Color.new(0, 0, 0)
  878.         # 生成bitmap
  879.         b = Bitmap.new(r.width, r.height)
  880.         for y in 0..(b.height - 1)
  881.           for x in 0..(b.width - 1)
  882.             i = x + y * b.width
  883.             uc = ubc[i]
  884.             sc = sbc[i]
  885.             mc = mix_color(uc, sc, npc4map.blend_type)
  886.             b.set_pixel(x, y, mc)
  887.           end
  888.         end
  889.         r = Rect.new(0, 0, r.width, r.height)
  890.       end
  891.       # 若不是地图原件,采用行走图绘制方式
  892.       if npc4map.tile_id == 0
  893.         bitmap.blt(rx, ry, b, r, o)
  894.       else
  895.         bitmap.blt(rx, ry, b, Rect.new(0, 0, 32, 32), o)
  896.       end
  897.     end
  898.   end
  899.   #--------------------------------------------------------------------------
  900.     # Return Bitmap
  901.     return bitmap
  902.   end
  903.   #--------------------------------------------------------------------------
  904.   def mix_color(c1, c2, bt)
  905.     return c1 if c2.alpha == 0
  906.     case bt
  907.     when 1 # 加法
  908.       tc_r = c1.red   + c2.red
  909.       tc_g = c1.green + c2.green
  910.       tc_b = c1.blue  + c2.blue
  911.       tc_a = c1.alpha + c2.alpha
  912.     when 2 # 减法
  913.       tc_r = (c1.red   - c2.red).abs
  914.       tc_g = (c1.green - c2.green).abs
  915.       tc_b = (c1.blue  - c2.blue).abs
  916.       tc_a = [c1.alpha, c2.alpha].max
  917.     end
  918.     mc = [tc_r, tc_g, tc_b, tc_a]
  919.     @tc.set(mc[0], mc[1], mc[2], mc[3])
  920.     return @tc
  921.   end
  922.   #--------------------------------------------------------------------------
  923. end
复制代码
[/fold]


【Step.1】
S1.png
如图所示(CS6界面)
通常情况下要用辅助线来配合制作光影。
设置方式:视图-显示-网格(G)
网格的预设是在:编辑-首选项-参考、网格和切片(S)
·设置参数:[样式]直线(默认) / 网格线间隔:32 像素 / 子网格:1 (颜色根据需要自行调整)


————————————————————————————————————————————————————

【Step.2】
新建图层,选择“油漆桶工具”,参数根据需要调整为1%-99%,白天的话个人喜欢默认50%,晚上则为70%甚至更高。前景色纯黑色(R/G/B:0)。
然后填充画面。如图。

S2.png

————————————————————————————————————————————————————

【Step.3】
确定光源影响区域,选择“矩形选框工具”,方式为“添加到选区”
S3.png

————————————————————————————————————————————————————

【Step.4】
选择“橡皮擦工具”,参数设置:将不透明度和流量设置在较低的数值(一般20%以下)橡皮擦样式一般默认即可。
在准确的光源处单击。接下来使用键盘上的“{[”和“}]”调整橡皮擦半径(规律递增)
小技巧:保持中心不动,小半径下多使用橡皮擦工具,大半径下少使用(随着距离增大因为空气的反射折射会减弱光源)
对于侧面从窗户投射的光,在网格辅助下利用多边形套索选取相应区域再使用橡皮擦即可。


————————————————————————————————————————————————————

【Step.5】
而对于人工光源,先用橡皮擦在光源出操作类似Step.4的步骤,再新建图层,将图层不透明度调至50%左右,图层的叠加模式根据画面需求调试。选择画笔工具,参数的设置接近橡皮擦,可以更高一些。前景色自行调整。如图所示,得到较简单的光影,此后只需要隐藏截图图层输出为png格式保存在“Fog”文件夹作为雾图形使用即可.(普通合成,不透明度255)
另,人工光源可用Character(光源素材也是有的)采用加法配合雾图形效果更加。至于阴影的绘制...作为雾图形不太合适,因为优先度高会遮盖行走图,只能说随机应变...

S5.png





再添加一个使用去黑色背景的高光素材小方法:通道法...其实也是来源网上,再扩散一下好了(
[fold=延展内容] 16 点 53 分 21 秒.png
如图...
16 点 54 分 03 秒.png
新建三个图层分别命名为RGB。
然后跳转至通道,首先按住Ctrl单击 红 会出现选区,再返回图层。
17 点 03 分 23 秒.png
选择R图层,在图层界面的功能选项“创建新的填充或调整图层”选择纯色,在RGB的参数里设置为(R255 G0 B0),确定后,隐藏R图层继续对G,B执行对应的操作。
未标题-1.png
全部操作完成后将RGB三个图层设置为可见,图层混合模式为线性减淡。隐藏原图层。
最后得到该图。
16 点 59 分 53 秒.png
最后别忘了先输出为png格式,再打开png格式的素材再使用呀。[/fold]


【Fog】展示

Aeria Central _ Armory Office.png
(来自Freebird工作室的作品《Quintessence:The Blighted Venom》以研究的目的很厚颜无耻地破解...在这里说声抱歉...)
(典型的,以数位板绘制雾图形的范例)

旅店房间.png
(个人的一个实验)

————————————————————————————————————————————————————————

【Screeshots】展示

00 点 48 分 52 秒.png
14 点 50 分 15 秒.png
14 点 14 分 48 秒.png
(三张的个人实验)

NUMINA.png9.png
(这张或许采用了高光...)
NUMINA2.png
NUMINA5.png
(以上3张来自作品Numina,已经出了测试版,各位可以去试玩一下,在油管上也有作者绘制地图的过程,曾经还向作者请教过来着...)

10924761_825574607501381_5506266617778691800_n.png
desert_path_by_jose1208-d5hp4bx.png
Forest_NightScene.jpg
(来源不明...截图是在逛Galley的时候顺手存的...都还有我值得研究和学习的地方...)



【后记】
以上就是本次教程的全部内容...算是新手向,但是勉勉强强可以画一张挺有氛围的地图了,相比VA VX的ULDS(是这么叫吗?= =  相比RMXP的极限究竟能有多少我还是会继续探究的。)
另外欢迎有兴趣的各位一起探讨地图的绘制> <

评分

参与人数 7星屑 +640 赞 +5 收起 理由
azazaaz13142121 + 1 精品文章
comqocit + 1 塞糖
Nil2018 + 1 学习学习!
畫很多 + 1
king + 1 精品
Anson + 500 精品文章!
garfeng + 140 学习了……

查看全部评分


Engine:RPG Maker XP
Ability:

帅的人在默默填坑,而丑的人在疯狂灌水。
梦石
2
星屑
5550
在线时间
2566 小时
注册时间
2012-2-9
回帖
947

开拓者

发表于 2017-9-9 17:54:25 | 显示全部楼层
竟然是先给整体浇灌黑色,然后有光的地方擦掉……

我总是拿比较大的画笔,然后透明度硬度调低来画阴影,总是会画得很违和,就像一团脏兮兮的淤泥。

新技能。

点评

范例做的挺好的~看起来很舒服。  发表于 2017-9-9 20:38
有用就好w,不过正文的这个范例做的失败...太急了...一般一张正常的FOG需要半小时以上才看得出效果(  发表于 2017-9-9 19:02
回复

使用道具 举报

梦石
0
星屑
55
在线时间
12 小时
注册时间
2017-9-28
回帖
24
发表于 2017-9-28 17:38:46 | 显示全部楼层
这个就是专业的区别,感觉很舒服很自然,有空慢慢研究,感谢
回复

使用道具 举报

梦石
0
星屑
1115
在线时间
262 小时
注册时间
2016-1-29
回帖
30

开拓者

发表于 2017-10-4 15:41:29 | 显示全部楼层
建议虎叔多开几个光影的造福我们
回复

使用道具 举报

梦石
0
星屑
1768
在线时间
126 小时
注册时间
2018-4-1
回帖
8
发表于 2019-4-20 14:41:37 | 显示全部楼层
受教了,正好在光影方面可以学习尝试
回复

使用道具 举报

梦石
0
星屑
191
在线时间
21 小时
注册时间
2021-2-10
回帖
10
发表于 2021-2-14 11:23:34 | 显示全部楼层
请问,这个航拍脚本为什么374行出现报错啊
emmmm,杰哥我还要
回复

使用道具 举报

梦石
0
星屑
377
在线时间
38 小时
注册时间
2021-3-30
回帖
42
发表于 2021-3-31 20:44:57 | 显示全部楼层
好贴啊,顶,偶顶!!!!
To be a better man.
回复

使用道具 举报

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

本版积分规则

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

在本版发帖返回顶部