KK20

Custom Resolution v0.96b

Nov 15th, 2013
944
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #===============================================================================
  2. # Custom Resolution
  3. # Authors: ForeverZer0, KK20
  4. # Version: 0.96b
  5. # Date: 11.15.2013
  6. #===============================================================================
  7. # KK20's Notes
  8. #===============================================================================
  9. # Introduction:
  10. #
  11. #   This script is intended to create screen resolutions other than 640 x 480.
  12. #   The script comes with its own Tilemap rewrite in order to combat larger
  13. #   screen resolutions (because anything beyond 640 x 480 is not drawn).
  14. #
  15. # Instructions:
  16. #
  17. #   Place script above 'Main'. Probably best to put it below all your other
  18. #   custom scripts.
  19. #   You will also need 'screenshot.dll' included in your project. You can find
  20. #   that in Fantasist's Transitions Pack linked below.
  21. #
  22. # Things to Consider:
  23. #
  24. #  - Fullscreen will change the resolution back to 640 x 480. A solution is in
  25. #    the works.
  26. #  - Transitions do not work properly on larger resolutions. You can use a
  27. #    Transitions Add-Ons script if you want better transitions (otherwise, all
  28. #    you will get is the default fade in/out). Links listed below.
  29. #  - Custom scripts that draw windows to the screen will most likely need edits.
  30. #  - Larger resolutions = more processing power = more lag
  31. #
  32. #  ***************************************************************************  
  33. #  * THIS IS STILL A WORK IN PROGRESS; IF YOU FIND ANYTHING PLEASE REPORT IT *
  34. #  ***************************************************************************  
  35. #
  36. #  Links:
  37. #  - Fantasist's Transitions Pack (w/ screenshot.dll)
  38. #    http://forum.chaos-project.com/index.php/topic,1390.0.html
  39. #  - ForeverZer0's Add-ons
  40. #    http://forum.chaos-project.com/index.php/topic,7862.0.html
  41. #  - ThallionDarkshine's Add-ons
  42. #    http://forum.chaos-project.com/index.php/topic,12655.0.html
  43. #  - Drago Transition Pack
  44. #    http://forum.chaos-project.com/index.php/topic,13488.0.html
  45. #
  46. #===============================================================================
  47. # ForeverZer0's Notes from v0.93                   (outdated information)
  48. #===============================================================================
  49. # Introduction:
  50. #
  51. #   My goal in creating this script was to create a system that allowed the user
  52. #   to set the screen size to something other than 640 x 480, but not have make
  53. #   huge sacrifices in compatibility and performance. Although the script is
  54. #   not simply Plug-and-Play, it is about as close as one can achieve with a
  55. #   script of this nature.
  56. #
  57. # Instructions:
  58. #
  59. #  - Place the "screenshot.dll" from Fantasist's Transition Pack script, which
  60. #    can be found here: http://www.sendspace.com/file/yjd54h in your game folder
  61. #  - Place this script above main, below default scripts.
  62. #  - In my experience, unchecking "Reduce Screen Flickering" actually helps the
  63. #    screen not to flicker. Open menu with F1 while playing and set this to what
  64. #    you get the best results with.
  65. #
  66. # Features:
  67. #  
  68. #  - Totally re-written Tilemap and Plane class. Both classes were written to
  69. #    display the map across any screen size automatically. The Tilemap class
  70. #    is probably even more efficient than the original, which will help offset
  71. #    any increased lag due to using a larger screen size with more sprites
  72. #    being displayed.
  73. #  - Every possible autotile graphic (48 per autotile) will be cached for the
  74. #    next time that tile is used.
  75. #  - Autotile animation has been made as efficient as possible, with a system
  76. #    that stores their coodinates, but only if they change. This greatly reduces
  77. #    the number of iterations at each update.
  78. #  - System creates an external file to save pre-cached data priorities and
  79. #    autotiles. This will decrease any loading times even more, and only takes a
  80. #    second, depending on the number of maps you have.
  81. #  - User defined autotile animation speed. Can change with script calls.
  82. #  - Automatic re-sizing of Bitmaps and Viewports that are 640 x 480 to the
  83. #    defined resolution, unless explicitely over-ridden in the method call.
  84. #    The graphics themselves will not be resized, but any existing scripts that
  85. #    use the normal screen size will already be configured to display different
  86. #    sizes of graphics for transitions, battlebacks, pictures, fogs, etc.
  87. #  - Option to have a log file ouput each time the game is ran, which can alert
  88. #    you to possible errors with map sizes, etc.
  89. #
  90. # Issues/Bugs/Possible Bugs:
  91. #
  92. #   - Graphic related scripts and your graphics will need to be customized to
  93. #     fit the new screen size, so this script is not for everyone.
  94. #   - The Z-axis for the Plane class, which is used for Fogs and Panoramas has
  95. #     been altered. It is now multiplied by 1000. This will likely be a minor
  96. #     issue for most, since this class is very rarely used except for Fogs and
  97. #     Panoramas, which are already far above and below respectfully.
  98. #   - Normal transitions using graphics cannot be used. With the exception of
  99. #     a standard fade, like that used when no graphic is defined will be used.
  100. #     Aside from that, only special transitions from Transition Pack can be
  101. #     used.
  102. #===============================================================================
  103. #  Credits/Thanks:
  104. #    - ForeverZer0, for script.
  105. #    - Creators of the Transition Pack and Screenshot.dll
  106. #    - Selwyn, for base resolution script
  107. #    - KK20, for Version 0.94 and above and the Tilemap class
  108. #===============================================================================
  109. #                             CONFIGURATION
  110. #===============================================================================
  111.  
  112.   SCREEN = [1024, 576]
  113.   # Define the resolution of the game screen. These values can be anything
  114.   # within reason. Centering, viewports, etc. will all be taken care of, but it
  115.   # is recommended that you use values divisible by 32 for best results.
  116.  
  117.   UPDATE_COUNT = 8
  118.   # Define the number of frames between autotile updates. The lower the number,
  119.   # the faster the animations cycle. This can be changed in-game with the
  120.   # following script call: $game_map.autotile_speed = SPEED
  121.  
  122.   RESOLUTION_LOG = true
  123.   # This will create a log in the Game directory each time the game is ran in
  124.   # DEBUG mode, which will list possible errors with map sizes, etc.
  125.  
  126. #===============================================================================
  127. # ** Resolution
  128. #===============================================================================
  129.  
  130. class Resolution
  131.  
  132.   attr_reader :version
  133.  
  134.   def initialize
  135.     # Define version.
  136.     @version = 0.96
  137.     # Set instance variables for calling basic Win32 functions.
  138.     ini = Win32API.new('kernel32', 'GetPrivateProfileString','PPPPLP', 'L')
  139.     title = "\0" * 256
  140.     ini.call('Game', 'Title', '', title, 256, '.\\Game.ini')
  141.     title.delete!("\0")
  142.     @window = Win32API.new('user32', 'FindWindow', 'PP', 'I').call('RGSS Player', title)
  143.     set_window_long = Win32API.new('user32', 'SetWindowLong', 'LIL', 'L')
  144.     set_window_pos  = Win32API.new('user32', 'SetWindowPos', 'LLIIIII', 'I')
  145.     @metrics         = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
  146.     # Set default size, displaying error if size is larger than the hardware.
  147.     default_size = self.size
  148.     if default_size[0] < SCREEN[0] || default_size[1] < SCREEN[1]
  149.       print("\"#{title}\" requires a minimum screen resolution of [#{SCREEN[0]} x #{SCREEN[1]}]\r\n\r\n" +
  150.             "\tYour Resolution: [#{default_size[0]} x #{default_size[1]}]")
  151.       exit
  152.     end
  153.     # Apply resolution change.
  154.     x = (@metrics.call(0) - SCREEN[0]) / 2
  155.     y = (@metrics.call(1) - SCREEN[1]) / 2
  156.     set_window_long.call(@window, -16, 0x14CA0000)
  157.     set_window_pos.call(@window, 0, x, y, SCREEN[0] + 6, SCREEN[1] + 26, 0)
  158.     @window = Win32API.new('user32', 'FindWindow', 'PP', 'I').call('RGSS Player', title)
  159.   end
  160.   #--------------------------------------------------------------------------
  161.   def size
  162.     # Returns the screen size of the machine.
  163.     return [@metrics.call(0), @metrics.call(1)]
  164.   end
  165.   #--------------------------------------------------------------------------
  166.   def snapshot(filename = 'Data/snap', quality = 0)
  167.     # FILENAME =   Filename that the picture will be saved as.
  168.     # FILETYPE =   0 = High Quality   1 = Low Quality
  169.     @screen = Win32API.new('screenshot.dll', 'Screenshot', 'LLLLPLL', '')
  170.     @screen.call(0, 0, SCREEN[0], SCREEN[1], filename, @window, quality)
  171.   end
  172.   #--------------------------------------------------------------------------
  173. end
  174.  
  175. #===============================================================================
  176. # ** Graphics
  177. #===============================================================================
  178.  
  179. module Graphics
  180.  
  181.   class << self
  182.     alias zer0_graphics_transition transition
  183.   end
  184.  
  185.   def self.transition(duration = 8, *args)
  186.     # Call default transition if no instance of the resolution is defined.
  187.     if $resolution == nil
  188.       zer0_graphics_transition(duration, *args)
  189.     else
  190.       # Skip this section and instantly transition graphics if duration is 0.
  191.       if duration > 0
  192.         # Take a snapshot of the the screen, overlaying screen with graphic.
  193.         $resolution.snapshot
  194.         zer0_graphics_transition(0)
  195.         # Create screen instance
  196.         sprite = Sprite.new(Viewport.new(0, 0, SCREEN[0], SCREEN[1]))
  197.         sprite.bitmap = Bitmap.new('Data/snap')
  198.         # Use a simple fade if transition is not defined.
  199.         fade = 255 / duration
  200.         duration.times { sprite.opacity -= fade ; update }
  201.         # Dispose sprite and delete snapshot file.
  202.         [sprite, sprite.bitmap].each {|obj| obj.dispose }
  203.         File.delete('Data/snap')
  204.       end
  205.      zer0_graphics_transition(0)
  206.    end
  207.  end
  208. end  
  209.  
  210. #===============================================================================
  211. # ** RPG::Cache
  212. #===============================================================================
  213.  
  214. module RPG::Cache
  215.  
  216.   AUTO_INDEX = [
  217.  
  218.   [27,28,33,34],  [5,28,33,34],  [27,6,33,34],  [5,6,33,34],
  219.   [27,28,33,12],  [5,28,33,12],  [27,6,33,12],  [5,6,33,12],
  220.   [27,28,11,34],  [5,28,11,34],  [27,6,11,34],  [5,6,11,34],
  221.   [27,28,11,12],  [5,28,11,12],  [27,6,11,12],  [5,6,11,12],
  222.   [25,26,31,32],  [25,6,31,32],  [25,26,31,12], [25,6,31,12],
  223.   [15,16,21,22],  [15,16,21,12], [15,16,11,22], [15,16,11,12],
  224.   [29,30,35,36],  [29,30,11,36], [5,30,35,36],  [5,30,11,36],
  225.   [39,40,45,46],  [5,40,45,46],  [39,6,45,46],  [5,6,45,46],
  226.   [25,30,31,36],  [15,16,45,46], [13,14,19,20], [13,14,19,12],
  227.   [17,18,23,24],  [17,18,11,24], [41,42,47,48], [5,42,47,48],
  228.   [37,38,43,44],  [37,6,43,44],  [13,18,19,24], [13,14,43,44],
  229.   [37,42,43,48],  [17,18,47,48], [13,18,43,48], [1,2,7,8]
  230.    
  231.   ]
  232.  
  233.   def self.autotile(filename)
  234.     key = "Graphics/Autotiles/#{filename}"
  235.     if !@cache.include?(key) || @cache[key].disposed?
  236.       # Cache the autotile graphic.
  237.       @cache[key] = (filename == '') ? Bitmap.new(128, 96) : Bitmap.new(key)
  238.       # Cache each configuration of this autotile.
  239.       new_bm = self.format_autotiles(@cache[key], filename)
  240.       @cache[key].dispose
  241.       @cache[key] = new_bm
  242.     end
  243.     return @cache[key]
  244.   end
  245.  
  246.   def self.format_autotiles(bitmap, filename)
  247.     if bitmap.height > 32
  248.       frames = bitmap.width / 96
  249.       template = Bitmap.new(256*frames,192)
  250.       # Create a bitmap to use as a template for creation.
  251.       (0..frames-1).each{|frame|
  252.       (0...6).each {|i| (0...8).each {|j| AUTO_INDEX[8*i+j].each {|number|
  253.         number -= 1
  254.         x, y = 16 * (number % 6), 16 * (number / 6)
  255.         rect = Rect.new(x + (frame * 96), y, 16, 16)
  256.         template.blt((32 * j + x % 32) + (frame * 256), 32 * i + y % 32, bitmap, rect)
  257.       }}}}
  258.       return template
  259.     else
  260.       return bitmap
  261.     end
  262.   end
  263.  
  264. end
  265. #===============================================================================
  266. # ** Tilemap_DataTable
  267. #===============================================================================
  268. class Tilemap_DataTable
  269.   attr_accessor :updates
  270.   attr_accessor :table
  271.   def initialize(table)
  272.     @table = table
  273.     @updates = []
  274.   end
  275.  
  276.   def updated
  277.     return @updates.size >= 1
  278.   end
  279.  
  280.   def [](x,y=nil,z=nil)
  281.     return @table[x,y,z] unless z.nil?
  282.     return @table[x,y] unless y.nil?
  283.     return @table[x]
  284.   end
  285.  
  286.   def []=(x,y,z=nil,t_id=nil)
  287.     @updates.push([x,y,z,t_id]) unless t_id.nil?
  288.     t_id.nil? ? (z.nil? ? @table[x] = y : @table[x,y] = z) : @table[x,y,z] = t_id
  289.   end
  290.  
  291.   def xsize; return @table.xsize; end
  292.   def ysize; return @table.ysize; end
  293.   def zsize; return @table.zsize; end
  294.    
  295.   def resize(x,y=nil,z=nil); @table.resize(x,y,z); end
  296.  
  297. end
  298. #===============================================================================
  299. # ** Tilemap
  300. #===============================================================================
  301.  
  302. class Tilemap
  303.  
  304.   attr_reader   :map_data, :ox, :oy, :viewport
  305.   attr_accessor :tileset, :autotiles, :priorities
  306.  
  307.   def initialize(viewport)
  308.     # Initialize instance variables to store required data.
  309.     @viewport, @autotiles, @tile_sprites, @ox, @oy = viewport, [], [], 0, 0
  310.     @current_frame, @total_frames = [], []
  311.     @tilemap_drawn = false
  312.     @ox_oy_set = [false, false]
  313.     # Get priority data for this tileset from instance of Game_Map.
  314.     @priorities = $game_map.priorities
  315.     # Holds all the Sprite instances of animating tiles (keys based on tile's ID)
  316.     @animating_tiles = {}
  317.     # Game map's x/y location of the top left corner tile
  318.     @corner_tile_loc = [-1,-1]
  319.   end
  320.   #-----------------------------------------------------------------------------
  321.   # Initialize all tile sprites. Draws three sprites per (x,y).
  322.   #-----------------------------------------------------------------------------
  323.   def init_tiles
  324.     # Determine how many frames of animation this autotile has
  325.     for i in 0..6
  326.       bm = @autotiles[i]
  327.       if bm.nil?
  328.         @total_frames = 1
  329.       elsif bm.height > 32
  330.         @total_frames[i] = bm.width / 256
  331.       else
  332.         @total_frames[i] = bm.width / 32
  333.       end
  334.       @current_frame[i] = 0
  335.     end
  336.     # Turn on flag that the tilemap sprites have been initialized
  337.     @tilemap_drawn = true
  338.    
  339.     @animating_tiles.clear
  340.     # Create a sprite and viewport to use for each priority level.
  341.     (0...((SCREEN[0]/32+2) * (SCREEN[1]/32+2))*3).each{|i|
  342.       @tile_sprites[i/3] = [] if @tile_sprites[i/3].nil?
  343.       @tile_sprites[i/3][i%3] = Sprite.new(@viewport) unless @tile_sprites[i/3][i%3].is_a?(Sprite)
  344.       # Rename to something shorter and easier to work with for below
  345.       tile = @tile_sprites[i/3][i%3]
  346.       # Assign tile's respective ID value
  347.       tile.tile_sprite_id = i
  348.       # Draw sprite at index location (ex. ID 0 should always be the top-left sprite)
  349.       tile.x = (i % ((SCREEN[0]/32+2)*3) / 3 * 32) - 32 + (@ox % 32)
  350.       tile.y = (i / ((SCREEN[0]/32+2)*3) * 32) - 32 + (@oy % 32)
  351.      
  352.       map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
  353.       @corner_tile_loc = [map_x, map_y] if i == 0
  354.       # If the tile happens to be drawn along the outside borders of the map
  355.       if map_x < 0 || map_x >= $game_map.width || map_y < 0 || map_y >= $game_map.height
  356.         tile.z = 0
  357.         tile.bitmap = RPG::Cache.picture('')
  358.         tile.src_rect.set(0,0,0,0)
  359.       else # Tile is actually on the map
  360.         tile_id = @map_data[map_x,map_y,i%3]
  361.         if @priorities[tile_id] == 0
  362.           tile.z = 0
  363.         else
  364.           tile.z = tile.y + @priorities[tile_id] * 32 + 32
  365.         end
  366.         # No tile exists here
  367.         if tile_id == 0
  368.           tile.bitmap = RPG::Cache.picture('')#@tileset
  369.           tile.src_rect.set(0,0,0,0)
  370.         elsif tile_id >= 384 # non-autotile
  371.           tile.bitmap = @tileset
  372.           tile.src_rect.set(((tile_id - 384) % 8)*32,((tile_id - 384) / 8)*32, 32, 32)
  373.         else # autotile
  374.           tile.bitmap = @autotiles[tile_id/48-1]
  375.           tile.src_rect.set(((tile_id % 48) % 8)*32,((tile_id % 48) / 8)*32, 32, 32)
  376.           @animating_tiles[i] = tile if tile.bitmap.width > 256
  377.         end
  378.       end
  379.     }
  380.     # Sprite ID located at top left corner (ranges from 0..map_width * map_height
  381.     @corner_index = 0
  382.   end
  383.  
  384.   #-----------------------------------------------------------------------------
  385.   # Makes update to ox and oy. Sprites out of range will be moved based on these
  386.   # two values.
  387.   #-----------------------------------------------------------------------------
  388.   def ox=(ox)
  389.     #
  390.     unless @tilemap_drawn
  391.       @ox = ox
  392.       @ox_oy_set[0] = true
  393.       return
  394.     end
  395.    
  396.     return if @ox == ox
  397.     # Shift all tiles left or right by the difference
  398.     shift = @ox - ox
  399.  
  400.     @tile_sprites.each {|set| set.each{|tile| tile.x += shift }}
  401.     @ox = ox
  402.     # Determine if columns need to be shifted
  403.     col_num = @corner_index
  404.     #return unless @tile_sprites[col_num][0].x <= -49 || @tile_sprites[col_num][0].x >= -17
  405.     while @tile_sprites[col_num][0].x <= -49 || @tile_sprites[col_num][0].x >= -17
  406.      
  407.     @corner_tile_loc[0] += (shift < 0 ? 1 : -1)
  408.     modTileId = ((SCREEN[0]+64)*(SCREEN[1]+64))/1024    
  409.     # If new ox is greater than old ox
  410.     if shift < 0
  411.       # Move all sprites in left column to the right side and change bitmaps
  412.       # and z-values
  413.       (0...(SCREEN[1]/32+2)).each{|n|
  414.         j = ((SCREEN[0]/32+2) * n + col_num) % modTileId
  415.         @tile_sprites[j].each_index{|i|
  416.           tile = @tile_sprites[j][i]
  417.           @animating_tiles.delete(tile.tile_sprite_id)
  418.           tile.x += 64 + SCREEN[0]
  419.          
  420.           map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
  421.           tile_id = @map_data[map_x,map_y,i]
  422.          
  423.           if tile_id.nil?
  424.             tile.z = [map_y * 32, 0].max
  425.             tile.bitmap = RPG::Cache.picture('')
  426.             tile.src_rect.set(0,0,0,0)
  427.             next
  428.           else
  429.             if @priorities[tile_id] == 0
  430.               tile.z = 0
  431.             else
  432.               tile.z = 32 + (tile.y/32) * 32 + @priorities[tile_id] * 32
  433.             end
  434.           end
  435.           if tile_id == 0
  436.             tile.bitmap = RPG::Cache.picture('')
  437.             tile.src_rect.set(0,0,0,0)
  438.           elsif tile_id >= 384
  439.             tile.bitmap = @tileset
  440.             tile.src_rect.set(((tile_id - 384) % 8) * 32,((tile_id - 384) / 8) *32, 32, 32)
  441.           else
  442.             auto_id = tile_id/48-1
  443.             tile.bitmap = @autotiles[auto_id]
  444.             tile.src_rect.set(((tile_id % 48) % 8)*32 + @current_frame[auto_id] * 256,((tile_id % 48) / 8)*32, 32, 32)
  445.             @animating_tiles[tile.tile_sprite_id] = tile if @total_frames[auto_id] > 1
  446.           end
  447.         }
  448.       }
  449.       # New corner should be the tile immediately right of the previous tile
  450.       col_num /= SCREEN[0]/32+2
  451.       col_num *= SCREEN[0]/32+2
  452.       @corner_index = (@corner_index + 1) % (SCREEN[0]/32+2) + col_num
  453.     else
  454.       # Shift right column to the left
  455.       # Gets the right column
  456.       row_index = col_num / (SCREEN[0]/32+2)
  457.       row_index *= (SCREEN[0]/32+2)
  458.       col_num = (@corner_index - 1) % (SCREEN[0]/32+2) + row_index
  459.      
  460.       (0...(SCREEN[1]/32+2)).each{|n|
  461.         j = ((SCREEN[0]/32+2) * n + col_num) % modTileId
  462.         @tile_sprites[j].each_index{|i|
  463.           tile = @tile_sprites[j][i]
  464.           @animating_tiles.delete(tile.tile_sprite_id)
  465.           tile.x -= 64 + SCREEN[0]
  466.          
  467.           map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
  468.           tile_id = @map_data[map_x,map_y,i]
  469.           if tile_id.nil?
  470.             tile.z = [map_y * 32, 0].max
  471.             tile.bitmap = @tileset
  472.             tile.src_rect.set(0,0,0,0)
  473.             next
  474.           else
  475.             if @priorities[tile_id] == 0
  476.               tile.z = 0
  477.             else
  478.               tile.z = 32 + (tile.y/32) * 32 + @priorities[tile_id] * 32
  479.             end
  480.           end
  481.           if tile_id == 0
  482.             tile.bitmap = RPG::Cache.picture('')
  483.             tile.src_rect.set(0,0,0,0)
  484.           elsif tile_id >= 384
  485.             tile.bitmap = @tileset
  486.             tile.src_rect.set(((tile_id - 384) % 8)*32,((tile_id - 384) / 8)*32, 32, 32)
  487.           else
  488.             auto_id = tile_id/48-1
  489.             tile.bitmap = @autotiles[auto_id]
  490.             tile.src_rect.set(((tile_id % 48) % 8)*32 + @current_frame[auto_id] * 256,((tile_id % 48) / 8)*32, 32, 32)
  491.             @animating_tiles[tile.tile_sprite_id] = tile if @total_frames[auto_id] > 1
  492.           end
  493.         }
  494.       }
  495.       col_num /= SCREEN[0]/32+2
  496.       col_num *= SCREEN[0]/32+2
  497.       @corner_index = (@corner_index - 1) % (SCREEN[0]/32+2) + col_num
  498.     end
  499.     col_num = @corner_index
  500.     end #end of while
  501.   end
  502.  
  503.   #-----------------------------------------------------------------------------
  504.  
  505.   def oy=(oy)
  506.     #
  507.     unless @tilemap_drawn
  508.       @oy = oy
  509.       @ox_oy_set[1] = true
  510.       return
  511.     end
  512.    
  513.     return if @oy == oy
  514.     # Shift all tiles up or down by the difference, and change z-value
  515.     shift = @oy - oy
  516.  
  517.     @tile_sprites.each {|set| set.each{|tile| tile.y += shift; tile.z += shift unless tile.z == 0 }}
  518.     @oy = oy
  519.     # Determine if rows need to be shifted
  520.     row_num = @corner_index
  521.     #return unless @tile_sprites[row_num][0].y <= -49 || @tile_sprites[row_num][0].y >= -17
  522.     while @tile_sprites[row_num][0].y <= -49 || @tile_sprites[row_num][0].y >= -17
  523.    
  524.      
  525.     # Needed for resetting the new corner index much later.
  526.     modTileId = ((SCREEN[0]+64)*(SCREEN[1]+64))/1024
  527.     @corner_tile_loc[1] += (shift < 0 ? 1 : -1)
  528.     # If new oy is greater than old oy
  529.     if shift < 0
  530.       row_num /= SCREEN[0]/32+2
  531.       row_num *= SCREEN[0]/32+2
  532.       # Move all sprites in top row to the bottom side and change bitmaps
  533.       # and z-values
  534.       (0...(SCREEN[0]/32+2)).each{|n|
  535.         # Run through each triad of sprites from left to right
  536.         j = n + row_num
  537.         @tile_sprites[j].each_index{|i|
  538.           # Get each individual tile on each layer
  539.           tile = @tile_sprites[j][i]
  540.           @animating_tiles.delete(tile.tile_sprite_id)
  541.           tile.y += 64 + SCREEN[1]
  542.           # Determine what map coordinate this tile now resides at...
  543.           map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
  544.           # ...and get its tile_id
  545.           tile_id = @map_data[map_x,map_y,i]
  546.           # If no tile exists here (effectively out of array bounds)
  547.           if tile_id.nil?
  548.             tile.z = [map_y * 32, 0].max
  549.             tile.bitmap = RPG::Cache.picture('')
  550.             tile.src_rect.set(0,0,0,0)
  551.             next
  552.           else # Tile exists. Figure out its z-coordinate based on priority
  553.             if @priorities[tile_id] == 0
  554.               tile.z = 0
  555.             else
  556.               tile.z = 32 + (tile.y/32) * 32 + @priorities[tile_id] * 32
  557.             end
  558.           end
  559.           # If empty tile
  560.           if tile_id == 0
  561.             tile.bitmap = RPG::Cache.picture('')
  562.             tile.src_rect.set(0,0,0,0)
  563.           # If not an autotile
  564.           elsif tile_id >= 384
  565.             tile.bitmap = @tileset
  566.             tile.src_rect.set(((tile_id - 384) % 8) * 32,((tile_id - 384) / 8) *32, 32, 32)
  567.           else # Autotile
  568.             auto_id = tile_id/48-1
  569.             tile.bitmap = @autotiles[auto_id]
  570.             tile.src_rect.set(((tile_id % 48) % 8)*32 + @current_frame[auto_id] * 256,((tile_id % 48) / 8)*32, 32, 32)
  571.             @animating_tiles[tile.tile_sprite_id] = tile if @total_frames[auto_id] > 1
  572.           end
  573.         }
  574.       }
  575.      
  576.       @corner_index = (@corner_index + (SCREEN[0]/32+2)) % modTileId
  577.     else
  578.       row_num = (@corner_index - (SCREEN[0]/32+2)) % modTileId
  579.       row_num /= SCREEN[0]/32+2
  580.       row_num *= SCREEN[0]/32+2
  581.       (0...(SCREEN[0]/32+2)).each{|n|
  582.         # Run through each triad of sprites from left to right
  583.         j = n + row_num
  584.         @tile_sprites[j].each_index{|i|
  585.           # Get each individual tile on each layer
  586.           tile = @tile_sprites[j][i]
  587.           @animating_tiles.delete(tile.tile_sprite_id)
  588.           tile.y -= 64 + SCREEN[1]
  589.           # Determine what map coordinate this tile now resides at...
  590.           map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
  591.           # ...and get its tile_id
  592.           tile_id = @map_data[map_x,map_y,i]
  593.           # If no tile exists here (effectively out of array bounds)
  594.           if tile_id.nil?
  595.             tile.z = [map_y * 32, 0].max
  596.             tile.bitmap = RPG::Cache.picture('')
  597.             tile.src_rect.set(0,0,0,0)
  598.             next
  599.           else # Tile exists. Figure out its z-coordinate based on priority
  600.             if @priorities[tile_id] == 0
  601.               tile.z = 0
  602.             else
  603.               tile.z = 32 + (tile.y/32) * 32 + @priorities[tile_id] * 32
  604.             end
  605.           end
  606.           # If empty tile
  607.           if tile_id == 0
  608.             tile.bitmap = RPG::Cache.picture('')
  609.             tile.src_rect.set(0,0,0,0)
  610.           # If not an autotile
  611.           elsif tile_id >= 384
  612.             tile.bitmap = @tileset
  613.             tile.src_rect.set(((tile_id - 384) % 8) * 32,((tile_id - 384) / 8) *32, 32, 32)
  614.           else # Autotile
  615.             auto_id = tile_id/48-1
  616.             tile.bitmap = @autotiles[auto_id]
  617.             tile.src_rect.set(((tile_id % 48) % 8)*32 + @current_frame[auto_id] * 256,((tile_id % 48) / 8)*32, 32, 32)
  618.             @animating_tiles[tile.tile_sprite_id] = tile if @total_frames[auto_id] > 1
  619.           end
  620.         }
  621.       }
  622.       @corner_index = (@corner_index - (SCREEN[0]/32+2)) % modTileId
  623.     end
  624.     row_num = @corner_index
  625.     end # end of while
  626.   end
  627.   #-----------------------------------------------------------------------------
  628.   # Dispose all the tile sprites
  629.   #-----------------------------------------------------------------------------
  630.   def dispose
  631.     # Dispose all of the sprites
  632.     @tile_sprites.each {|set| set.each{|tile| tile.dispose }}
  633.     @tile_sprites.clear
  634.     @animating_tiles.clear
  635.   end
  636.   #-----------------------------------------------------------------------------
  637.   # Set map data
  638.   #-----------------------------------------------------------------------------
  639.   def map_data=(data)
  640.     # Set the map data to new class
  641.     if data.is_a?(Tilemap_DataTable)
  642.       @map_data = data
  643.     else
  644.       @map_data = Tilemap_DataTable.new(data)
  645.     end
  646.     @map_data.table = @map_data.table.clone
  647.     @map_data.updates = []
  648.    
  649.     @animating_tiles.clear
  650.     @tilemap_drawn = false
  651.   end
  652.   #-----------------------------------------------------------------------------
  653.   # Update the tile sprites; make changes to the map_data and update autotiles
  654.   #-----------------------------------------------------------------------------
  655.   def update
  656.     # Can't update anything if the ox and oy have not yet been set
  657.     return if @ox_oy_set != [true, true]
  658.     # If the tilemap sprites have not been initialized, GO DO IT
  659.     if !@tilemap_drawn
  660.       init_tiles
  661.     end
  662.    
  663.     # If made any changes to $game_map.data, the proper graphics will be drawn
  664.     if @map_data.updated
  665.       @map_data.updates.each{|item|
  666.         x,y,z,tile_id = item
  667.         # If this changed tile is visible on screen
  668.         if x.between?(@corner_tile_loc[0], @corner_tile_loc[0]+(SCREEN[0]/32 + 1)) and
  669.         y.between?(@corner_tile_loc[1], @corner_tile_loc[1]+(SCREEN[1]/32 + 1))
  670.          
  671.           x_dif = x - @corner_tile_loc[0]
  672.           y_dif = y - @corner_tile_loc[1]
  673.          
  674.           id = @corner_index + x_dif
  675.           id -= SCREEN[0]/32+2 if id/(SCREEN[0]/32+2) > @corner_index/(SCREEN[0]/32+2)
  676.          
  677.           id += y_dif * (SCREEN[0]/32+2)
  678.           id -= (SCREEN[0]/32+2)*(SCREEN[1]/32+2) if id >= (SCREEN[0]/32+2)*(SCREEN[1]/32+2)
  679.          
  680.           tile = @tile_sprites[id][z]
  681.           @animating_tiles.delete(tile.tile_sprite_id)
  682.           #Figure out its z-coordinate based on priority
  683.           if @priorities[tile_id] == 0
  684.             tile.z = 0
  685.           else
  686.             tile.z = 32 + (tile.y/32) * 32 + @priorities[tile_id] * 32
  687.           end
  688.           # If empty tile
  689.           if tile_id == 0
  690.             tile.bitmap = RPG::Cache.picture('')
  691.             tile.src_rect.set(0,0,0,0)
  692.           # If not an autotile
  693.           elsif tile_id >= 384
  694.             tile.bitmap = @tileset
  695.             tile.src_rect.set(((tile_id - 384) % 8) * 32,((tile_id - 384) / 8) *32, 32, 32)
  696.           else # Autotile
  697.             auto_id = tile_id/48-1
  698.             tile.bitmap = @autotiles[auto_id]
  699.             tile.src_rect.set(((tile_id % 48) % 8)*32 + @current_frame[auto_id] * 256,((tile_id % 48) / 8)*32, 32, 32)
  700.             @animating_tiles[tile.tile_sprite_id] = tile if @total_frames[auto_id] > 1
  701.           end
  702.         end
  703.       }
  704.       @map_data.updates = []
  705.     end
  706.  
  707.     # Update the sprites.
  708.     if Graphics.frame_count % $game_map.autotile_speed == 0
  709.       # Increase current frame of tile by one, looping by width.
  710.       for i in 0..6
  711.         @current_frame[i] = (@current_frame[i] + 1) % @total_frames[i]
  712.       end
  713.       @animating_tiles.each_value{|tile|
  714.         frames = tile.bitmap.width
  715.         tile.src_rect.set((tile.src_rect.x + 256) % frames, tile.src_rect.y, 32, 32)
  716.       }
  717.     end
  718.   end
  719. end
  720.  
  721. #===============================================================================
  722. # Game_Map
  723. #===============================================================================
  724.  
  725. class Game_Map
  726.  
  727.   attr_reader :tile_size, :autotile_speed, :autotile_data, :priority_data
  728.  
  729.   alias zer0_load_autotile_data_init initialize
  730.   def initialize
  731.     # Call original method.
  732.     zer0_load_autotile_data_init
  733.     # Store the screen dimensions in tiles to save on calculations later.
  734.     @tile_size = [SCREEN[0], SCREEN[1]].collect {|n| (n / 32.0).ceil }
  735.     @autotile_speed = UPDATE_COUNT
  736.   end
  737.  
  738.   alias zer0_map_edge_setup setup
  739.   def setup(map_id)
  740.     # Call original method.
  741.     zer0_map_edge_setup(map_id)
  742.     # Change Map's data into a special Table class
  743.     @map.data = Tilemap_DataTable.new(@map.data)
  744.     # Find the displayed area of the map in tiles. No calcualting every step.
  745.     @map_edge = [self.width - @tile_size[0], self.height - @tile_size[1]]
  746.     @map_edge.collect! {|size| size * 128 }
  747.   end
  748.  
  749.   def scroll_down(distance)
  750.     # Find point that the map edge meets the screen edge, using custom size.
  751.     @display_y = [@display_y + distance, @map_edge[1]].min
  752.   end
  753.  
  754.   def scroll_right(distance)
  755.     # Find point that the map edge meets the screen edge, using custom size.
  756.     @display_x = [@display_x + distance, @map_edge[0]].min
  757.   end
  758.  
  759.   def autotile_speed=(speed)
  760.     # Keep the speed above 0 to prevent the ZeroDivision Error.
  761.     @autotile_speed = speed
  762.     @autotile_speed = 1 if @autotile_speed < 1
  763.   end
  764.  
  765. end
  766.  
  767. #===============================================================================
  768. # ** Game_Player
  769. #===============================================================================
  770.  
  771. class Game_Player
  772.  
  773.   CENTER_X = ((SCREEN[0] / 2) - 16) * 4    # Center screen x-coordinate * 4
  774.   CENTER_Y = ((SCREEN[1] / 2) - 16) * 4    # Center screen y-coordinate * 4
  775.  
  776.   def center(x, y)
  777.     # Recalculate the screen center based on the new resolution.
  778.     max_x = ($game_map.width - $game_map.tile_size[0]) * 128
  779.     max_y = ($game_map.height - $game_map.tile_size[1]) * 128
  780.     $game_map.display_x = [0, [x * 128 - CENTER_X, max_x].min].max
  781.     $game_map.display_y = [0, [y * 128 - CENTER_Y, max_y].min].max
  782.   end  
  783. end
  784.  
  785. #===============================================================================
  786. # ** Sprite
  787. #===============================================================================
  788. class Sprite
  789.   attr_accessor :tile_sprite_id
  790.   alias tile_sprite_id_init initialize
  791.   def initialize(view = nil)
  792.     # No defined ID
  793.     @tile_sprite_id = nil
  794.     # Call original method.
  795.     tile_sprite_id_init(view)
  796.   end
  797. end
  798.  
  799. #===============================================================================
  800. # ** Viewport
  801. #===============================================================================
  802. class Viewport
  803.  
  804.   alias zer0_viewport_resize_init initialize
  805.   def initialize(x=0, y=0, width=SCREEN[0], height=SCREEN[1], override=false)
  806.     if x.is_a?(Rect)
  807.       # If first argument is a Rectangle, just use it as the argument.
  808.       zer0_viewport_resize_init(x)
  809.     elsif [x, y, width, height] == [0, 0, 640, 480] && !override
  810.       # Resize fullscreen viewport, unless explicitly overridden.
  811.       zer0_viewport_resize_init(Rect.new(0, 0, SCREEN[0], SCREEN[1]))
  812.     else
  813.       # Call method normally.
  814.       zer0_viewport_resize_init(Rect.new(x, y, width, height))
  815.     end
  816.   end
  817.  
  818.   def resize(*args)
  819.     # Resize the viewport. Can call with (X, Y, WIDTH, HEIGHT) or (RECT).
  820.     self.rect = args[0].is_a?(Rect) ? args[0] : Rect.new(*args)
  821.   end
  822. end
  823. #===============================================================================
  824. # ** Plane
  825. #===============================================================================
  826.  
  827. class Plane < Sprite
  828.  
  829.   def z=(z)
  830.     # Change the Z value of the viewport, not the sprite.
  831.     super(z * 1000)
  832.   end
  833.  
  834.   def ox=(ox)
  835.     return if @bitmap == nil
  836.     # Have viewport stay in loop on X-axis.
  837.     super(ox % @bitmap.width)
  838.   end
  839.  
  840.   def oy=(oy)
  841.     return if @bitmap == nil
  842.     # Have viewport stay in loop on Y-axis.
  843.     super(oy % @bitmap.height)
  844.   end
  845.  
  846.   def bitmap
  847.     # Return the single bitmap, before it was tiled.
  848.     return @bitmap
  849.   end
  850.  
  851.   def bitmap=(tile)
  852.     @bitmap = tile
  853.     # Calculate the number of tiles it takes to span screen in both directions.
  854.     xx = 1 + (SCREEN[0].to_f / tile.width).ceil
  855.     yy = 1 + (SCREEN[1].to_f / tile.height).ceil
  856.     # Create appropriately sized bitmap, then tile across it with source image.
  857.     plane = Bitmap.new(@bitmap.width * xx, @bitmap.height * yy)
  858.     (0..xx).each {|x| (0..yy).each {|y|
  859.       plane.blt(x * @bitmap.width, y * @bitmap.height, @bitmap, @bitmap.rect)
  860.     }}
  861.     # Set the bitmap to the sprite through its super class (Sprite).
  862.     super(plane)
  863.   end
  864.  
  865.   # Redefine methods dealing with coordinates (defined in super) to do nothing.
  866.   def x; end
  867.   def y; end
  868.   def x=(x); end
  869.   def y=(y); end
  870. end
  871. #===============================================================================
  872. # ** Integer
  873. #===============================================================================
  874.  
  875. class Integer
  876.    
  877.   def gcd(num)
  878.     # Returns the greatest common denominator of self and num.
  879.     min, max = self.abs, num.abs
  880.     while min > 0
  881.       tmp = min
  882.       min = max % min
  883.       max = tmp
  884.     end
  885.     return max
  886.   end
  887.  
  888.   def lcm(num)
  889.     # Returns the lowest common multiple of self and num.
  890.     return [self, num].include?(0) ? 0 : (self / self.gcd(num) * num).abs
  891.   end
  892. end
  893. #===============================================================================
  894. # ** Resolution Log
  895. #===============================================================================
  896. if RESOLUTION_LOG
  897.     undersize, mapinfo = [], load_data('Data/MapInfos.rxdata')
  898.     # Create a text file and write the header.
  899.     file = File.open('Resolution Log.txt', 'wb')
  900.     file.write("[RESOLUTION LOG]\r\n\r\n")
  901.     time = Time.now.strftime("%x at %I:%M:%S %p")
  902.     file.write("  Logged on #{time}\r\n\r\n")
  903.     lcm = SCREEN[0].lcm(SCREEN[1]).to_f
  904.     aspect = [(lcm / SCREEN[1]), (lcm / SCREEN[0])].collect {|num| num.round }
  905.     file.write("RESOLUTION:\r\n  #{SCREEN[0].to_i} x #{SCREEN[1].to_i}\r\n")
  906.     file.write("ASPECT RATIO:\r\n  #{aspect[0]}:#{aspect[1]}\r\n")
  907.     file.write("MINIMUM MAP SIZE:\r\n  #{(SCREEN[0] / 32).ceil} x #{(SCREEN[1] / 32).ceil}\r\n\r\n")
  908.     file.write("UNDERSIZED MAPS:\r\n")
  909.     mapinfo.keys.each {|key|
  910.       map = load_data(sprintf("Data/Map%03d.rxdata", key))
  911.       next if map.width*32 >= SCREEN[0] && map.height*32 >= SCREEN[1]
  912.       undersize.push(key)
  913.     }
  914.     unless undersize.empty?
  915.       file.write("The following maps are too small for the defined resolution. They should be adjusted to prevent graphical errors.\r\n\r\n")
  916.       undersize.sort.each {|id| file.write("    MAP[#{id}]:  #{mapinfo[id].name}\r\n") }
  917.       file.write("\r\n")
  918.     else
  919.       file.write('    All maps are sized correctly.')
  920.     end
  921.     file.close
  922. end
  923.  
  924. # Call the resolution, setting it to a global variable for plug-ins.
  925. $resolution = Resolution.new
RAW Paste Data