Advertisement
LiTTleDRAgo

[RGSS] Custom Resolution (edited)

Jan 27th, 2014
3,329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 60.10 KB | None | 0 0
  1. #==============================================================================
  2. # Custom Resolution (DLL-less)
  3. # Authors: ForeverZer0, KK20, LiTTleDRAgo
  4. # Version: 0.97e
  5. # Date: 11.2.2014
  6. #==============================================================================
  7. # LiTTleDRAgo's Notes
  8. #==============================================================================
  9. #
  10. #  Change Resolution in game :
  11. #      $resolution.change_resolution(width, height)
  12. #
  13. #  Enable / Disable the script :
  14. #      $resolution.enable(true / false)
  15. #
  16. #  Change Tile in game :
  17. #      $game_map.change_tile(x,y,layer,tile_id)
  18. #
  19. #  Note that X in the notes below means that it's no longer true
  20. #
  21. #  If you're using RGSS3, don't use map larger than 20 x 15 or
  22. #  resolution larger than 640 x 480
  23. #
  24. #==============================================================================
  25. # KK20's Notes
  26. #==============================================================================
  27. # Introduction:
  28. #
  29. #   This script is intended to create screen resolutions other than 640 x 480.
  30. #   The script comes with its own Tilemap rewrite in order to combat larger
  31. #   screen resolutions (because anything beyond 640 x 480 is not drawn).
  32. #
  33. # Instructions:
  34. #
  35. #   Place script above 'Main'. Probably best to put it below all your other
  36. #   custom scripts.
  37. #   This version does not require the 'screenshot.dll'.
  38. #
  39. # Things to Consider:
  40. #
  41. #  X Fullscreen will change the resolution back to 640 x 480. A solution is in
  42. #    the works.
  43. #  - Transitions do not work properly on larger resolutions. You can use a
  44. #    Transitions Add-Ons script if you want better transitions (otherwise, all
  45. #    you will get is the default fade in/out). Links listed below.
  46. #  - Custom scripts that draw windows to the screen will probably need edits.
  47. #  - Larger resolutions = more processing power = more lag
  48. #
  49. #
  50. #  ***************************************************************************
  51. #  * THIS IS STILL A WORK IN PROGRESS; IF YOU FIND ANYTHING PLEASE REPORT IT *
  52. #  ***************************************************************************
  53. #
  54. #  Links:
  55. #  - Fantasist's Transitions Pack
  56. #    http://forum.chaos-project.com/index.php/topic,1390.0.html
  57. #  - ForeverZer0's Add-ons
  58. #    http://forum.chaos-project.com/index.php/topic,7862.0.html
  59. #  - ThallionDarkshine's Add-ons
  60. #    http://forum.chaos-project.com/index.php/topic,12655.0.html
  61. #  - Drago Transition Pack
  62. #    http://forum.chaos-project.com/index.php/topic,13488.0.html
  63. #
  64. #==============================================================================
  65. # ForeverZer0's Notes from v0.93                   (outdated information)
  66. #==============================================================================
  67. # Introduction:
  68. #
  69. #   My goal in creating this script was to create a system that allowed the
  70. #   user to set the screen size to something other than 640 x 480, but not have
  71. #   make huge sacrifices in compatibility and performance. Although the script
  72. #   is not simply Plug-and-Play, it is about as close as one can achieve with a
  73. #   script of this nature.
  74. #
  75. # Instructions:
  76. #
  77. #  X Place the "screenshot.dll" from Fantasist's Transition Pack script, which
  78. #    can be found here: http://sendspace.com/file/yjd54h in your game folder
  79. #  - Place this script above main, below default scripts.
  80. #  - In my experience, unchecking "Reduce Screen Flickering" actually helps
  81. #    the screen not to flicker. Open menu with F1 while playing and set this
  82. #    to what you get the best results with.
  83. #
  84. # Features:
  85. #  
  86. #  X Totally re-written Tilemap and Plane class. Both classes were written to
  87. #    display the map across any screen size automatically. The Tilemap class
  88. #    is probably even more efficient than the original, which will help offset
  89. #    any increased lag due to using a larger screen size with more sprites
  90. #    being displayed.
  91. #  - Every possible autotile graphic (48 per autotile) will be cached for the
  92. #    next time that tile is used.
  93. #  - Autotile animation has been made as efficient as possible, with a system
  94. #    that stores their coodinates, but only if they change. This greatly
  95. #    reduces the number of iterations at each update.
  96. #  X System creates an external file to save pre-cached data priorities and
  97. #    autotiles. This will decrease any loading times even more, and only takes
  98. #    a second, depending on the number of maps you have.
  99. #  - User defined autotile animation speed. Can change with script calls.
  100. #  - Automatic re-sizing of Bitmaps and Viewports that are 640 x 480 to the
  101. #    defined resolution, unless explicitely over-ridden in the method call.
  102. #    The graphics themselves will not be resized, but any existing scripts that
  103. #    use the normal screen size will already be configured to display different
  104. #    sizes of graphics for transitions, battlebacks, pictures, fogs, etc.
  105. #  X Option to have a log file ouput each time the game is ran, which can alert
  106. #    you to possible errors with map sizes, etc.
  107. #
  108. # Issues/Bugs/Possible Bugs:
  109. #
  110. #   - Graphic related scripts and your graphics will need to be customized to
  111. #     fit the new screen size, so this script is not for everyone.
  112. #   X The Z-axis for the Plane class, which is used for Fogs and Panoramas has
  113. #     been altered. It is now multiplied by 1000. This will likely be a minor
  114. #     issue for most, since this class is very rarely used except for Fogs and
  115. #     Panoramas, which are already far above and below respectfully.
  116. #   - Normal transitions using graphics cannot be used. With the exception of
  117. #     a standard fade, like that used when no graphic is defined will be used.
  118. #     Aside from that, only special transitions from Transition Pack can be
  119. #     used.
  120. #==============================================================================
  121. #  Credits/Thanks:
  122. #  - ForeverZer0, for script.
  123. #  - Creators of the Transition Pack and Screenshot.dll
  124. #  - Selwyn, for base resolution script
  125. #  - KK20, for Version 0.94 and above and the Tilemap class
  126. #  - LiTTleDRAgo, for Core Engine script to remove screenshot.dll dependency
  127. #==============================================================================
  128. #                             CONFIGURATION
  129. #==============================================================================
  130.  
  131.   SCREEN = [1024,576]
  132.   # Define the resolution of the game screen. These values can be anything
  133.   # within reason. Centering, viewports, etc. will all be taken care of, but it
  134.   # is recommended that you use values divisible by 32 for best results.
  135.  
  136.   UPDATE_COUNT = 8
  137.   # Define the number of frames between autotile updates. The lower the number,
  138.   # the faster the animations cycle. This can be changed in-game with the
  139.   # following script call: $game_map.autotile_speed = SPEED
  140.  
  141.   USE_CR_SPRITE = true
  142.   # Replace unused sprite in tilemap with a dummy, still in experimental phase.
  143.  
  144.  
  145. #==============================================================================
  146. # ** Resolution
  147. #------------------------------------------------------------------------------
  148. #  
  149. #==============================================================================
  150.  
  151. class Resolution
  152.   #--------------------------------------------------------------------------
  153.   # * Public Instance Variables
  154.   #--------------------------------------------------------------------------
  155.   attr_reader :version, :width, :height
  156.   #--------------------------------------------------------------------------
  157.   # * Object Initialization
  158.   #--------------------------------------------------------------------------
  159.   def initialize
  160.     # Define version.
  161.     @version = 0.975
  162.     # Set instance variables for calling basic Win32 functions.
  163.     ini = Win32API.new('kernel32', 'GetPrivateProfileString','PPPPLP', 'L')
  164.     ini.call('Game', 'Title', '', (title = "\0" * 256), 256, '.\\Game.ini')
  165.     title.delete!("\0")
  166.     @window   = LiTTleDRAgo.hwnd
  167.     @metrics  = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
  168.     # Set default size, displaying error if size is larger than the hardware.
  169.     default_size = self.size
  170.     if default_size[0] < SCREEN[0] || default_size[1] < SCREEN[1]
  171.       print("\"#{title}\" requires a minimum screen resolution of "+
  172.             "[#{SCREEN[0]} x #{SCREEN[1]}]\r\n\r\n" +
  173.             "\tYour Resolution: [#{default_size[0]} x #{default_size[1]}]")
  174.       exit
  175.     end
  176.     # Apply resolution change.
  177.     enable(true)  
  178.   end
  179.   #--------------------------------------------------------------------------
  180.   # * Returns the screen size of the machine.
  181.   #--------------------------------------------------------------------------
  182.   def size
  183.     return [@metrics.call(0), @metrics.call(1)]
  184.   end
  185.   #--------------------------------------------------------------------------
  186.   # * Enable / Disable the resolution script
  187.   #--------------------------------------------------------------------------
  188.   def enable(value = true)
  189.     value && !@enable && change_resolution(SCREEN[0], SCREEN[1])
  190.     unless $imported[:drg_custom_resolution]
  191.       !value && @enable && change_resolution(640,480)
  192.     end
  193.     @enable = value
  194.   end
  195.   #--------------------------------------------------------------------------
  196.   # * Returns true if resolution is enabled
  197.   #--------------------------------------------------------------------------
  198.   def enabled?
  199.     @enable
  200.   end
  201.   #--------------------------------------------------------------------------
  202.   # * Returns the fullscreen state
  203.   #--------------------------------------------------------------------------
  204.   def fullscreen?
  205.     size.at(0) == Graphics.width
  206.   end
  207.   #--------------------------------------------------------------------------
  208.   # * Change the resolution size
  209.   #--------------------------------------------------------------------------
  210.   unless method_defined?(:change_resolution)
  211.     def change_resolution(w = @width, h = @height)
  212.       @set_window_long ||= Win32API.new('user32', 'SetWindowLong', 'lil','L')
  213.       @set_window_pos  ||= Win32API.new('user32', 'SetWindowPos','lliiiii','I')
  214.       w, h = (w / 32.0).ceil * 32, (h / 32.0).ceil * 32
  215.       x, y = (size[0] - w) / 2, (size[1] - h) / 2
  216.       if Graphics.respond_to?(:resize_screen)
  217.         Graphics.resize_screen(w,h)
  218.       else
  219.         @set_window_pos.call(@window, 0, x, y, w + 6, h + 26, 0)
  220.       end
  221.       @set_window_long.call(@window, -16, 0x14CA0000)
  222.       @width, @height = w, h  if @width != w || @height != h
  223.       Graphics.check_center_player
  224.     end
  225.   end
  226.   #--------------------------------------------------------------------------
  227. end
  228.  
  229. #==============================================================================
  230. # ** Drago - Core Engine
  231. # Version : 1.39
  232. # Contact : littledrago.blogspot.com / forum.chaos-project.com
  233. #==============================================================================
  234.  
  235. module LiTTleDRAgo
  236.   #-------------------------------------------------------------------------
  237.   # * Constant
  238.   #-------------------------------------------------------------------------
  239.   VX           = defined?(Window_ActorCommand)
  240.   VXA          = defined?(Window_BattleActor)
  241.   RGSS1        = defined?(Hangup)
  242.   RGSS2        = RUBY_VERSION == '1.8.1' && !RGSS1
  243.   RGSS3        = RUBY_VERSION == '1.9.2'
  244.   APPPATHDRAGO = "#{ENV['APPDATA']}/Drago/"
  245. end
  246.  
  247. $imported ||= {}
  248. #==============================================================================
  249. # ** CoreDLL
  250. #------------------------------------------------------------------------------
  251. #  
  252. #==============================================================================
  253. module CoreDLL
  254.   #-------------------------------------------------------------------------
  255.   # * Constant
  256.   #-------------------------------------------------------------------------
  257.   Rtlmemory_pi = Win32API.new('kernel32','RtlMoveMemory','pii','i')
  258.   Rtlmemory_ip = Win32API.new('kernel32','RtlMoveMemory','ipi','i')
  259.   #-------------------------------------------------------------------------
  260.   # * Get the game window handle (specific to game)
  261.   #-------------------------------------------------------------------------
  262.   unless method_defined?(:hwnd)
  263.     def hwnd
  264.       @window_find ||= Win32API.new('user32', 'FindWindowEx', %w(l l p p), 'i')
  265.       @game_window ||= @window_find.call(0,0,"RGSS Player",0)
  266.       return @game_window
  267.     end  
  268.   end
  269.   #-------------------------------------------------------------------------
  270.   # * Get the Game Window's width and height
  271.   #-------------------------------------------------------------------------
  272.   unless method_defined?(:client_size)
  273.     def client_size
  274.       @window_c_rect ||= Win32API.new('user32', 'GetClientRect', %w(l p), 'i')
  275.       @window_c_rect.call(self.hwnd, (rect = [0, 0, 0, 0].pack('l4')))
  276.       right, bottom = rect.unpack('l4')[2..3]
  277.       return right, bottom
  278.     end  
  279.   end
  280.   #--------------------------------------------------------------------------
  281.   # * snap_to_bitmap
  282.   #--------------------------------------------------------------------------
  283.   unless method_defined?(:snap_to_bitmap)
  284.     def snap_to_bitmap
  285.       @getdc       ||= Win32API.new('user32','GetDC','i','i')
  286.       @ccdc        ||= Win32API.new('gdi32','CreateCompatibleDC','i','i')
  287.       @ccbitmap    ||= Win32API.new('gdi32','CreateCompatibleBitmap','iii','i')
  288.       @deleteobject||= Win32API.new('gdi32','DeleteObject','i','i')
  289.       @bitblt      ||= Win32API.new('gdi32','BitBlt','iiiiiiiii','i')
  290.       @setdibits   ||= Win32API.new('gdi32','SetDIBits','iiiiipi','i')
  291.       @getdibits   ||= Win32API.new('gdi32','GetDIBits','iiiiipi','i')
  292.       @selectobject||= Win32API.new('gdi32','SelectObject','ii','i')
  293.       bitmap = Bitmap.new((width = Graphics.width), (height = Graphics.height))
  294.       info   = [40,width,height,1,32,0,0,0,0,0,0].pack('LllSSLLllLL')
  295.       hDC    = @ccdc.call((dc = @getdc.call(hwnd)))
  296.       hBM    = @ccbitmap.call(dc, width, height)
  297.       @deleteobject.call(@selectobject.call(hDC, hBM))
  298.       @setdibits.call(hDC, hBM, 0, height, (address = bitmap.address), info, 0)
  299.       @bitblt.call(hDC, 0, 0, width, height, dc, 0, 0, 0xCC0020)
  300.       @getdibits.call(hDC, hBM, 0, height, address, info, 0)
  301.       @deleteobject.call(hBM)
  302.       @deleteobject.call(hDC)
  303.       bitmap
  304.     end    
  305.   end
  306. end                        
  307. LiTTleDRAgo.extend(CoreDLL)
  308.  
  309. #==============================================================================
  310. # ** Graphics
  311. #------------------------------------------------------------------------------
  312. #  This module handles all Graphics
  313. #==============================================================================
  314. class << Graphics
  315.   #--------------------------------------------------------------------------
  316.   # ● Redefined method: width
  317.   #--------------------------------------------------------------------------
  318.   unless method_defined?(:width)
  319.     def width
  320.       LiTTleDRAgo.client_size.at(0)
  321.     end
  322.   end
  323.   #--------------------------------------------------------------------------
  324.   # ● Redefined method: height
  325.   #--------------------------------------------------------------------------
  326.   unless method_defined?(:height)
  327.     def height
  328.       LiTTleDRAgo.client_size.at(1)
  329.     end
  330.   end
  331.   #--------------------------------------------------------------------------
  332.   # ● Redefined method: snap_to_bitmap
  333.   #--------------------------------------------------------------------------
  334.   unless method_defined?(:snap_to_bitmap)
  335.     def snap_to_bitmap
  336.       LiTTleDRAgo.snap_to_bitmap
  337.     end
  338.   end
  339. end
  340. #==============================================================================
  341. # ■ Bitmap
  342. #------------------------------------------------------------------------------
  343. #
  344. #==============================================================================
  345. class Bitmap  
  346.   #----------------------------------------------------------------------------
  347.   # ● Constant
  348.   #----------------------------------------------------------------------------
  349.   RtlMoveMemory_pi = CoreDLL::Rtlmemory_pi
  350.   RtlMoveMemory_ip = CoreDLL::Rtlmemory_ip
  351.   #----------------------------------------------------------------------------
  352.   # ● New method: address
  353.   #----------------------------------------------------------------------------
  354.   unless method_defined?(:address)
  355.     def address
  356.       @address ||= (
  357.         RtlMoveMemory_pi.call(a="\0"*4, __id__*2+16, 4)
  358.         RtlMoveMemory_pi.call(a, a.unpack('L')[0]+8, 4)
  359.         RtlMoveMemory_pi.call(a, a.unpack('L')[0]+16, 4)
  360.         a.unpack('L')[0]
  361.       )
  362.     end
  363.   end
  364. end
  365. #==============================================================================
  366. # **                                               END OF Drago - Core Engine
  367. #==============================================================================
  368.  
  369. #==============================================================================
  370. # ** Graphics
  371. #------------------------------------------------------------------------------
  372. #  This module handles all Graphics
  373. #==============================================================================
  374. class << Graphics
  375.   #---------------------------------------------------------------------------
  376.   # * Method check
  377.   #---------------------------------------------------------------------------
  378.   unless method_defined?(:zer0_graphics_transition)
  379.     #-------------------------------------------------------------------------
  380.     # * Alias Listing
  381.     #-------------------------------------------------------------------------
  382.     alias_method(:zer0_graphics_transition, :transition)    
  383.     #-------------------------------------------------------------------------
  384.     # * Aliased method: transition
  385.     #-------------------------------------------------------------------------
  386.     def transition(duration = 8, *args)
  387.       # Call default transition if no instance of the resolution is defined.
  388.       if $resolution == nil || default_resolution? ||
  389.         !$resolution.enabled? && !$imported[:drg_custom_resolution]
  390.         zer0_graphics_transition(duration, *args)
  391.       else
  392.         # Skip this section and instantly transition graphics if duration is 0.
  393.         if duration > 0
  394.           # Take a snapshot of the the screen, overlaying screen with graphic.
  395.           #$resolution.snapshot
  396.           zer0_graphics_transition(0)
  397.           # Create screen instance
  398.           viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
  399.           sprite = Sprite.new(viewport)
  400.           sprite.bitmap = Graphics.snap_to_bitmap
  401.           # Use a simple fade if transition is not defined.
  402.           fade = 255 / duration
  403.           duration.times { (sprite.opacity -= fade) && update }
  404.           # Dispose sprite and delete snapshot file.
  405.           [sprite, sprite.bitmap, viewport].each {|obj| obj.dispose }
  406.         end
  407.         zer0_graphics_transition(0)
  408.       end
  409.     end
  410.   end
  411.   #--------------------------------------------------------------------------
  412.   # * Alias Listing
  413.   #--------------------------------------------------------------------------
  414.   unless method_defined?(:drg_spriteset_viewport_adjust)
  415.     alias_method :drg_spriteset_viewport_adjust, :update
  416.     #--------------------------------------------------------------------------
  417.     # * Aliased method: update
  418.     #--------------------------------------------------------------------------
  419.     def update(*args)
  420.       check_center_player
  421.       drg_spriteset_viewport_adjust(*args)
  422.     end
  423.     #--------------------------------------------------------------------------
  424.     # * New method: check_center_player
  425.     #--------------------------------------------------------------------------
  426.     def check_center_player
  427.       return unless $resolution
  428.       return unless Game_Player.const_defined?(:CENTER_X)
  429.       $resolution.change_resolution if !$resolution.fullscreen? &&
  430.       viewport_size_change?
  431.       unless Game_Player.const_get(:CENTER_X) == center_x
  432.         Game_Player.const_set(:CENTER_X,  center_x)
  433.         Game_Player.const_set(:CENTER_Y,  center_y)
  434.         $game_player && $game_player.center($game_player.x,$game_player.y)
  435.       end
  436.     end
  437.     #--------------------------------------------------------------------------
  438.     # * X Coordinate of Screen Center
  439.     #--------------------------------------------------------------------------
  440.     def center_x
  441.       zoom_x = $game_map.respond_to?(:zoom_x) ? $game_map.zoom_x : 1
  442.       return ((Graphics.width / 2) / zoom_x - 16).ceil * 4
  443.     end
  444.     #--------------------------------------------------------------------------
  445.     # * Y Coordinate of Screen Center
  446.     #--------------------------------------------------------------------------
  447.     def center_y
  448.       zoom_y = $game_map.respond_to?(:zoom_y) ? $game_map.zoom_y : 1
  449.       return ((Graphics.height / 2) / zoom_y - 16).ceil * 4
  450.     end
  451.     #--------------------------------------------------------------------------
  452.     # * New method: viewport_size_change?
  453.     #--------------------------------------------------------------------------
  454.     def viewport_size_change?
  455.       return false unless $resolution
  456.       return false if $resolution.fullscreen?
  457.       return true if (Graphics.width  - $resolution.width).abs  > 30
  458.       return true if (Graphics.height - $resolution.height).abs > 30
  459.     end
  460.   end
  461.   #--------------------------------------------------------------------------
  462.   # * New method: default_resolution?
  463.   #--------------------------------------------------------------------------
  464.   def default_resolution?
  465.     width <= 640 && height <= 480
  466.   end
  467. end  
  468.  
  469. #==============================================================================
  470. # ** RPG::Cache
  471. #==============================================================================
  472. ModCache = LiTTleDRAgo::VX ? Cache : RPG::Cache
  473. module ModCache
  474.   #-------------------------------------------------------------------------
  475.   # * Self
  476.   #-------------------------------------------------------------------------
  477.   class << self
  478.     #---------------------------------------------------------------------------
  479.     # * Constant
  480.     #---------------------------------------------------------------------------
  481.     AUTO_INDEX = [
  482.       [27,28,33,34],  [5,28,33,34],  [27,6,33,34],  [5,6,33,34],
  483.       [27,28,33,12],  [5,28,33,12],  [27,6,33,12],  [5,6,33,12],
  484.       [27,28,11,34],  [5,28,11,34],  [27,6,11,34],  [5,6,11,34],
  485.       [27,28,11,12],  [5,28,11,12],  [27,6,11,12],  [5,6,11,12],
  486.       [25,26,31,32],  [25,6,31,32],  [25,26,31,12], [25,6,31,12],
  487.       [15,16,21,22],  [15,16,21,12], [15,16,11,22], [15,16,11,12],
  488.       [29,30,35,36],  [29,30,11,36], [5,30,35,36],  [5,30,11,36],
  489.       [39,40,45,46],  [5,40,45,46],  [39,6,45,46],  [5,6,45,46],
  490.       [25,30,31,36],  [15,16,45,46], [13,14,19,20], [13,14,19,12],
  491.       [17,18,23,24],  [17,18,11,24], [41,42,47,48], [5,42,47,48],
  492.       [37,38,43,44],  [37,6,43,44],  [13,18,19,24], [13,14,43,44],
  493.       [37,42,43,48],  [17,18,47,48], [13,18,43,48], [1,2,7,8]
  494.     ].freeze
  495.     #---------------------------------------------------------------------------
  496.     # * Alias Listing
  497.     #---------------------------------------------------------------------------
  498.     if method_defined?(:autotile)
  499.       $@ || alias_method(:autotile_cr_tilemap, :autotile)
  500.     end
  501.     #---------------------------------------------------------------------------
  502.     # * Aliased method: autotile
  503.     #---------------------------------------------------------------------------
  504.     def autotile(filename)
  505.       if respond_to?(:autotile_cr_tilemap)
  506.         return autotile_cr_tilemap(filename) unless $resolution.enabled?
  507.       end
  508.       key = "Graphics/Autotiles/#{filename}"
  509.       if !@cache.include?(key) || @cache[key].disposed?
  510.         # Cache the autotile graphic.
  511.         @cache[key] = (filename == '') ? Bitmap.new(128, 96) : Bitmap.new(key)
  512.         # Cache each configuration of this autotile.
  513.         new_bm = self.format_autotiles(@cache[key], filename)
  514.         @cache[key].dispose
  515.         @cache[key] = new_bm
  516.       end
  517.       return @cache[key]
  518.     end
  519.     #--------------------------------------------------------------------------
  520.     # * New method: include?
  521.     #--------------------------------------------------------------------------
  522.     unless method_defined?(:include?)
  523.       def include?(key)
  524.         @cache[key] && !@cache[key].disposed?
  525.       end
  526.     end
  527.     #---------------------------------------------------------------------------
  528.     # * New method: format_autotiles
  529.     #---------------------------------------------------------------------------
  530.     def format_autotiles(bitmap, filename)
  531.       if bitmap.height > 32
  532.         frames = bitmap.width / 96
  533.         template = Bitmap.new(256*frames,192)
  534.         # Create a bitmap to use as a template for creation.
  535.         (0..frames-1).each{|frame|
  536.         (0...6).each {|i| (0...8).each {|j| AUTO_INDEX[8*i+j].each {|number|
  537.           number -= 1
  538.           x, y = 16 * (number % 6), 16 * (number / 6)
  539.           rect = Rect.new(x + (frame * 96), y, 16, 16)
  540.           template.blt((32 * j + x % 32) +
  541.           (frame * 256), 32 * i + y % 32, bitmap, rect)
  542.         }}}}
  543.         return template
  544.       else
  545.         return bitmap
  546.       end
  547.     end
  548.   end
  549. end
  550.  
  551. #==============================================================================
  552. # ** Tilemap_DataTable
  553. #------------------------------------------------------------------------------
  554. #  
  555. #==============================================================================
  556. class Tilemap_DataTable
  557.   #---------------------------------------------------------------------------
  558.   # * Public Instance Variables
  559.   #---------------------------------------------------------------------------
  560.   attr_accessor :table
  561.   #---------------------------------------------------------------------------
  562.   # * Get tilemap table
  563.   #---------------------------------------------------------------------------
  564.   define_method(:initialize)  {|table| @table = table }
  565.   define_method(:"[]")        {|*args| @table[*args]  }
  566.   define_method(:"[]=")       {|*args| @table[*args[0..-2]] = args.last }
  567.   def method_missing(sym, *a, &blk)  table.send(sym, *a, &blk) end
  568. end
  569.  
  570. #==============================================================================
  571. # ** Game_Map
  572. #------------------------------------------------------------------------------
  573. #  This class handles the map. It includes scrolling and passable determining
  574. #  functions. Refer to "$game_map" for the instance of this class.
  575. #==============================================================================
  576.  
  577. class Game_Map
  578.   #--------------------------------------------------------------------------
  579.   # * Public Instance Variables
  580.   #--------------------------------------------------------------------------
  581.   attr_writer :autotile_speed
  582.   #--------------------------------------------------------------------------
  583.   # * Alias Listing
  584.   #--------------------------------------------------------------------------
  585.   $@ || alias_method(:drg_scroll_up_adjust,    :scroll_up)
  586.   $@ || alias_method(:drg_scroll_left_adjust,  :scroll_left)
  587.   $@ || alias_method(:drg_scroll_down_adjust,  :scroll_down)
  588.   $@ || alias_method(:drg_scroll_right_adjust, :scroll_right)
  589.   #--------------------------------------------------------------------------
  590.   # * Scroll Down
  591.   #--------------------------------------------------------------------------
  592.   def scroll_down(distance)
  593.     times = vxa_map_multiplier
  594.     if loop_vertical?
  595.       @display_y += distance
  596.       @display_y %= height * times
  597.       @parallax_y += distance if @parallax_y && @parallax_loop_y
  598.     else
  599.       last_y = @display_y
  600.       result = [@display_y + distance, map_edge.at(1) / zoom_y].min
  601.       drg_scroll_down_adjust(distance)
  602.       @display_y = result
  603.       @parallax_y += @display_y - last_y if @parallax_y
  604.     end
  605.   end
  606.   #--------------------------------------------------------------------------
  607.   # * Scroll Right
  608.   #--------------------------------------------------------------------------
  609.   def scroll_right(distance)
  610.     times = vxa_map_multiplier
  611.     if loop_horizontal?
  612.       @display_x += distance
  613.       @display_x %= width * times
  614.       @parallax_x += distance if @parallax_x && @parallax_loop_x
  615.     else
  616.       last_x = @display_x
  617.       result = [@display_x + distance, map_edge.at(0) / zoom_x].min
  618.       drg_scroll_right_adjust(distance)
  619.       @display_x = result
  620.       @parallax_x += @display_x - last_x if @parallax_x
  621.     end
  622.   end
  623.   #--------------------------------------------------------------------------
  624.   # * New method: map_edge
  625.   #--------------------------------------------------------------------------
  626.   def map_edge
  627.     times = vxa_map_multiplier
  628.     [_w = [(width  * zoom_x - screen_tile_x).ceil * times, 0].max,
  629.      _h = [(height * zoom_y - screen_tile_y).ceil * times, 0].max]
  630.   end
  631.   #--------------------------------------------------------------------------
  632.   # * New method: vxa_map_multiplier
  633.   #--------------------------------------------------------------------------
  634.   def vxa_map_multiplier
  635.     LiTTleDRAgo::VXA ? 1 : 128
  636.   end
  637.   #--------------------------------------------------------------------------
  638.   # * New method: change_tile
  639.   #--------------------------------------------------------------------------
  640.   def change_tile(x, y, z, tile_id = 0)
  641.     data[x,y,z] = tile_id    
  642.     spriteset.tilemap.map_data = data if spriteset.is_a?(Spriteset_Map)
  643.   end
  644.   #--------------------------------------------------------------------------
  645.   # * New method: spriteset
  646.   #--------------------------------------------------------------------------
  647.   unless method_defined?(:spriteset)
  648.     define_method(:spriteset) { $scene.instance_variable_get(:@spriteset) }
  649.   end
  650.   #--------------------------------------------------------------------------
  651.   # * New method: screen_tile_x
  652.   #--------------------------------------------------------------------------
  653.   unless method_defined?(:screen_tile_x)
  654.     define_method(:screen_tile_x) {(Graphics.width  / 32.0).ceil}
  655.   end
  656.   #--------------------------------------------------------------------------
  657.   # * New method: screen_tile_y
  658.   #--------------------------------------------------------------------------
  659.   unless method_defined?(:screen_tile_y)
  660.     define_method(:screen_tile_y) {(Graphics.height / 32.0).ceil}
  661.   end
  662.   #--------------------------------------------------------------------------
  663.   # * New method: autotile_speed, zoom_x, zoom_y
  664.   #--------------------------------------------------------------------------
  665.   define_method(:autotile_speed) { [@autotile_speed ||= UPDATE_COUNT, 1].max }
  666.   define_method(:zoom_x) { resolution_enabled? ? (@zoom_x ||= 1) : 1 }
  667.   define_method(:zoom_y) { resolution_enabled? ? (@zoom_y ||= 1) : 1 }
  668.   define_method(:resolution_enabled?) { $resolution && $resolution.enabled? }
  669.   method_defined?(:loop_horizontal?) || define_method(:loop_horizontal?) {}
  670.   method_defined?(:loop_vertical?)   || define_method(:loop_vertical?)   {}
  671. end
  672.  
  673. #==============================================================================
  674. # ** Game_Player
  675. #------------------------------------------------------------------------------
  676. #  This class handles the player. Its functions include event starting
  677. #  determinants and map scrolling. Refer to "$game_player" for the one
  678. #  instance of this class.
  679. #==============================================================================
  680.  
  681. class Game_Player
  682.   #--------------------------------------------------------------------------
  683.   # * Alias Listing
  684.   #--------------------------------------------------------------------------
  685.   $@ || alias_method(:drg_adjust_viewport_center, :center)
  686.   #--------------------------------------------------------------------------
  687.   # * Aliased method: center
  688.   #--------------------------------------------------------------------------
  689.   def center(x, y)
  690.     drg_adjust_viewport_center(x, y)
  691.     # Recalculate the screen center based on the new resolution.  
  692.     max_x = $game_map.map_edge.at(0) / $game_map.zoom_x
  693.     max_y = $game_map.map_edge.at(1) / $game_map.zoom_y
  694.     $game_map.display_x = [0, [(x * 32*4) - center_x, max_x.ceil].min].max
  695.     $game_map.display_y = [0, [(y * 32*4) - center_y, max_y.ceil].min].max
  696.     if $game_map.spriteset.is_a?(Spriteset_Map) &&
  697.       $game_map.spriteset.tilemap.is_a?(CRTilemap)
  698.       $game_map.spriteset.tilemap.refresh
  699.     end
  700.   end  
  701.   #--------------------------------------------------------------------------
  702.   # * X Coordinate of Screen Center
  703.   #--------------------------------------------------------------------------
  704.   def center_x
  705.     Graphics.center_x
  706.   end
  707.   #--------------------------------------------------------------------------
  708.   # * Y Coordinate of Screen Center
  709.   #--------------------------------------------------------------------------
  710.   def center_y
  711.     Graphics.center_y
  712.   end
  713. end
  714.  
  715. #==============================================================================
  716. # ** Viewport
  717. #------------------------------------------------------------------------------
  718. #  
  719. #==============================================================================
  720. class Viewport
  721.   #--------------------------------------------------------------------------
  722.   # * Alias Listing
  723.   #--------------------------------------------------------------------------
  724.   $@ || alias_method(:zer0_viewport_resize_init, :initialize)
  725.   #--------------------------------------------------------------------------
  726.   # * Aliased method: initialize
  727.   #--------------------------------------------------------------------------
  728.   def initialize(*args)
  729.     default = Rect.new(0, 0, Graphics.width, Graphics.height)
  730.     if args.size == 0 || args == [0, 0, 640, 480]
  731.       # If argument is nil, use default resolution.
  732.       zer0_viewport_resize_init(default)
  733.     else
  734.       # Call method normally.
  735.       zer0_viewport_resize_init(*args)
  736.     end
  737.   end
  738.   #--------------------------------------------------------------------------
  739.   # * New method: resize
  740.   #--------------------------------------------------------------------------
  741.   unless method_defined?(:resize)
  742.     def resize(*args)
  743.       # Resize the viewport. Can call with (X, Y, WIDTH, HEIGHT) or (RECT).
  744.       self.rect = args[0].is_a?(Rect) ? args[0] : Rect.new(*args)
  745.     end
  746.   end
  747.   #--------------------------------------------------------------------------
  748.   # * New method: update_viewport_sizes
  749.   #--------------------------------------------------------------------------
  750.   def update_viewport_sizes
  751.     map = $game_map
  752.     w, h = Graphics.width, Graphics.height
  753.     hor = $game_map.loop_horizontal?
  754.     ver = $game_map.loop_vertical?
  755.     _w = $game_map.width * 32 * $game_map.zoom_x
  756.     _h = $game_map.height * 32 * $game_map.zoom_y
  757.     _w, _h = 640, 480 unless $game_map.resolution_enabled?
  758.     dx = w > _w && !hor ? (w - _w) / 2 : 0
  759.     dw = hor ? w : [w, $game_map.width  * 32 * $game_map.zoom_x].min  
  760.     dy = h > _h && !ver ? (h - _h) / 2 : 0
  761.     dh = ver ? h : [h, $game_map.height * 32 * $game_map.zoom_y].min
  762.     resize(Rect.new(dx, dy, dw, dh))
  763.   end
  764. end
  765.  
  766. #==============================================================================
  767. # ** Spriteset_Map
  768. #------------------------------------------------------------------------------
  769. #  This class brings together map screen sprites, tilemaps, etc.
  770. #  It's used within the Scene_Map class.
  771. #==============================================================================
  772. class Spriteset_Map
  773.   #--------------------------------------------------------------------------
  774.   # * Public Instance Variable
  775.   #--------------------------------------------------------------------------
  776.   attr_reader :tilemap
  777.   #--------------------------------------------------------------------------
  778.   # * Alias Listing
  779.   #--------------------------------------------------------------------------
  780.   # Checked whether :drg_spriteset_viewport_adjust is already exist
  781.   # Drago - Core Engine already has this method
  782.   unless method_defined?(:drg_spriteset_viewport_adjust)
  783.     # Method Aliasing
  784.     alias_method :drg_spriteset_viewport_adjust, :update
  785.   end
  786.   #--------------------------------------------------------------------------
  787.   # * Aliased method: update
  788.   #--------------------------------------------------------------------------
  789.   def update(*args)
  790.     # If resolution is changing
  791.     if viewport_size_change?
  792.       @viewport_map_width     = $game_map.width * $game_map.zoom_x
  793.       @viewport_map_height    = $game_map.height * $game_map.zoom_y
  794.       @viewport_screen_width  = Graphics.width
  795.       @viewport_screen_height = Graphics.height
  796.       # Change all viewport resolution
  797.       [@viewport1,@viewport2,@viewport3].each { |v| v.update_viewport_sizes }
  798.     end
  799.     weather_fix_custom_resolution
  800.     update_tilemap_zoom
  801.     drg_spriteset_viewport_adjust(*args)
  802.   end
  803.   #--------------------------------------------------------------------------
  804.   # * New method: viewport_size_change?
  805.   #--------------------------------------------------------------------------
  806.   def viewport_size_change?
  807.     return true if @viewport_map_width   != $game_map.width  * $game_map.zoom_x
  808.     return true if @viewport_map_height  != $game_map.height * $game_map.zoom_y
  809.     return true if @viewport_screen_width  != Graphics.width
  810.     return true if @viewport_screen_height != Graphics.height
  811.   end
  812.   #--------------------------------------------------------------------------
  813.   # * New method: reload_tilemap
  814.   #--------------------------------------------------------------------------
  815.   def reload_tilemap
  816.     @tilemap.respond_to?(:dispose) && @tilemap.dispose
  817.     for i in 0..6
  818.       @tilemap.autotiles[i].respond_to?(:dispose) &&
  819.       @tilemap.autotiles[i].dispose
  820.     end
  821.     res = resolution_enabled?
  822.     @tilemap = res ? CRTilemap.new(@viewport1) : Tilemap.new(@viewport1)
  823.     @tilemap.tileset = ModCache.tileset($game_map.tileset_name)
  824.     for i in 0..6
  825.       autotile_name = $game_map.autotile_names[i]
  826.       @tilemap.autotiles[i] = ModCache.autotile(autotile_name)
  827.     end
  828.     @tilemap.map_data = $game_map.data
  829.     @tilemap.priorities = $game_map.priorities
  830.     @tilemap.update
  831.     @viewport_screen_width = 0
  832.   end    
  833.   #--------------------------------------------------------------------------
  834.   # * New method: reload_plane
  835.   #--------------------------------------------------------------------------
  836.   def reload_plane
  837.     z1  = @panorama.respond_to?(:z) ? @panorama.z : -1000
  838.     z2  = @fog.respond_to?(:z)      ? @fog.z      :  5000
  839.     z1 /= 1000 if @panorama.is_a?(CRPlane)
  840.     z2 /= 1000 if @fog.is_a?(CRPlane)
  841.     res = resolution_enabled? && !Graphics.default_resolution?
  842.     bitmap1 = @panorama.respond_to?(:bitmap) ? @panorama.bitmap : nil
  843.     bitmap2 = @fog.respond_to?(:bitmap) ? @fog.bitmap : nil
  844.     @panorama.respond_to?(:dispose) && @panorama.dispose
  845.     @fog.respond_to?(:dispose) && @fog.dispose      
  846.     p = @panorama = res ? CRPlane.new(@viewport1) : Plane.new(@viewport1)
  847.     f = @fog      = res ? CRPlane.new(@viewport1) : Plane.new(@viewport1)
  848.     p.bitmap = bitmap1 if bitmap1.is_a?(Bitmap)
  849.     f.bitmap = bitmap2 if bitmap2.is_a?(Bitmap)
  850.     p.z, f.z = z1, z2
  851.     @viewport_screen_width = 0
  852.   end
  853.   #--------------------------------------------------------------------------
  854.   # * New method: update_tilemap_zoom
  855.   #--------------------------------------------------------------------------
  856.   def update_tilemap_zoom
  857.     return unless @tilemap.respond_to?(:zoom_x=)
  858.     @tilemap.zoom_x = $game_map.zoom_x
  859.     @tilemap.zoom_y = $game_map.zoom_y
  860.     @weather.zoom_x = $game_map.zoom_x
  861.     @weather.zoom_y = $game_map.zoom_y
  862.   end
  863.   #--------------------------------------------------------------------------
  864.   # * New method: weather_fix_custom_resolution
  865.   #--------------------------------------------------------------------------
  866.   def weather_fix_custom_resolution
  867.     if resolution_enabled?
  868.       reload_tilemap if @tilemap.is_a?(Tilemap)
  869.     else
  870.       reload_tilemap if @tilemap.is_a?(CRTilemap)
  871.     end
  872.     if resolution_enabled? && !Graphics.default_resolution?
  873.       reload_plane   if @panorama.is_a?(Plane)   || @fog.is_a?(Plane)
  874.     else
  875.       reload_plane   if @panorama.is_a?(CRPlane) || @fog.is_a?(CRPlane)
  876.     end
  877.   end
  878.   #--------------------------------------------------------------------------
  879.   # * New method: resolution_enabled?
  880.   #--------------------------------------------------------------------------
  881.   def resolution_enabled?
  882.     $game_map.resolution_enabled?
  883.   end
  884. end
  885.  
  886. #==============================================================================
  887. # ** RPG::Weather
  888. #------------------------------------------------------------------------------
  889. #  A class for weather effects (rain, storm, and snow). It is used within the
  890. # Spriteset_Map class.
  891. #==============================================================================
  892. CRWeather = LiTTleDRAgo::VX ? Spriteset_Weather : RPG::Weather
  893. class CRWeather
  894.   #--------------------------------------------------------------------------
  895.   # * Public Instance Variable
  896.   #--------------------------------------------------------------------------
  897.   attr_reader :viewport
  898.   attr_accessor :zoom_x, :zoom_y
  899.   #--------------------------------------------------------------------------
  900.   # * Alias Listing
  901.   #--------------------------------------------------------------------------
  902.   $@ || alias_method(:init_custom_resolution, :initialize)
  903.   #--------------------------------------------------------------------------
  904.   # * Aliased method: initialize
  905.   #--------------------------------------------------------------------------
  906.   def initialize(viewport)
  907.     @viewport = viewport
  908.     init_custom_resolution(@viewport)
  909.   end
  910.   #--------------------------------------------------------------------------
  911.   # * Overwriten method: update
  912.   #--------------------------------------------------------------------------
  913.   def update
  914.     return if @type == 0
  915.     update_screen if respond_to?(:update_screen)
  916.     @sprites.each {|sprite| update_sprite(sprite) }
  917.   end
  918.   #--------------------------------------------------------------------------
  919.   # * Update Sprite
  920.   #--------------------------------------------------------------------------
  921.   def update_sprite(sprite)
  922.     sprite.ox = @ox
  923.     sprite.oy = @oy
  924.     case @type
  925.     when 1, :rain  then update_sprite_rain(sprite)
  926.     when 2, :storm then update_sprite_storm(sprite)
  927.     when 3, :snow  then update_sprite_snow(sprite)
  928.     end
  929.     create_new_particle(sprite) if sprite.opacity < 64
  930.   end
  931.   #--------------------------------------------------------------------------
  932.   # * Update Sprite [Rain]
  933.   #--------------------------------------------------------------------------
  934.   def update_sprite_rain(sprite)
  935.     sprite.bitmap = @rain_bitmap
  936.     sprite.x -= 2 * sprite.zoom_x
  937.     sprite.y += 16 * sprite.zoom_y
  938.     sprite.opacity -= 8
  939.   end
  940.   #--------------------------------------------------------------------------
  941.   # * Update Sprite [Storm]
  942.   #--------------------------------------------------------------------------
  943.   def update_sprite_storm(sprite)
  944.     sprite.bitmap = @storm_bitmap
  945.     sprite.x -= 8 * sprite.zoom_x
  946.     sprite.y += 16 * sprite.zoom_y
  947.     sprite.opacity -= 12
  948.   end
  949.   #--------------------------------------------------------------------------
  950.   # * Update Sprite [Snow]
  951.   #--------------------------------------------------------------------------
  952.   def update_sprite_snow(sprite)
  953.     sprite.bitmap = @snow_bitmap
  954.     sprite.x -= 2 * sprite.zoom_x
  955.     sprite.y += 8 * sprite.zoom_y
  956.     sprite.opacity -= 8
  957.   end
  958.   #--------------------------------------------------------------------------
  959.   # * Create New Particle
  960.   #--------------------------------------------------------------------------
  961.   def create_new_particle(sprite)
  962.     sprite.x = rand(Graphics.width + 100) - 100 + @ox
  963.     sprite.y = rand(Graphics.height + 200) - 200 + @oy
  964.     sprite.zoom_x = @zoom_x || 1
  965.     sprite.zoom_y = @zoom_y || 1
  966.     sprite.x *= sprite.zoom_x
  967.     sprite.y *= sprite.zoom_y
  968.     sprite.opacity = 160 + rand(96)
  969.   end
  970.   #---------------------------------------------------------------------------
  971.   # * New method: method_missing
  972.   #---------------------------------------------------------------------------
  973.   def method_missing(val,*a,&b)
  974.     en = @sprites.flatten.find_all {|s|s.respond_to?(val.to_sym)}
  975.     if en.empty?
  976.       text = "Undefined method #{val} at #{self.inspect}"
  977.       raise(NoMethodError,text,caller(1))
  978.     end
  979.     return en.map {|s| s.send(val.to_sym,*a,&b)}
  980.   end  
  981. end
  982.  
  983. #==============================================================================
  984. # ** Plane
  985. #------------------------------------------------------------------------------
  986. #  This class is the rewrite of the default plane class
  987. #==============================================================================
  988.  
  989. class CRPlane < Sprite
  990.   #---------------------------------------------------------------------------
  991.   # * Public Instance Variable
  992.   #---------------------------------------------------------------------------
  993.   attr_reader :bitmap
  994.   #---------------------------------------------------------------------------
  995.   # * New method: z=
  996.   #---------------------------------------------------------------------------
  997.   def z=(z)
  998.     # Change the Z value of the viewport, not the sprite.
  999.     super(z * 1000)
  1000.   end
  1001.   #---------------------------------------------------------------------------
  1002.   # * New method: ox=
  1003.   #---------------------------------------------------------------------------
  1004.   def ox=(ox)
  1005.     # Have viewport stay in loop on X-axis.
  1006.     super(ox % bitmap.width)  if bitmap.is_a?(Bitmap)
  1007.   end
  1008.   #---------------------------------------------------------------------------
  1009.   # * New method: oy=
  1010.   #---------------------------------------------------------------------------
  1011.   def oy=(oy)
  1012.     # Have viewport stay in loop on Y-axis.
  1013.     super(oy % bitmap.height) if bitmap.is_a?(Bitmap)
  1014.   end
  1015.   #---------------------------------------------------------------------------
  1016.   # * New method: bitmap=
  1017.   #---------------------------------------------------------------------------
  1018.   def bitmap=(tile)
  1019.     return if @bitmap == tile
  1020.     @bitmap = tile
  1021.     if bitmap.is_a?(Bitmap)
  1022.       # Calculate the number of tiles to span screen in both directions.
  1023.       xx = 1 + (Graphics.width.to_f  / tile.width).ceil
  1024.       yy = 1 + (Graphics.height.to_f / tile.height).ceil
  1025.       # Create appropriately sized bitmap, then tile with source image.
  1026.       plane = Bitmap.new(@bitmap.width * xx, @bitmap.height * yy)
  1027.       (0..xx).each {|x| (0..yy).each {|y|
  1028.         plane.blt(x * @bitmap.width, y * @bitmap.height, @bitmap, @bitmap.rect)
  1029.       }}
  1030.       # Set the bitmap to the sprite through its super class (Sprite).
  1031.       super(plane)
  1032.     end
  1033.   end
  1034.   #---------------------------------------------------------------------------
  1035.   # * Undefine methods dealing with coordinates to do nothing.
  1036.   #---------------------------------------------------------------------------
  1037.   undef :x, :x=, :y, :y=   if method_defined?(:x)
  1038. end
  1039.  
  1040. #==============================================================================
  1041. # ** Tilemap
  1042. #------------------------------------------------------------------------------
  1043. #  
  1044. #==============================================================================
  1045. class Tilemap
  1046.   #---------------------------------------------------------------------------
  1047.   # * Public Instance Variables
  1048.   #---------------------------------------------------------------------------
  1049.   method_defined?(:tileset)   || attr_accessor(:tileset)
  1050.   method_defined?(:priorities)|| attr_accessor(:priorities)
  1051.   method_defined?(:autotiles) || define_method(:autotiles){ @autotiles ||= [] }
  1052. end
  1053.  
  1054.  
  1055. #==============================================================================
  1056. # ** CRTilemap
  1057. #------------------------------------------------------------------------------
  1058. #  This class is the rewrite of the default tilemap class
  1059. #==============================================================================
  1060.  
  1061. class CRTilemap
  1062.   #---------------------------------------------------------------------------
  1063.   # * Constant
  1064.   #---------------------------------------------------------------------------
  1065.   CRSprite = Struct.new(:x,:y,:z,:tsprite_id,:tone,:bitmap,:update,:dispose)
  1066.   #---------------------------------------------------------------------------
  1067.   # * Public Instance Variables
  1068.   #---------------------------------------------------------------------------
  1069.   attr_reader   :map_data, :ox, :oy, :viewport, :tile_sprites, :zoom_x, :zoom_y
  1070.   attr_accessor :tileset, :autotiles, :priorities, :tone
  1071.   #---------------------------------------------------------------------------
  1072.   # * Tilemap width and height
  1073.   #---------------------------------------------------------------------------
  1074.   define_method(:width)  { $game_map.screen_tile_x + 2 }
  1075.   define_method(:height) { $game_map.screen_tile_y + 2 }
  1076.   #---------------------------------------------------------------------------
  1077.   # Object Initialization
  1078.   #---------------------------------------------------------------------------
  1079.   def initialize(viewport)
  1080.     # Initialize instance variables to store required data.
  1081.     @viewport, @autotiles, @tile_sprites = viewport, [], []
  1082.     @current_frame, @total_frames = [], []
  1083.     # Get priority data for this tileset from instance of Game_Map.
  1084.     @priorities = $game_map.priorities
  1085.     # Holds all the Sprite instances of animating tiles
  1086.     # (keys based on tile's ID)
  1087.     @animating_tiles = {}
  1088.     # Game map's x/y location of the top left corner tile
  1089.     @zoom_x = @zoom_y = @ox = @oy = 1
  1090.   end
  1091.   #---------------------------------------------------------------------------
  1092.   # Makes update to ox and oy. Sprites out of range will be moved based on
  1093.   # these two values.
  1094.   #---------------------------------------------------------------------------
  1095.   def ox=(ox)
  1096.     return if @ox == ox && !@ox_refresh
  1097.     @ox_refresh = false
  1098.     shift   = (@ox - ox) * @zoom_x
  1099.     width   = self.width
  1100.     height  = self.height
  1101.     count   = (@ox = ox) * 0
  1102.     sign    = (shift < 0 ? 1 : -1)
  1103.     c_index = @corner_index
  1104.     @tile_sprites.flatten.each {|tile| tile.x += shift }
  1105.     while (sprite = @tile_sprites.at(c_index)) &&
  1106.       !(@range_x === sprite.first.x/@zoom_x) && count < 100
  1107.       count += 1
  1108.       unless sign == 1
  1109.         row_index = c_index / width
  1110.         row_index *= width
  1111.         c_index = (@corner_index - 1) % width + row_index
  1112.       end
  1113.       (0...height).each do |n|
  1114.         j = (width * n + c_index) % @modtile
  1115.         next unless @tile_sprites.at(j)
  1116.         (0...@tile_sprites.at(j).size).each do |i|
  1117.           tile = @tile_sprites.at(j).at(i)
  1118.           tile.x += @incr_x * sign
  1119.           tile_update(tile,i)
  1120.         end
  1121.       end
  1122.       c_index /= width
  1123.       c_index *= width
  1124.       @corner_index = (@corner_index + sign) % width + c_index
  1125.       c_index = @corner_index
  1126.     end #end of while
  1127.   end
  1128.   #---------------------------------------------------------------------------
  1129.   # Makes update to ox and oy. Sprites out of range will be moved based on
  1130.   # these two values.
  1131.   #---------------------------------------------------------------------------
  1132.   def oy=(oy)
  1133.     return if @oy == oy && !@oy_refresh
  1134.     @oy_refresh = false
  1135.     shift   = (@oy - oy) * @zoom_y
  1136.     width   = self.width
  1137.     height  = self.height
  1138.     count   = (@oy = oy) * 0
  1139.     sign    = (shift < 0 ? 1 : -1)
  1140.     r_index = @corner_index
  1141.     @tile_sprites.flatten.each do |tile|
  1142.       tile.y += shift
  1143.       priority = tile.instance_variable_get(:@priorities)
  1144.       next unless priority.is_a?(Integer) && priority > 0
  1145.       tile.z = 32 + (tile.y.to_i / 32) * 32 + priority * 32 * @zoom_y
  1146.     end
  1147.     while (sprite = @tile_sprites.at(r_index)) &&  
  1148.       !(@range_y === sprite.first.y/@zoom_y) && count < 100
  1149.       count += 1
  1150.       r_index = (@corner_index - width) % @modtile unless sign == 1
  1151.       r_index /= width
  1152.       r_index *= width
  1153.       (0...width).each do |n|
  1154.         j = n + r_index
  1155.         next unless @tile_sprites.at(j)
  1156.         (0...@tile_sprites.at(j).size).each do |i|
  1157.           tile = @tile_sprites.at(j).at(i)
  1158.           tile.y += @incr_y * sign
  1159.           tile_update(tile,i)
  1160.         end
  1161.       end
  1162.       @corner_index = (@corner_index + width * sign) % @modtile
  1163.       r_index = @corner_index
  1164.     end # end of while
  1165.   end
  1166.   #---------------------------------------------------------------------------
  1167.   # * tile_update
  1168.   #---------------------------------------------------------------------------
  1169.   def tile_update(tile,i)
  1170.     if tile.is_a?(Sprite)
  1171.       tsprite_id = tile.instance_variable_get(:@tsprite_id)
  1172.     else
  1173.       tsprite_id = tile.tsprite_id
  1174.     end
  1175.     @animating_tiles.delete(tsprite_id)
  1176.     # Determine what map coordinate this tile now resides at...
  1177.     # Assign tile's respective ID value
  1178.     map_x = (tile.x / @zoom_x + @ox).round / 32
  1179.     map_y = (tile.y / @zoom_y + @oy).round / 32
  1180.     # ...and get its tile_id
  1181.     tile_id = @map_data[map_x,map_y,i]
  1182.     # If no tile exists here (effectively out of array bounds)
  1183.     if tile_id.nil? || (priority = tile.
  1184.       instance_variable_set(:@priorities, @priorities[tile_id]) || 0) == 0
  1185.       tile.z = 0
  1186.     else
  1187.       tile.z = 32  + (tile.y.to_i / 32) * 32 + priority * 32 * @zoom_y
  1188.     end
  1189.     # If empty tile    
  1190.     if tile_id.nil? || tile_id == 0
  1191.       tile.bitmap = nil
  1192.       if USE_CR_SPRITE && tile.is_a?(Sprite)
  1193.         temp = [tile.x, tile.y, tile.z, tsprite_id]
  1194.         (i = tsprite_id) && tile.dispose
  1195.         @tile_sprites[i/3][i%3] = CRSprite.new(*temp)
  1196.       end
  1197.     else
  1198.       if tile.is_a?(CRSprite)
  1199.         temp = [tile.x, tile.y, tile.z, tile.tsprite_id]
  1200.         tsprite_id = i = temp.at(3)
  1201.         tile = (@tile_sprites[i/3][i%3] = Sprite.new(@viewport))
  1202.         tile.x, tile.y, tile.z = temp[0..2]
  1203.         tile.zoom_x, tile.zoom_y = @zoom_x, @zoom_y
  1204.         tile.instance_variable_set(:@priorities, priority)
  1205.         tile.instance_variable_set(:@tsprite_id,i)
  1206.       end
  1207.       tile.tone = @tone if @tone.is_a?(Tone)
  1208.       if tile_id >= 384
  1209.         tile.bitmap = @tileset unless tile.bitmap == @tileset
  1210.         tile_div = (tile_id - 384)
  1211.         tile.src_rect.set((tile_div % 8) * 32,(tile_div / 8) * 32, 32, 32)
  1212.       else # Autotile
  1213.         auto_id = tile_id / 48 - 1
  1214.         autotile = @autotiles.at(auto_id)
  1215.         tile.bitmap = autotile unless tile.bitmap == autotile
  1216.         tile_div = (tile_id % 48)
  1217.         tile.src_rect.set((tile_div % 8)*32 +
  1218.         @current_frame.at(auto_id) * 256,(tile_div / 8) * 32, 32, 32)
  1219.         @animating_tiles[tsprite_id] = tile if @total_frames.at(auto_id) > 1
  1220.       end
  1221.     end
  1222.   end
  1223.   #---------------------------------------------------------------------------
  1224.   # * Refresh the tilemap
  1225.   #---------------------------------------------------------------------------
  1226.   def refresh
  1227.     sprite = Sprite.new
  1228.     sprite.bitmap = Graphics.snap_to_bitmap
  1229.     1.times { Graphics.update }
  1230.     # Determine how many frames of animation this autotile has
  1231.     for i in 0..6
  1232.       bm = @autotiles[i]
  1233.       bm.nil? && @total_frames[i] = 1
  1234.       bm.nil? || @total_frames[i] = bm.width / (bm.height > 32 ? 256 : 32)
  1235.       @current_frame[i] = @ox_refresh = @oy_refresh =  0
  1236.     end
  1237.     _width  = (width - 2) * 32 + 64
  1238.     _height = (height - 2) * 32 + 64
  1239.     _ox,_oy = @ox, @oy
  1240.     @modtile = _width * _height / 1024
  1241.     @range_x = (-49*@zoom_x)..(-17*@zoom_x)
  1242.     @range_y = (-49*@zoom_y)..(-17*@zoom_y)
  1243.     @incr_x  = _width * @zoom_x
  1244.     @incr_y  = _height * @zoom_y
  1245.     @animating_tiles.clear
  1246.     # Create a sprite and viewport to use for each priority level.
  1247.     (0...(width * height)*3).each do |i|
  1248.       @tile_sprites[i/3] ||= []
  1249.       @tile_sprites[i/3][i%3] ||= CRSprite.new if USE_CR_SPRITE
  1250.       unless sprite_exist?(@tile_sprites[i/3][i%3])
  1251.         @tile_sprites[i/3][i%3] = Sprite.new(@viewport)
  1252.       end
  1253.       # Rename to something shorter and easier to work with for below
  1254.       tile = @tile_sprites[i/3][i%3]
  1255.       # Draw sprite at index location
  1256.       # (ex. ID 0 should always be the top-left sprite)
  1257.       org_x = (((i % (width*3) / 3 * 32) - 32) + ((@ox *= 0) % 32))
  1258.       org_y = (((i / (width*3) * 32) - 32) + ((@oy *= 0)  % 32))
  1259.       tile.x = org_x * @zoom_x
  1260.       tile.y = org_y * @zoom_y
  1261.       # Assign tile's respective ID value
  1262.       if tile.is_a?(Sprite)
  1263.         tile.zoom_x, tile.zoom_y = @zoom_x, @zoom_y
  1264.         tile.instance_variable_set(:@tsprite_id, i)
  1265.       else
  1266.         tile.tsprite_id = i
  1267.       end
  1268.       tile_update(tile,i%3)
  1269.     end
  1270.     # Sprite ID located at top left corner
  1271.     @corner_index = 0
  1272.     self.ox = _ox
  1273.     self.oy = _oy
  1274.     sprite.bitmap.dispose
  1275.     sprite.dispose
  1276.   end
  1277.   #---------------------------------------------------------------------------
  1278.   # Set map data
  1279.   #---------------------------------------------------------------------------
  1280.   def map_data=(data)
  1281.     # Set the map data to new class
  1282.     @map_data = data.is_a?(Tilemap_DataTable) ?
  1283.                 data : Tilemap_DataTable.new(data)
  1284.     @map_data.table = @map_data.table.clone
  1285.     @animating_tiles.clear
  1286.     refresh
  1287.   end
  1288.   #---------------------------------------------------------------------------
  1289.   # * Check whether sprite is exist
  1290.   #---------------------------------------------------------------------------
  1291.   def sprite_exist?(sprite)
  1292.     sprite.is_a?(CRSprite) || (sprite.is_a?(Sprite) && !sprite.disposed?)
  1293.   end
  1294.   #---------------------------------------------------------------------------
  1295.   # * New method: method_missing
  1296.   #---------------------------------------------------------------------------
  1297.   def method_missing(val,*a,&b)
  1298.     en = tile_sprites.flatten.find_all {|s|s.respond_to?(val.to_sym)}
  1299.     if en.empty?
  1300.       text = "Undefined method #{val} at #{self.inspect}"
  1301.       raise(NoMethodError,text,caller(1))
  1302.     end
  1303.     return en.map {|s| s.send(val.to_sym,*a,&b)}
  1304.   end  
  1305.   #---------------------------------------------------------------------------
  1306.   # * New method: zoom_x=
  1307.   #---------------------------------------------------------------------------
  1308.   def zoom_x=(value)
  1309.     return if @zoom_x == value
  1310.     (@zoom_x = (value == value.to_i) ? value.to_i : value) && refresh
  1311.   end
  1312.   #---------------------------------------------------------------------------
  1313.   # * New method: zoom_y=
  1314.   #---------------------------------------------------------------------------
  1315.   def zoom_y=(value)
  1316.     return if @zoom_y == value
  1317.     (@zoom_y = (value == value.to_i) ? value.to_i : value) && refresh
  1318.   end
  1319.   #---------------------------------------------------------------------------
  1320.   # * Frame Update
  1321.   #---------------------------------------------------------------------------
  1322.   def update
  1323.     update_autotile
  1324.     update_check_resolution
  1325.   end
  1326.   #---------------------------------------------------------------------------
  1327.   # * Update the autotile
  1328.   #---------------------------------------------------------------------------
  1329.   def update_autotile
  1330.     # Update the sprites.
  1331.     if Graphics.frame_count % $game_map.autotile_speed == 0
  1332.       # Increase current frame of tile by one, looping by width.
  1333.       for i in 0..6
  1334.         next if @total_frames.at(i) == 0
  1335.         @current_frame[i] = (@current_frame.at(i) + 1) % @total_frames.at(i)
  1336.       end
  1337.       @animating_tiles.each_value do |tile|
  1338.         frames = tile.bitmap.width
  1339.         tile.src_rect.set((tile.src_rect.x+256)%frames,tile.src_rect.y,32,32)
  1340.       end
  1341.     end
  1342.   end
  1343.   #---------------------------------------------------------------------------
  1344.   # * Refresh if Resolution is changed
  1345.   #---------------------------------------------------------------------------
  1346.   def update_check_resolution
  1347.     if @old_width != width || @old_height != height
  1348.       (@old_width = width) && (@old_height = height)
  1349.       refresh
  1350.     end
  1351.   end
  1352.   #---------------------------------------------------------------------------
  1353.   # Dispose all the tile sprites
  1354.   #---------------------------------------------------------------------------
  1355.   def dispose
  1356.     # Dispose all of the sprites
  1357.     @tile_sprites.flatten.each {|tile| tile.dispose }
  1358.     @tile_sprites.clear
  1359.     @animating_tiles.clear
  1360.   end
  1361. end
  1362.  
  1363. # Call the resolution, setting it to a global variable for plug-ins.
  1364. $resolution = Resolution.new
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement