SHARE
TWEET

[RGSS] KK20's XPA Tilemap (edited)

LiTTleDRAgo Nov 15th, 2014 (edited) 378 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. =begin
  2. ===============================================================================
  3. XPA Tilemap                                                      Version 0.11b
  4. by KK20                                                          03 Nov 2014
  5. _______________________________________________________________________________
  6.  
  7.  [ Version History]
  8.  
  9.  Ver.      Date            Notes
  10.  -----     -----------     ----------------------------------------------------
  11.  0.11b ... 03 Nov 2014 ... Bug fixes:
  12.                             - Table did not take in parameters upon initialize
  13.                             - Centering of maps now shrinks Viewport sizes
  14.                             - Fixed Tilemap#oy= logic
  15.  0.1b  ... 02 Nov 2014 ... Initial release
  16. _______________________________________________________________________________
  17.  
  18.  [ Introduction ]
  19.  
  20.  In light of recent discoveries regarding the usage of RGSS3 in RPG Maker XP
  21.  games, many users were left with a dilemma in choosing which Tilemap rewrite
  22.  to use due to the vast differences between RGSS1's and RGSS3's Tilemap classes
  23.  that would cause complications in this transition. I aimed to find the best
  24.  Tilemap rewrite and decided that I would have to make my own. Like every other
  25.  Tilemap rewrite before it, this implementation is in no ways perfect, boasting
  26.  PROs and CONs.
  27.  
  28.  This script is intended to be used for RPG Maker XP games using the RGSS3
  29.  library (unofficially coined RPG Maker XP Ace); however, it is entirely
  30.  compatible with RPG Maker XP games in the RGSS1 library.
  31. _______________________________________________________________________________
  32.  
  33.  [ License ]
  34.  
  35.  This work is protected by the following license:
  36.  http://creativecommons.org/licenses/by-nc-sa/3.0/
  37.  
  38. *******************************************************************************
  39.  
  40. You are free:
  41.  
  42. to Share - to copy, distribute and transmit the work
  43. to Remix - to adapt the work
  44.  
  45. Under the following conditions:
  46.  
  47. Attribution:
  48. You must attribute the work in the manner specified by the author or licensor,
  49. but not in any way that suggests that they endorse you or your use of the work.
  50.  
  51. Noncommercial:
  52. You may not use this work for commercial purposes.
  53.  
  54. Share alike:
  55. If you alter, transform, or build upon this work, you may distribute the
  56. resulting work only under the same or similar license to this one.
  57.  
  58. - For any reuse or distribution, you must make clear to others the license  
  59.   terms of this work. The best way to do this is with a link to this web page.
  60.  
  61. - Any of the above conditions can be waived if you get permission from the
  62.   copyright holder.
  63.  
  64. - Nothing in this license impairs or restricts the author's moral rights.
  65.  
  66. *******************************************************************************
  67.  
  68.  [ Instructions ]
  69.  
  70.  - Place this script below the default scripts but above Main.
  71.  - Move 'XPATilemap.dll' into your project folder (same directory as 'Game.exe')
  72.  - Configure values at the start of the script
  73.  
  74.  More detailed instructions can be found in the PDF that came with this script.
  75. _______________________________________________________________________________
  76.  
  77.  [ Features ]
  78.  
  79.  About the script:
  80.  - XP and XPA (RGSS1 and RGSS3) compatible
  81.  - Define your own custom resolution
  82.  - Maps that are smaller than the game resolution are automatically centered
  83.  - Drawing methods written in C-language, which has faster pixel-by-pixel
  84.    operations than Ruby
  85.  
  86.  Add-ons:
  87.  - Customize frame rate animation and define unique patterns for your autotiles
  88.  - Remove unnecessary priority layers to boost frames-per-second (FPS)
  89.  - Extend the default RPG::Weather class to fit larger screens, or not
  90.  - more to add later...
  91. _______________________________________________________________________________
  92.  
  93.  [ Compatibility ]
  94.  
  95.  Unknown at this time...
  96. _______________________________________________________________________________
  97.  
  98.  [ Credits ]
  99.  
  100.  KK20 - Author of this script and DLL
  101.  Zexion - Tester and morale support
  102.  ForeverZer0 - Reusing code from his Custom Resolution script, found here:
  103.                 http://forum.chaos-project.com/index.php/topic,7814.0.html
  104.  LiTTleDRAgo - Reusing code from his edits to Custom Resolution
  105. _______________________________________________________________________________
  106.  
  107.  [ Contact ]
  108.  
  109.  To contact the author of this script, please visit
  110.                 http://forum.chaos-project.com/index.php
  111.                
  112.  or send an email to
  113.                         tscrane20@gmail.com
  114.                        
  115. ===============================================================================
  116. =end
  117. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  118. #                                       B E G I N   C O N F I G U R A T I O N
  119. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  120. #------------------------------------------------------------------------------
  121. # The game window's screen resolution. RPG Maker XP's default is [640, 480].
  122. # Do note that a larger resolution is prone to sprite lag.
  123. #------------------------------------------------------------------------------
  124. SCREEN_RESOLUTION = [740,510]
  125.  
  126. #------------------------------------------------------------------------------
  127. # Save modified resolution to a file, change to false to disable
  128. # To modify resolution, use $resolution.resize_screen(width,height)
  129. #------------------------------------------------------------------------------
  130. SAVE_RESOLUTION_TO_FILE = "Resolution.rxdata"  
  131.  
  132. #------------------------------------------------------------------------------
  133. # The largest level of priority your game uses. This value should be between
  134. # 1 and 5. If using a large resolution, lowering the number of priority layers
  135. # will help in reducing the lag.
  136. #------------------------------------------------------------------------------
  137. MAX_PRIORITY_LAYERS = 5
  138.  
  139. #------------------------------------------------------------------------------
  140. # If using a larger resolution than 640x480, the default weather effects will
  141. # look sparse as there are fewer sprites to cover a wider area. Setting this to
  142. # TRUE will increase the number of sprites proportionally. This will create
  143. # more lag as a result.
  144. #------------------------------------------------------------------------------
  145. WEATHER_ADJUSTMENT = false
  146.  
  147. #------------------------------------------------------------------------------
  148. # Prevents the player from using ALT + ENTER to go into Fullscreen Mode. Note
  149. # that this change applies to all applications on the player's computer.
  150. #------------------------------------------------------------------------------
  151. DISABLE_ALT_ENTER = true
  152.  
  153. #------------------------------------------------------------------------------
  154. # Set the animation frame rate for autotiles. By default, all autotiles will
  155. # update on the 16th frame. You can change that by providing an array of
  156. # numbers that represent how many frames that particular frame on animation
  157. # will be visible for.
  158. #------------------------------------------------------------------------------
  159. def autotile_framerate(filename)
  160.   case filename
  161.   when '009-G2_Water01' then return [8,8,8,8]
  162.   when '001-G_Water01' then return [20,20,20,20]
  163.   when '024-Ocean01' then return [32,16,32,16]
  164.   else
  165.     # Generates array of [16, 16, ...] based on autotile width
  166.     # (or nil if not animating autotile)
  167.     w = RPG::Cache.autotile(filename).width
  168.     h = RPG::Cache.autotile(filename).height
  169.     if (h == 32 && w / 32 == 1) || (h == 192 && w / 256 == 1)
  170.       return nil
  171.     else
  172.       return h == 32 ? Array.new(w/32){|i| 16} : Array.new(w/256){|i| 16}
  173.     end
  174.   end
  175. end
  176. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  177. #                                           E N D   C O N F I G U R A T I O N
  178. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  179. if DISABLE_ALT_ENTER
  180.   # Disable ALT+Enter
  181.   reghotkey = Win32API.new('user32', 'RegisterHotKey', 'LIII', 'I')
  182.   reghotkey.call(0, 1, 1, 0x0D)
  183. end
  184.  
  185. XPACE = RUBY_VERSION == "1.9.2"
  186.  
  187. #==============================================================================
  188. # ** Resolution
  189. #==============================================================================
  190.  
  191. class Resolution
  192.  
  193.   SAVEDATA = SAVE_RESOLUTION_TO_FILE
  194.  
  195.   attr_reader :version, :window
  196.  
  197.   define_method(:width)      { @width  ||= SCREEN_RESOLUTION[0] }
  198.   define_method(:height)     { @height ||= SCREEN_RESOLUTION[1] }
  199.   define_method(:maxsize)    { [@metrics.call(0), @metrics.call(1)] }
  200.   define_method(:fullscreen?){ [@width,@height] == maxsize }
  201.   define_method(:fullscreen) { fullscreen?||resize_screen(*maxsize) }
  202.   define_method(:window)     { fullscreen?&&(s=@old_size)&&resize_screen(*s) }
  203.  
  204.   def initialize
  205.     # Define version.
  206.     @version = 1.12
  207.     # Set instance variables for calling basic Win32 functions.
  208.     ini = Win32API.new('kernel32', 'GetPrivateProfileString','PPPPLP', 'L')
  209.     ini.call('Game', 'Title', '', (title = "\0" * 256), 256, '.\\Game.ini')
  210.     findwindow       = Win32API.new('user32','FindWindow','PP','I')
  211.     @set_window_long = Win32API.new('user32', 'SetWindowLong', 'LIL', 'L')
  212.     @set_window_pos  = Win32API.new('user32', 'SetWindowPos', 'LLIIIII', 'I')
  213.     @metrics         = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
  214.     @window          = findwindow.call('RGSS Player', title.delete!("\0"))
  215.     # Apply resolution change.
  216.     load_setting
  217.   end
  218.   #--------------------------------------------------------------------------
  219.   def resize_screen(w,h)
  220.     @old_size = [width,height] unless [width,height] == (s = maxsize)
  221.     @width, @height = w, h
  222.     $game_map.refresh_map_edge if $game_map
  223.     $scene = $scene.class.new  if $scene
  224.     $game_player.center($game_player.x,$game_player.y) if $game_player
  225.     if (save = SAVEDATA) && (File.exist?(save) or [w,h] != SCREEN_RESOLUTION)
  226.       Marshal.dump([w,h,@old_size], (file=File.open(save,"wb"))) && file.close
  227.     end
  228.     Graphics.resize_screen(w,h) if Graphics.respond_to?(:resize_screen)
  229.     @set_window_long.call(@window, -16, s == [w,h] ? 0x14000000 : 0x14CA0000)
  230.     @set_window_pos.call(@window,0,(s[0]-w)/2,(s[1]-h)/2, w, h, 0)
  231.   end
  232.   #--------------------------------------------------------------------------
  233.   def load_setting
  234.     if (load = SAVEDATA) && File.exist?(load)
  235.       (res = Marshal.load((file = File.open(load, "rb")))) && file.close
  236.       (@width, @height = res.at(2)) if res.at(2)
  237.       (resize_screen(res.at(0), res.at(1)))
  238.     else
  239.       resize_screen(width,height)
  240.     end
  241.   end
  242.   #--------------------------------------------------------------------------
  243. end
  244.  
  245. #==============================================================================
  246. # ** RPG::Cache
  247. #==============================================================================
  248.  
  249. module RPG::Cache
  250.  
  251.   AUTO_INDEX = [[
  252.       [27,28,33,34],  [ 5,28,33,34],  [27, 6,33,34],  [ 5, 6,33,34],
  253.       [27,28,33,12],  [ 5,28,33,12],  [27, 6,33,12],  [ 5, 6,33,12],
  254.       [27,28,11,34],  [ 5,28,11,34],  [27, 6,11,34],  [ 5, 6,11,34],
  255.       [27,28,11,12],  [ 5,28,11,12],  [27, 6,11,12],  [ 5, 6,11,12],
  256.       [25,26,31,32],  [25, 6,31,32],  [25,26,31,12],  [25, 6,31,12],
  257.       [15,16,21,22],  [15,16,21,12],  [15,16,11,22],  [15,16,11,12],
  258.       [29,30,35,36],  [29,30,11,36],  [ 5,30,35,36],  [ 5,30,11,36],
  259.       [39,40,45,46],  [ 5,40,45,46],  [39, 6,45,46],  [ 5, 6,45,46],
  260.       [25,30,31,36],  [15,16,45,46],  [13,14,19,20],  [13,14,19,12],
  261.       [17,18,23,24],  [17,18,11,24],  [41,42,47,48],  [ 5,42,47,48],
  262.       [37,38,43,44],  [37, 6,43,44],  [13,18,19,24],  [13,14,43,44],
  263.       [37,42,43,48],  [17,18,47,48],  [13,18,43,48],  [ 1, 2, 7, 8]],
  264.      
  265.      [[27,28,33,34],  [49,50,55,56],  [51,52,57,58],  [49,52,55,58],
  266.       [63,64,69,70],  [65,66,71,72],  [51,52,69,70],  [ 5, 6,33,12],
  267.       [61,62,67,68],  [49,50,67,68],  [53,54,59,60],  [ 5, 6,11,34],
  268.       [61,64,67,70],  [ 5,28,11,12],  [27, 6,11,12],  [ 5, 6,11,12],
  269.       [25,26,31,32],  [25, 6,31,32],  [25,26,31,12],  [25, 6,31,12],
  270.       [15,16,21,22],  [15,16,21,12],  [15,16,11,22],  [15,16,11,12],
  271.       [29,30,35,36],  [29,30,11,36],  [ 5,30,35,36],  [ 5,30,11,36],
  272.       [39,40,45,46],  [ 5,40,45,46],  [39, 6,45,46],  [ 5, 6,45,46],
  273.       [25,30,31,36],  [15,16,45,46],  [13,14,19,20],  [13,14,19,12],
  274.       [17,18,23,24],  [17,18,11,24],  [41,42,47,48],  [ 5,42,47,48],
  275.       [37,38,43,44],  [37, 6,43,44],  [13,18,19,24],  [13,14,43,44],
  276.       [37,42,43,48],  [17,18,47,48],  [13,18,43,48],  [ 1, 2, 7, 8]]
  277.     ].freeze
  278.  
  279.   def self.autotile(filename)
  280.     key = "Graphics/Autotiles/#{filename}"
  281.     if !@cache.include?(key) || @cache[key].disposed?
  282.       # Cache the autotile graphic.
  283.       @cache[key] = (filename == '') ? Bitmap.new(128, 96) : Bitmap.new(key)
  284.       # Cache each configuration of this autotile.
  285.       new_bm = self.format_autotiles(@cache[key], filename)
  286.       @cache[key] = [@cache[key].dispose] && new_bm
  287.     end
  288.     return @cache[key]
  289.   end
  290.  
  291.   def self.format_autotiles(bitmap, filename)
  292.     if bitmap.height > 32
  293.       frames = bitmap.width / 96
  294.       index = bitmap.height == 192 ? AUTO_INDEX[1] : AUTO_INDEX[0]
  295.       template = Bitmap.new(256*frames,192)
  296.       frames.times {|a| (0...6).each { |i| (0...8).each { |j|
  297.         index[8*i+j].each { |number|
  298.           number -= 1
  299.           x, y = 16 * (number % 6), 16 * (number / 6)
  300.           ox, oy = (32 * j + x % 32) + (a * 256), 32 * i + y % 32
  301.           rect = Rect.new(x + (a * 96), y, 16, 16)
  302.           template.blt(ox, oy, bitmap, rect)
  303.       }}}}
  304.       return template
  305.     else
  306.       return bitmap
  307.     end
  308.   end
  309.  
  310. end
  311. #==============================================================================
  312. # ** Resolution
  313. #==============================================================================
  314. class Viewport
  315.  
  316.   def resize(*args)
  317.     # Resize the viewport. Can call with (X, Y, WIDTH, HEIGHT) or (RECT).
  318.     self.rect = args[0].is_a?(Rect) ? args[0] : Rect.new(*args)
  319.   end
  320.  
  321.   def update_viewport_sizes
  322.     w = $resolution.width
  323.     h = $resolution.height
  324.     _w = ($game_map.width  * 32 * $game_map.zoom_x)
  325.     _h = ($game_map.height * 32 * $game_map.zoom_y)
  326.     dx = w > _w ? ((w - _w).abs / 32.0) * 16 : 0
  327.     dw = [w, $game_map.width  * 32 * $game_map.zoom_x].min  
  328.     dy = h > _h ? ((h - _h).abs / 32.0) * 16 : 0
  329.     dh = [h, $game_map.height * 32 * $game_map.zoom_y].min
  330.     resize(Rect.new(dx, dy, dw, dh))
  331.   end
  332. end
  333.  
  334. #==============================================================================
  335. # ** Tilemap
  336. #==============================================================================
  337. class Tilemap
  338.  
  339.   attr_accessor :tileset, :autotiles, :map_data, :priorities, :ground_sprite
  340.   attr_accessor :zoom_x, :zoom_y
  341.   #---------------------------------------------------------------------------
  342.   # Initialize
  343.   #---------------------------------------------------------------------------
  344.   def initialize(viewport = nil)
  345.     @viewport = viewport
  346.     @layer_sprites = []
  347.     # [[ANIMATION_DRAW_INDEX, CURRENT_LOGICAL_FRAME], ... ]
  348.     @autotile_frame = []      
  349.     # [[DATA_FROM_CONFIGURATION_ABOVE], ... ]
  350.     @autotile_framedata = []  
  351.    
  352.     @zoom_x = @zoom_y = 1
  353.     # Ensures that the bitmap width accounts for an extra tile
  354.     # and is divisible by 32
  355.     bitmap_width = (($resolution.width / 32.0).ceil + 1) * 32
  356.     # Create the priority layers
  357.     (($resolution.height/32.0).ceil + MAX_PRIORITY_LAYERS).times do |i|
  358.       s = Sprite.new(@viewport)
  359.       s.y = i*32 - (MAX_PRIORITY_LAYERS - 1) * 32 * @zoom_y
  360.       s.z = 32 * (i+2)
  361.       s.zoom_x = @zoom_x
  362.       s.zoom_y = @zoom_y
  363.       s.bitmap = Bitmap.new(bitmap_width, MAX_PRIORITY_LAYERS * 32)
  364.       @layer_sprites.push(s)
  365.     end
  366.     # Same reasons as bitmap_width, but for height
  367.     bitmap_height = (($resolution.height / 32.0).ceil + 1) * 32
  368.     # Create the ground layer (priority 0)
  369.     s = Sprite.new(@viewport)
  370.     s.bitmap = Bitmap.new(bitmap_width, bitmap_height)
  371.     @ground_sprite = s
  372.     @ground_sprite.z = 0
  373.     @ground_sprite.zoom_x = @zoom_x
  374.     @ground_sprite.zoom_y = @zoom_y
  375.    
  376.     # Initialize Autotile data
  377.     $game_map.autotile_names.each_index do |i|
  378.       filename = $game_map.autotile_names[i]
  379.       # Get animation frame rate of the autotile
  380.       frames = autotile_framerate(filename)
  381.       # If autotile doesn't animate
  382.       if frames.nil?
  383.         @autotile_frame[i] = [0,0]
  384.         @autotile_framedata[i] = nil
  385.       else
  386.         # Save the frame rate data
  387.         @autotile_framedata[i] = frames
  388.         # Determine how long one animation cycle takes and indicate at what
  389.         # time the next frame of animation occurs
  390.         total = 0
  391.         frame_checkpoints = []
  392.         frames.each_index{|j| frame_checkpoints[j] = (total += frames[j]) }
  393.         # Get animation frame for this autotile based on game time passed
  394.         current_frame = Graphics.frame_count % total
  395.         frame_checkpoints.each_index do |j|
  396.           c = frame_checkpoints[j]
  397.           if c && c > current_frame
  398.             (@autotile_frame[i] = [j, c - current_frame]) && break
  399.           end
  400.         end
  401.       end
  402.     end
  403.     # Initialize remaining variables
  404.     @first_update = true
  405.     @autotiles    = []
  406.     @empty        = Color.new(0,0,0,0)
  407.     @old_ox       = @old_oy = 0
  408.     @ox           = @oy = 0
  409.     @shift        = 0
  410.     # Set up the DLL calls
  411.     @@update          = Win32API.new("XPATilemap","DrawMapsBitmap2","pppp","i")
  412.     @@autotile_update = Win32API.new("XPATilemap","UpdateAutotiles","pppp","i")
  413.     @@initial_draw    = Win32API.new("XPATilemap","DrawMapsBitmap","pppp","i")
  414.     init_empty_tile   = Win32API.new("XPATilemap","InitEmptyTile","l","i")
  415.     init_empty_tile.call((@empty_tile = Bitmap.new(32,32)).object_id)
  416.   end
  417.   #---------------------------------------------------------------------------
  418.   # Dispose tilemap
  419.   #---------------------------------------------------------------------------
  420.   def dispose
  421.     @layer_sprites.each{|sprite| sprite.dispose}
  422.     @ground_sprite.dispose
  423.   end
  424.   #---------------------------------------------------------------------------
  425.   # Zoom x
  426.   #---------------------------------------------------------------------------
  427.   def zoom_x=(value)
  428.     return if @zoom_x == value
  429.     (@layer_sprites + [@ground_sprite]).each do |sprite|
  430.       sprite.x *= value / zoom_x
  431.       sprite.zoom_x = value
  432.     end
  433.     @zoom_x = value
  434.   end
  435.   #---------------------------------------------------------------------------
  436.   # Zoom y
  437.   #---------------------------------------------------------------------------
  438.   def zoom_y=(value)
  439.     return if @zoom_y == value
  440.     (@layer_sprites + [@ground_sprite]).each do |sprite|
  441.       sprite.y *= value / zoom_y
  442.       sprite.zoom_y = value
  443.     end
  444.     @zoom_y = value
  445.   end
  446.   #---------------------------------------------------------------------------
  447.   # Check if disposed tilemap
  448.   #---------------------------------------------------------------------------
  449.   def disposed?
  450.     return @layer_sprites[0].disposed?
  451.   end
  452.   #---------------------------------------------------------------------------
  453.   # Get viewport
  454.   #---------------------------------------------------------------------------
  455.   def viewport
  456.     return @viewport
  457.   end
  458.   #---------------------------------------------------------------------------
  459.   # Update tilemap graphics
  460.   #---------------------------------------------------------------------------
  461.   def update
  462.     # t = Time.now
  463.     autotile_need_update = []
  464.     # Update autotile animation frames
  465.     for i in 0..6
  466.       autotile_need_update[i] = false
  467.       # If this autotile doesn't animate, skip
  468.       next if @autotile_framedata[i].nil?
  469.       # Reduce frame count
  470.       @autotile_frame[i][1] -= 1
  471.       # Autotile requires update
  472.       if (autotile = @autotile_frame[i])[1] == 0
  473.         autotile[0] = (autotile[0] + 1) % @autotile_framedata[i].size
  474.         autotile[1] = @autotile_framedata[i][autotile[0]]
  475.         autotile_need_update[i] = true
  476.       end
  477.     end
  478.     # If $game_map.data[]= script call was used, force redraw on entire map
  479.     if self.map_data.changed
  480.       @first_update = true
  481.       self.map_data.changed = false
  482.     end
  483.    
  484.     # Stop the update unless updating for first time or there are no shifting
  485.     return if (!@first_update && @shift==0 &&
  486.                autotile_need_update.index(true).nil?)
  487.  
  488.     # Set up the array for the priority layers
  489.     layers = [@layer_sprites.size + 1]
  490.     # Insert higher priority layers into the array in order
  491.     # (least to most y-value sprite)
  492.     @layer_sprites.each{|sprite| layers.push(sprite.bitmap.object_id) }
  493.     # Insert ground layer last in the array
  494.     layers.push(@ground_sprite.bitmap.object_id)
  495.     # Load autotile bitmap graphics into array
  496.     tile_bms = [self.tileset.object_id]
  497.     self.autotiles.each{|autotile| tile_bms.push(autotile.object_id) }
  498.     # Store autotile animation frame data
  499.     autotiledata = []
  500.     for i in 0..6
  501.       autotiledata.push(@autotile_frame[i][0])
  502.       autotiledata.push(autotile_need_update[i] ? 1 : 0)
  503.     end
  504.     # Fills in remaining information of other tilemaps
  505.     misc_data = [@ox + $game_screen.shake.to_i, @oy, self.map_data.object_id,
  506.                  self.priorities.object_id, @shift, MAX_PRIORITY_LAYERS]
  507.     process = [layers.pack("L*"), tile_bms.pack("L*"),
  508.                autotiledata.pack("L*"), misc_data.pack("L*")]
  509.     # If forcing fresh redraw of the map (or drawing for first time)
  510.     if @first_update
  511.       # Initialize layer sprite positions and clear them for drawing
  512.       @layer_sprites.each_index{|i| layer = @layer_sprites[i]
  513.         layer.bitmap.clear
  514.         layer.x = -@ox % 32
  515.         if layer.x <= -32 + $game_screen.shake.to_i
  516.           layer.x += 32
  517.         elsif layer.x > $game_screen.shake.to_i
  518.           layer.x -= 32
  519.         end
  520.         layer.y = (i * 32) - (@oy % 32) - (MAX_PRIORITY_LAYERS-1) * 32
  521.         layer.x *= @zoom_x
  522.         layer.y *= @zoom_y
  523.         layer.zoom_x = @zoom_x
  524.         layer.zoom_y = @zoom_y
  525.       }
  526.       @ground_sprite.bitmap.clear
  527.       @ground_sprite.x = -(@ox % 32)
  528.       if @ground_sprite.x <= -32 + $game_screen.shake.to_i
  529.         @ground_sprite.x += 32
  530.       elsif @ground_sprite.x > $game_screen.shake.to_i
  531.         @ground_sprite.x -= 32
  532.       end
  533.       @ground_sprite.y = -(@oy % 32)
  534.       @ground_sprite.x *= @zoom_x
  535.       @ground_sprite.y *= @zoom_y
  536.       @ground_sprite.zoom_x = @zoom_x
  537.       @ground_sprite.zoom_y = @zoom_y
  538.       # Turn off flag to prevent calling this portion of code again
  539.       @first_update = false
  540.       # Make DLL call
  541.       @@initial_draw.call(*process)
  542.     elsif @shift != 0
  543.       # Update for shifting
  544.       @@update.call(*process)
  545.     end
  546.     # Check for autotile updates
  547.     autotile_need_update.index(true).nil? ||  @@autotile_update.call(*process)
  548.     # Reset shift flag
  549.     @shift = 0
  550.    
  551.     #puts Time.now - t
  552.   end
  553.   #---------------------------------------------------------------------------
  554.   # Return if tilemap is visible
  555.   #---------------------------------------------------------------------------
  556.   def visible
  557.     return layer_sprites[0].visible
  558.   end
  559.   #---------------------------------------------------------------------------
  560.   # Show or hide tilemap
  561.   #---------------------------------------------------------------------------
  562.   def visible=(bool)
  563.     @layer_sprites.each{|sprite| sprite.visible = bool}
  564.     @ground_sprite.visible = bool
  565.   end
  566.   #---------------------------------------------------------------------------
  567.   # Shift tilemap horizontally
  568.   #---------------------------------------------------------------------------
  569.   def ox=(ox)
  570.     # No shift = no need to continue
  571.     if !$game_screen.shaking? && -(@ox % 32) * @zoom_x  != @ground_sprite.x
  572.       @first_update = true
  573.     end
  574.     ox = ox.round
  575.     return if @ox == ox && !$game_screen.shaking?
  576.     # Compute difference and save change
  577.     diff = @ox - ox
  578.     @ox = ox
  579.     # If forcing redraw, no need to shift layer sprites around
  580.     return if @first_update
  581.     # If shift is too big, force redraw
  582.     if diff.abs > 32
  583.       return @first_update = true
  584.     end
  585.     # Shift sprites
  586.     @ground_sprite.x += (diff * @zoom_x)
  587.     @layer_sprites.each{|sprite| sprite.x += (diff * @zoom_x)}
  588.  
  589.     # If sprites are out of bounds, reposition and redraw (make DLL call)
  590.     if @ground_sprite.x <= (-32 + $game_screen.shake.to_i) * @zoom_x
  591.       @ground_sprite.x += (32 * @zoom_x)
  592.       bitmap = @ground_sprite.bitmap
  593.       bitmap.fill_rect(0, 0, 32, bitmap.height, @empty)
  594.       @layer_sprites.each do |s|
  595.         s.bitmap.fill_rect((s.x+=(32*@zoom_x))*0,0,32,s.bitmap.height,@empty)
  596.       end
  597.       @shift += 1 # Redraw right column
  598.     elsif @ground_sprite.x > (0 + $game_screen.shake.to_i) * @zoom_x
  599.       @ground_sprite.x -= (32 * @zoom_x)
  600.       bitmap = @ground_sprite.bitmap
  601.       bitmap.fill_rect(bitmap.width - 32, 0, 32, bitmap.height, @empty)
  602.       @layer_sprites.each do |s|
  603.         s.x -= (32 * @zoom_x)
  604.         s.bitmap.fill_rect(s.bitmap.width - 32,0,32,s.bitmap.height,@empty)
  605.       end
  606.       @shift += 2 # Redraw left column
  607.     end
  608.   end
  609.   #---------------------------------------------------------------------------
  610.   # Shift tilemap vertically
  611.   #---------------------------------------------------------------------------
  612.   def oy=(oy)
  613.     if !$game_screen.shaking? && -(@oy % 32) * @zoom_y != @ground_sprite.y  
  614.       @first_update = true
  615.     end
  616.     oy = oy.round
  617.     return if @oy == oy
  618.     diff = @oy - oy
  619.     @oy = oy
  620.     # If shift is too big, force redraw
  621.     return if @first_update  
  622.     if diff.abs > 32
  623.       return @first_update = true
  624.     end
  625.     # Shift sprites
  626.     @ground_sprite.y += (diff * @zoom_y)
  627.     @layer_sprites.each{ |sprite|
  628.       sprite.y += (diff * @zoom_y)
  629.       sprite.z += diff
  630.     }
  631.     # If ground is out of bounds, reshift and redraw (make DLL call)
  632.     if @ground_sprite.y <= -32 * @zoom_y
  633.       @ground_sprite.y += (32 * @zoom_y)
  634.       @shift += 4 # Redraw bottom row
  635.     elsif @ground_sprite.y > 0
  636.       @ground_sprite.y -= (32 * @zoom_y)
  637.       @shift += 8 # Redraw top row
  638.     end
  639.  
  640.     # If layer is too far up screen, need to move it down
  641.     if @layer_sprites[0].y <= -(MAX_PRIORITY_LAYERS * 32) * @zoom_y
  642.       shift_amt = (($resolution.height/32.0).ceil + MAX_PRIORITY_LAYERS) * 32
  643.       layer = @layer_sprites.shift
  644.       layer.y += shift_amt * @zoom_y
  645.       layer.z += shift_amt
  646.       layer.bitmap.clear
  647.       @layer_sprites.push(layer)
  648.     end
  649.     # If layer is too far down screen, need to move it up
  650.     if @layer_sprites[-1].y > (($resolution.height/32.0).ceil * 32) * @zoom_y
  651.       shift_amt = (($resolution.height/32.0).ceil + MAX_PRIORITY_LAYERS) * -32
  652.       layer = @layer_sprites.pop
  653.       layer.y += shift_amt * @zoom_y
  654.       layer.z += shift_amt
  655.       layer.bitmap.clear
  656.       @layer_sprites.unshift(layer)
  657.     end
  658.   end
  659. end
  660.  
  661. #==============================================================================
  662. # ** Game_Character
  663. #------------------------------------------------------------------------------
  664. #  This class deals with characters. It's used as a superclass for the
  665. #  determinants and map scrolling. Refer to "$game_player" for the one
  666. #  Game_Player and Game_Event classes.
  667. #==============================================================================
  668. class Game_Character
  669.  
  670.   $@ || alias_method(:screen_x_zoom, :screen_x)
  671.   $@ || alias_method(:screen_y_zoom, :screen_y)
  672.   $@ || alias_method(:screen_z_zoom, :screen_z)
  673.  
  674.   define_method(:screen_x) {|*args| screen_x_zoom(*args) * $game_map.zoom_x }
  675.   define_method(:screen_y) {|*args| screen_y_zoom(*args) * $game_map.zoom_y }
  676.  
  677.   def screen_z(*args)
  678.     return 999     if @always_on_top
  679.     return $1.to_i if self.is_a?(Game_Event) &&
  680.          self.instance_variable_get(:@event).name[/\<Z:\s*([-]?\d+)\s*\>/i]
  681.          
  682.     case @character_name
  683.     when '178-Switch01'  then return 0
  684.     when '180-Switch03'  then return 0
  685.     when '181-Switch04'  then return 0
  686.     when '199-Support07' then return 0
  687.     end
  688.     return screen_z_zoom(*args)
  689.   end
  690. end
  691. #==============================================================================
  692. # ** Game_Player
  693. #==============================================================================
  694.  
  695. class Game_Player
  696.  
  697.   def center(x, y)
  698.     # Recalculate the screen center based on the new resolution.
  699.     max_x = $game_map.map_edge.at(0)
  700.     max_y = $game_map.map_edge.at(1)  
  701.     $game_map.display_x = [0, [x * 128 - CENTER_X, max_x].min].max
  702.     $game_map.display_y = [0, [y * 128 - CENTER_Y, max_y].min].max
  703.   end  
  704. end
  705. #==============================================================================
  706. # ** Game_Map
  707. #==============================================================================
  708. class Game_Map
  709.  
  710.   $@ || alias_method(:zer0_map_edge_setup, :setup)
  711.   $@ || alias_method(:drg_width_adjust,    :width)
  712.   $@ || alias_method(:drg_height_adjust,   :height)
  713.   $@ || alias_method(:drg_update_zooming,  :update)
  714.  
  715.   attr_reader :map_edge
  716.   define_method(:zoom_x)            { [[@zoom_x ||= 1,12].min, 0.5].max }
  717.   define_method(:zoom_y)            { [[@zoom_y ||= 1,12].min, 0.5].max }
  718.   define_method(:width)             { @map ? drg_width_adjust  : 0  }
  719.   define_method(:height)            { @map ? drg_height_adjust : 0  }
  720.   define_method(:zooming?)          { (@zoom_duration ||= 0) > 0 }
  721.  
  722.   def setup(map_id)
  723.     zer0_map_edge_setup(map_id)
  724.     refresh_map_edge
  725.   end
  726.  
  727.   def refresh_map_edge
  728.     # Find the displayed area of the map in tiles. No calculating every step.
  729.     @map_edge = [[width*zoom_x-($resolution.width/32.0),0].max/zoom_x,
  730.                 [height*zoom_y-($resolution.height/32.0),0].max/zoom_y]
  731.     @map_edge.collect! {|size| (size * 128).ceil }
  732.     Game_Player.const_set(:CENTER_X,(($resolution.width/2)  / zoom_x - 16) * 4)
  733.     Game_Player.const_set(:CENTER_Y,(($resolution.height/2) / zoom_y - 16) * 4)
  734.     s = $scene.instance_variable_get(:@spriteset)
  735.     s.update_viewport_sizes if s.respond_to?(:update_viewport_sizes)
  736.   end
  737.  
  738.   def scroll_down(distance)
  739.     # Find point that the map edge meets the screen edge, using custom size.
  740.     @display_y = [@display_y + distance, @map_edge[1]].min
  741.   end
  742.  
  743.   def scroll_right(distance)
  744.     # Find point that the map edge meets the screen edge, using custom size.
  745.     @display_x = [@display_x + distance, @map_edge[0]].min
  746.   end
  747.  
  748.   def zoom(*zoom)
  749.     if zoom.size == 1
  750.       zoom = (zoom.first)
  751.     elsif zoom.size == 3
  752.       x,y,zoom = zoom
  753.     end
  754.     return unless zoom.is_a?(Numeric)
  755.     @zoom_x = @zoom_y = zoom
  756.     @zoom_x , @zoom_y = self.zoom_x, self.zoom_y
  757.     refresh_map_edge
  758.     $game_player.center(x,y) if x && y
  759.   end
  760.  
  761.   def start_zoom(x,y, zoom_target, duration=20)
  762.     @x_zoom, @y_zoom = x, y
  763.     @zoom_target = zoom_target * 1.0
  764.     @zoom_duration = @zoom_x == @zoom_target ? 0 : duration
  765.     if @zoom_duration == 0 && @zoom_x != @zoom_target
  766.       zoom(*[@x_zoom,@y_zoom,zoom_target].compact)
  767.     end
  768.   end
  769.  
  770.   def update_zooming
  771.     if zooming?
  772.       d = @zoom_duration
  773.       power = (@zoom_x * (d - 1) + @zoom_target) / d
  774.       args = [@x_zoom,@y_zoom,power].compact
  775.       zoom(*args)
  776.       @zoom_duration -= 1
  777.     end
  778.   end
  779.  
  780.   def update(*args)
  781.     drg_update_zooming(*args)
  782.     update_zooming
  783.   end
  784. end
  785. #==============================================================================
  786. # ** Plane
  787. #==============================================================================
  788. Object.send(:remove_const, :Plane)
  789. class Plane < Sprite
  790.  
  791.   attr_reader :bitmap
  792.   def z=(z)
  793.     # Change the Z value of the viewport, not the sprite.
  794.     super(z * 1000)
  795.   end
  796.  
  797.   def ox=(ox)
  798.     # Have viewport stay in loop on X-axis.
  799.     super(ox % bitmap.width)  if bitmap.is_a?(Bitmap)
  800.   end
  801.  
  802.   def oy=(oy)
  803.     # Have viewport stay in loop on Y-axis.
  804.     super(oy % bitmap.height) if bitmap.is_a?(Bitmap)
  805.   end
  806.  
  807.   def dispose
  808.     @plane && (@plane.disposed? || @plane.dispose)
  809.     super unless disposed?
  810.   end
  811.  
  812.   def bitmap=(tile)
  813.     return if @bitmap == tile
  814.     @bitmap = tile
  815.     return super(@bitmap) unless tile.is_a?(Bitmap)
  816.     # Calculate the number of tiles it takes to span screen in both directions.
  817.     xx = 1 + ($resolution.width.to_f  / tile.width ).ceil
  818.     yy = 1 + ($resolution.height.to_f / tile.height).ceil
  819.     # Create appropriately sized bitmap, then tile across it with source image.
  820.     @plane && (@plane.disposed? || @plane.dispose)
  821.     @plane = Bitmap.new(@bitmap.width * xx, @bitmap.height * yy)
  822.     (0..xx).each {|x| (0..yy).each {|y|
  823.       @plane.blt(x * @bitmap.width, y * @bitmap.height, @bitmap, @bitmap.rect)
  824.     }}
  825.     # Set the bitmap to the sprite through its super class (Sprite).
  826.     super(@plane)
  827.   end
  828.  
  829.   # Undefine methods dealing with coordinates (defined in super) to do nothing.
  830.   undef :x, :x=, :y, :y=   if method_defined?(:x)
  831. end
  832.  
  833. class CRPlane < Plane; end
  834. #==============================================================================
  835. # ** Table
  836. #==============================================================================
  837. class Table
  838.   attr_accessor :changed
  839.  
  840.   $@ || alias_method(:flag_changes_to_set, :"[]=")
  841.   def []=(*args)
  842.     @changed = true if args.size == 4
  843.     flag_changes_to_set(*args)
  844.   end
  845.  
  846. end
  847. #==============================================================================
  848. # ** RPG::Weather
  849. #==============================================================================
  850. class RPG::Weather
  851.  
  852.   if WEATHER_ADJUSTMENT
  853.    
  854.     $@ || alias_method(:add_more_weather_sprites, :initialize)
  855.     def initialize(vp = nil)
  856.       add_more_weather_sprites(vp)
  857.       total_sprites = $resolution.width * $resolution.height / 7680
  858.       if total_sprites > 40
  859.         for i in 1..(total_sprites - 40)
  860.           sprite = Sprite.new(vp)
  861.           sprite.z = 1000
  862.           sprite.visible = false
  863.           sprite.opacity = 0
  864.           @sprites.push(sprite)
  865.         end
  866.       end
  867.     end
  868.    
  869.     def type=(type)
  870.       return if @type == type
  871.       @type = type
  872.       bitmap = case @type
  873.       when 1 then @rain_bitmap
  874.       when 2 then @storm_bitmap
  875.       when 3 then @snow_bitmap
  876.       end
  877.       for i in 1..@sprites.size
  878.         sprite = @sprites[i]
  879.         if sprite != nil
  880.           sprite.visible = (i <= @max)
  881.           sprite.bitmap = bitmap
  882.         end
  883.       end
  884.     end
  885.    
  886.     def max=(max)
  887.       return if @max == max;
  888.       @max = [[max, 0].max, @sprites.size].min
  889.       for i in 1..@sprites.size
  890.         sprite = @sprites[i]
  891.         if sprite != nil
  892.           sprite.visible = (i <= @max)
  893.         end
  894.       end
  895.     end
  896.  
  897.   end # WEATHER_ADJUSTMENT  
  898.  
  899.   def update
  900.     return if @type == 0
  901.     for i in 1..@max
  902.       sprite = @sprites[i]
  903.       if sprite == nil
  904.         break
  905.       end
  906.       if @type == 1
  907.         sprite.x -= 2
  908.         sprite.y += 16
  909.         sprite.opacity -= 8
  910.       end
  911.       if @type == 2
  912.         sprite.x -= 8
  913.         sprite.y += 16
  914.         sprite.opacity -= 12
  915.       end
  916.       if @type == 3
  917.         sprite.x -= 2
  918.         sprite.y += 8
  919.         sprite.opacity -= 8
  920.       end
  921.       x = sprite.x - @ox
  922.       y = sprite.y - @oy
  923.       if sprite.opacity < 64
  924.         sprite.x = rand($resolution.width + 100) - 100 + @ox
  925.         sprite.y = rand($resolution.width + 200) - 200 + @oy
  926.         sprite.opacity = 160 + rand(96)
  927.       end
  928.     end
  929.   end
  930.  
  931. end
  932. #==============================================================================
  933. # ** Game_Screen
  934. #==============================================================================
  935. class Game_Screen
  936.   #--------------------------------------------------------------------------
  937.   # * Set Weather
  938.   #     type : type
  939.   #     power : strength
  940.   #     duration : time
  941.   #--------------------------------------------------------------------------
  942.   def weather(type, power, duration)
  943.     @weather_type_target = type
  944.     if @weather_type_target != 0
  945.       @weather_type = @weather_type_target
  946.     end
  947.     if @weather_type_target == 0
  948.       @weather_max_target = 0.0
  949.     else
  950.       if WEATHER_ADJUSTMENT
  951.         num = $resolution.width * $resolution.height / 76800.0
  952.       else
  953.         num = 4.0
  954.       end
  955.       @weather_max_target = (power + 1) * num
  956.     end
  957.     @weather_duration = duration
  958.     if @weather_duration == 0
  959.       @weather_type = @weather_type_target
  960.       @weather_max = @weather_max_target
  961.     end
  962.   end
  963.  
  964.   def shaking?
  965.     return @shake_duration > 0 || @shake != 0
  966.   end
  967. end
  968.  
  969. #==============================================================================
  970. # ** Spriteset_Map
  971. #==============================================================================
  972. class Spriteset_Map
  973.  
  974.   $@ || alias_method(:init_for_centered_small_maps , :initialize)
  975.   $@ || alias_method(:update_for_zoom, :update)
  976.  
  977.   #---------------------------------------------------------------------------
  978.   # Resize and reposition viewport so that it fits smaller maps
  979.   #---------------------------------------------------------------------------
  980.   def update_viewport_sizes
  981.     @viewport1.update_viewport_sizes
  982.     @viewport2.update_viewport_sizes
  983.     @viewport3.update_viewport_sizes
  984.   end
  985.  
  986.   def initialize
  987.     init_for_centered_small_maps
  988.     update_viewport_sizes
  989.   end
  990.  
  991.   def update    
  992.     if @old_fog_zoom_x
  993.       @fog.zoom_x          = @old_fog_zoom_x
  994.       @fog.zoom_y          = @old_fog_zoom_y
  995.       @panorama.zoom_x     = @old_panorama_zoom_x
  996.       @panorama.zoom_y     = @old_panorama_zoom_y
  997.     end
  998.     @tilemap.zoom_x      = $game_map.zoom_x
  999.     @tilemap.zoom_y      = $game_map.zoom_y
  1000.     update_for_zoom
  1001.     @old_fog_zoom_x      = @fog.zoom_x
  1002.     @old_fog_zoom_y      = @fog.zoom_y
  1003.     @old_panorama_zoom_x = @panorama.zoom_x
  1004.     @old_panorama_zoom_y = @panorama.zoom_y
  1005.     @fog.zoom_x         *= $game_map.zoom_x
  1006.     @fog.zoom_y         *= $game_map.zoom_y
  1007.     @panorama.zoom_x    *= $game_map.zoom_x
  1008.     @panorama.zoom_y    *= $game_map.zoom_y
  1009.   end
  1010. end
  1011. #==============================================================================
  1012. # ** Sprite_Character
  1013. #------------------------------------------------------------------------------
  1014. #  This sprite is used to display the character.It observes the Game_Character
  1015. #  class and automatically changes sprite conditions.
  1016. #==============================================================================
  1017. class Sprite_Character
  1018.  
  1019.   $@ || alias_method(:zoom_update_character, :update)
  1020.  
  1021.   def update(*args)
  1022.     if @old_character_zoom_x
  1023.       self.zoom_x = @old_character_zoom_x
  1024.       self.zoom_y = @old_character_zoom_y
  1025.     end
  1026.     zoom_update_character(*args)
  1027.     @old_character_zoom_x = self.zoom_x
  1028.     @old_character_zoom_y = self.zoom_y
  1029.     self.zoom_x *= $game_map.zoom_x
  1030.     self.zoom_y *= $game_map.zoom_y
  1031.   end
  1032. end
  1033.  
  1034. #------------------------------------------------------------------------------
  1035. $resolution = Resolution.new
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top