Guest User

Mode 7

a guest
Jul 19th, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 81.42 KB | None | 0 0
  1. #==============================================================================
  2. # Mode 7
  3. # Written by: MGCaladtogel
  4. # Version: unknown
  5. # English version date: 21.5.2007
  6. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  7. # - instruction rewritten by Blizzard for easier understanding.
  8. # - slightly optimized by Blizzard
  9. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  10. #
  11. # Introduction:
  12. #
  13. #   This script can display maps in a type of 3D with depth. It has a low lag
  14. #   factor.
  15. #
  16. #
  17. # Instructions:
  18. #
  19. #   In the editor in the lower left corner is the map list of the maps you
  20. #   are using in your game. You have several options: If you want to make a
  21. #   map use Mode 7 you need to ADD one or more of these text commands to the
  22. #   map's name. Those commands should not appear in the map's name if using
  23. #   a location display script. The options you have are the following:
  24. #  
  25. #   [M7]  : to activate Mode7
  26. #   [#XX] : XX is the slant angle (in degree). Default value is 0 (normal maps)
  27. #   [Y]   : Y-map looping
  28. #   [X]   : X-map looping. This option needs resources (lower fps).
  29. #   [A]   : animated autotiles (with 4 patterns). This option increases
  30. #           significantly the loading time, so it may crash for large maps
  31. #           (SystemStackError)
  32. #   [C]   : to center the map on the hero (even for small maps)
  33. #   [P]   : to have a fixed panorama
  34. #   [H]   : to have a white horizon
  35. #   [OV]  : Overworld Sprite Resize (a Mewsterus's script feature)
  36. #  
  37. #   Alternatively you can define prepared settings that will be triggered with
  38. #   every map that has that specific text included in its name. See the
  39. #   "MODE7_SETTINGS" below to prepare your settings.
  40. #  
  41. #  
  42. # Control commands:
  43. #  
  44. #   You can change the settings on the map in-game and use a couple of
  45. #   additional commands. If you want to use one of those commands, use a "Call
  46. #   Script" event command and type one of the following commands into the text
  47. #   input window:
  48. #  
  49. #   1. $scene.spriteset.tilemap.mode7_set(ANGLE)
  50. #   2. $scene.spriteset.tilemap.mode7_set_p(ANGLE)
  51. #   3. $scene.spriteset.tilemap.mode7_redraw
  52. #   4. $game_system.map_opacity = VALUE
  53. #   5. $game_system.map_gradual_opacity = VALUE
  54. #   6. $game_system.map_tone = Color.new(RED, GREEN, BLUE)
  55. #   7. $game_system.map_gradual_tone = Tone.new(RED, GREEN, BLUE, GREY)
  56. #   8. $game_system.horizon = VALUE
  57. #   9. $game_system.reset
  58. #  
  59. #   1. Redraws the map with a new angle which is specified by ANGLE
  60. #   2. Redraws the map progressively with a new angle which is specified by
  61. #      ANGLE
  62. #   3. Redraws the map (can be useful with the following commands)
  63. #   4. Defines the opacity for Mode7 maps (it needs to redraw)
  64. #   5. Defines a gradual opacity for Mode7 maps (it needs to redraw)
  65. #      (it bugs with horizontal looping)
  66. #   6. Defines the tone for Mode7 maps (it needs to redraw)
  67. #   7. Defines a gradual tone for Mode7 maps (it needs to redraw)
  68. #   8. Defines the view's distance (default : 960) (it needs to redraw)
  69. #   9. Re-initialize the previous options
  70. #  
  71. #  
  72. # Additional commands:
  73. #  
  74. #   1) If you wish to obtain flat events, add a comment in the event's code
  75. #      and type in the word "Flat" without the double quotes).
  76. #   2) You can handle the height of vertical events by adding a comment to the
  77. #      event's code with the text "Height X" (without the double quotes).
  78. #      Replace X with the height value. Example: If you use Height 1.5, then
  79. #      the event will appear floating above its position in a height of 1.5 map
  80. #      squares (48 pixels).
  81. #  
  82. #==============================================================================
  83.  
  84. # hash for predefined settings
  85. MODE7_SETTINGS = {}
  86. # access for map names
  87. $data_maps = load_data("Data/MapInfos.rxdata")
  88.  
  89. #---------------------#
  90. # START Configuration #
  91. #---------------------#
  92.  
  93. # The map is drawn from all the tiles of the three layers. You can define tiles
  94. # which are not being drawn flat, but vertical which creates the impression
  95. # that the objects would be standing upright.
  96. # To define such tiles, add one or more terrain tags to this array and separate
  97. # them with commas. In your tileset database gives those specific tiles one of
  98. # those terrain tags and the tile will be drawn vertically.
  99. VERTICAL_TILE_TERRAIN_TAGS = [1, 2, 3]
  100.  
  101. #   You can create packages of settings which are automatically triggered if a
  102. #   map name includes the text corresponding to the setting. Use following
  103. #   template to create such settings:
  104. #  
  105. #     MODE7_SETTINGS['CORRESPONDING_TEXT'] = ['SETTING_1', 'SETTING_2', ...]
  106. #  
  107. #   CORRESPONDING_TEXT - text in map name
  108. #   SETTING            - one of the settings from the instructions WITHOUT the
  109. #                        [ and ] brackets (i.e. instead of [H], use just H)
  110. #  
  111. #   You can add as many settings as you want. There are two predefined settings
  112. #   to make you understand easier how it works.
  113.  
  114. MODE7_SETTINGS['World Map'] = ['#60', 'X', 'Y', 'H', 'P']
  115. MODE7_SETTINGS['Smallslant'] = ['#20', 'A', 'S']
  116. MODE7_SETTINGS['Las'] = ['#60']
  117. #---------------------#
  118. #  END Configuration  #
  119. #---------------------#
  120.  
  121. #============================================================================
  122. # ■ Game_System
  123. #----------------------------------------------------------------------------
  124. # Add attributes to this class
  125. #============================================================================
  126.  
  127. class Game_System
  128.   attr_accessor :mode7 # false : normal map / true : mode 7
  129.   attr_accessor :loop_x # true : horizontal-looping map
  130.   attr_accessor :loop_y # true : vertical-looping map
  131.   attr_accessor :always_scroll # true : to center the camera around the hero
  132.   attr_accessor :map_tone # mode7 map's tone (Color)
  133.   attr_accessor :map_opacity # mode7 map's opacity (0..255)
  134.   attr_accessor :animated # true : animated autotiles for mode7 maps
  135.   attr_accessor :white_horizon # true : white line horizon for mode7 maps
  136.   attr_accessor :angle # mode7 map's slant angle (in degree)
  137.   attr_accessor :horizon # horizon's distance
  138.   attr_accessor :fixed_panorama # true : to fix the panorama (no scrolling any more)
  139.   attr_accessor :ov # true : Overworld Sprite Resize (smaller hero's sprite)
  140.   attr_accessor :ov_zoom # resize's value with ov
  141.   attr_accessor :map_gradual_opacity # mode7 map's gradual opacity (0..255)
  142.   attr_accessor :map_gradual_tone # mode7 map's gradual tone (Color)
  143.   #--------------------------------------------------------------------------
  144.   # * Object Initialization
  145.   #--------------------------------------------------------------------------
  146.   alias initialize_mode7_game_system initialize
  147.   def initialize
  148.     initialize_mode7_game_system
  149.     init_mode7
  150.   end
  151.   #--------------------------------------------------------------------------
  152.   # * Mode 7 Initialization
  153.   #--------------------------------------------------------------------------
  154.   def init_mode7
  155.     self.mode7 = true
  156.     self.loop_x = false
  157.     self.loop_y = false
  158.     self.always_scroll = false
  159.     self.animated = false
  160.     self.white_horizon = false
  161.     self.angle = 0
  162.     self.fixed_panorama = false
  163.     self.ov = false
  164.     self.ov_zoom = 0.6
  165.     reset
  166.   end
  167.   #--------------------------------------------------------------------------
  168.   # * Reset the values for opacity, tone and horizon's distance
  169.   #--------------------------------------------------------------------------
  170.   def reset
  171.     self.map_opacity = 255
  172.     self.map_tone = Color.new(0,0,0,0)
  173.     self.horizon = 960 # default value, equivalent to 30 tiles
  174.     self.map_gradual_opacity = 0
  175.     self.map_gradual_tone = Tone.new(0,0,0,0)
  176.   end
  177. end
  178.  
  179. #============================================================================
  180. # ■ Tilemap_mode7
  181. #----------------------------------------------------------------------------
  182. # This new Tilemap class handles the drawing of a mode7 map
  183. #============================================================================
  184.  
  185. class Tilemap_mode7
  186.   attr_accessor  :maps_list # contains map's graphics
  187.   attr_accessor  :map_ground # original map's graphic to handle flat events
  188.   attr_accessor  :tone_values # tone values for each line (Hash)
  189.   attr_accessor  :opacity_values # opacity values for each line (Hash)
  190.   #--------------------------------------------------------------------------
  191.   # * Object Initialization
  192.   #     viewport  : viewport
  193.   #--------------------------------------------------------------------------
  194.   def initialize(viewport)
  195.     @id = $game_map.map_id # map's ID : to load or save the map in Cache
  196.     @maps_list = [] # contains map's drawings (Bitmap)
  197.     @disp_y = $game_map.display_y # @disp_y : tilemap's display_y
  198.     @disp_x = $game_map.display_x # @disp_x : tilemap's display_x
  199.     @height = 32 * $game_map.height # @height : map's height (in pixel)
  200.     @width = 32 * $game_map.width # @width : map's width (in pixel)
  201.     $game_temp.height = @height
  202.     # map's drawings are loaded if already in Cache
  203.     if RPG::Cache_Carte.in_cache(@id)
  204.       @map = RPG::Cache_Carte.load(@id)
  205.       @maps_list.push(@map)
  206.       @map_ground = RPG::Cache_Carte.load(@id, 4) # to handle flat events
  207.       if $game_system.animated
  208.         @map_2 = RPG::Cache_Carte.load(@id, 1)
  209.         @map_3 = RPG::Cache_Carte.load(@id, 2)
  210.         @map_4 = RPG::Cache_Carte.load(@id, 3)
  211.         @maps_list.push(@map_2)
  212.         @maps_list.push(@map_3)
  213.         @maps_list.push(@map_4)
  214.       end
  215.     else # draw the map and save it in the Cache
  216.       draw_map
  217.     end
  218.     # create vertical elements from tiles
  219.     data_V = Data_Vertical_Sprites.new(viewport)
  220.     # @sprites_V : list of vertical sprites (Sprite_V)
  221.     @sprites_V = data_V.list_sprites_V
  222.     # @sprites_V_animated : list of animated vertical sprites (Sprite_V)
  223.     @sprites_V_animated = data_V.list_sprites_V_animated
  224.     @angle = $game_system.angle # map's slant angle (in degree)
  225.     @distance_h = 480 # distance between the map's center and the vanishing point
  226.     @pivot = 256 # screenline's number of the slant's pivot
  227.     @index_animated = 0 # 0..3 : index of animated tiles pattern
  228.     @viewport = viewport
  229.     @tone_values = {} # list of the tone values for each line
  230.     @opacity_values = {} # list of the opacity values for each line
  231.     init_sprites(@angle) # initialize screenlines sprites
  232.   end
  233.   #--------------------------------------------------------------------------
  234.   # * Dispose
  235.   #--------------------------------------------------------------------------
  236.   def dispose
  237.     # dispose of @sprites (scanlines), @sprites_V (vertical_sprites), and
  238.     # @sprites_loop_x (additional scanlines for horizontal looping)
  239.     (@sprites + @sprites_V + @sprites_loop_x).each {|sprite| sprite.dispose}
  240.     [@sprites, @sprites_V, @sprites_loop_x, @sprites_V_animated,
  241.         @maps_list].each {|obj| obj.clear}
  242.     $game_system.angle = @angle
  243.   end
  244.   #--------------------------------------------------------------------------
  245.   # * Increase slant's angle
  246.   #--------------------------------------------------------------------------
  247.   def increase_angle
  248.     return if @angle == 88
  249.     @angle += 2
  250.     @angle = 88 if @angle > 88
  251.     @sprites.clear
  252.     @sprites_loop_x.clear
  253.     init_sprites(@angle) # reinitialize screenlines sprites
  254.   end
  255.   #--------------------------------------------------------------------------
  256.   # * Decrease slant's angle
  257.   #--------------------------------------------------------------------------
  258.   def decrease_angle
  259.     return if @angle == 0
  260.     @angle -= 2
  261.     @angle = 0 if @angle < 0
  262.     @sprites.clear
  263.     @sprites_loop_x.clear
  264.     init_sprites(@angle) # reinitialize screenlines sprites
  265.   end
  266.   #--------------------------------------------------------------------------
  267.   # * Slide from the current angle into the target value
  268.   #     value  : target angle's value (in degree)
  269.   #--------------------------------------------------------------------------
  270.   def mode7_set_p(value)
  271.     while value > @angle
  272.       increase_angle
  273.       update
  274.       Graphics.update
  275.     end
  276.     while value < @angle
  277.       decrease_angle
  278.       update
  279.       Graphics.update
  280.     end
  281.   end
  282.   #--------------------------------------------------------------------------
  283.   # * Redraw the map instantaneously with the new slant angle's value
  284.   #     value  : target angle's value (in degree)
  285.   #--------------------------------------------------------------------------
  286.   def mode7_set(value)
  287.     if value < 0
  288.       @angle = 0
  289.     elsif value > 89
  290.       @angle = 89
  291.     else
  292.       @angle = value
  293.     end
  294.     @sprites.clear
  295.     @sprites_loop_x.clear
  296.     init_sprites(@angle) # reinitialize screenlines sprites
  297.     update
  298.     Graphics.update
  299.   end
  300.   #--------------------------------------------------------------------------
  301.   # * Reinitialize screenlines sprites
  302.   #--------------------------------------------------------------------------
  303.   def mode7_redraw
  304.     @sprites.clear
  305.     @sprites_loop_x.clear
  306.     init_sprites(@angle) # reinitialize scanlines
  307.     update
  308.     Graphics.update
  309.   end
  310.   #--------------------------------------------------------------------------
  311.   # * Create sprites equivalent to scanlines
  312.   #     value  : target angle's value (in degree)
  313.   #--------------------------------------------------------------------------
  314.   def init_sprites(angle)
  315.     @horizon = $game_system.horizon
  316.     angle_rad = (Math::PI * angle) / 180 # angle in radian
  317.     @sprites = [] # list of the scanlines sprites (Sprite)
  318.     @sprites_loop_x = [] # list of the additionnal sprites (for X-looping)
  319.     cos_angle = Math.cos(angle_rad)
  320.     sin_angle = Math.sin(angle_rad)
  321.     # save values in $game_temp
  322.     $game_temp.distance_h = @distance_h
  323.     $game_temp.pivot = @pivot
  324.     $game_temp.cos_angle = cos_angle
  325.     $game_temp.sin_angle = sin_angle
  326.     # h0, z0 : intermediate values
  327.     h0 = (- @distance_h * @pivot * cos_angle).to_f /
  328.     (@distance_h + @pivot * sin_angle) + @pivot
  329.     z0 = @distance_h.to_f / (@distance_h + @pivot * sin_angle)
  330.     $game_temp.slope_value = (1.0 - z0) / (@pivot - h0)
  331.     $game_temp.corrective_value = 1.0 - @pivot * $game_temp.slope_value
  332.     last_line = - @pivot - @horizon # last_line : the highest line that is drawn
  333.     height_limit = (@distance_h * last_line * cos_angle).to_f /
  334.     (@distance_h - last_line * sin_angle) + @pivot # the line corresponding to
  335.     # the last_line in the warped reference = horizon's line
  336.     $game_temp.height_limit = height_limit
  337.     # constant to handle gradual opacity
  338.     k2lim = ((@distance_h * last_line).to_f /
  339.       (@distance_h * cos_angle + last_line * sin_angle)).to_i
  340.     # one sprite is created for each screenline
  341.     (0..479).each {|j|
  342.         next if j < height_limit # if the line is further than the horizon's line,
  343.         # no sprite is created
  344.         i = j - @pivot # y-reference is the pivot's line
  345.         sprite = Sprite.new(@viewport)
  346.         sprite.x = 320 # x-reference is the vertical line in the middle of the screen
  347.         sprite.y = j
  348.         sprite.z = - 99999 # map must not mask vertical elements
  349.         sprite.y_origin_bitmap = (@distance_h * i).to_f /
  350.         (@distance_h * cos_angle + i * sin_angle) + @pivot
  351.         sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap + 0.5).to_i
  352.         sprite.y_origin_bitmap_i %= @height if $game_system.loop_y
  353.         sprite.zoom_x = $game_temp.slope_value * j + $game_temp.corrective_value
  354.         sprite.length = 2 + (640.to_f / sprite.zoom_x).to_i
  355.         sprite.x_origin_bitmap_i = ((642 - sprite.length) / 2)
  356.         sprite.x_origin_bitmap_i %= @width if $game_system.loop_x
  357.         sprite.x_origin_bitmap = (sprite.x_origin_bitmap_i).to_f
  358.         sprite.ox = sprite.length / 2
  359.         sprite.bitmap = @map
  360.         # horizontal translation to center around the hero
  361.         if @disp_x != 0
  362.           sprite.x_origin_bitmap += @disp_x / 4
  363.           sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i
  364.           sprite.x_origin_bitmap_i %= @width if $game_system.loop_x
  365.         end
  366.         # vertical translation to center around the hero
  367.         if @disp_y != 0
  368.           sprite.y_origin_bitmap += @disp_y / 4
  369.           sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap + 0.5).to_i
  370.           sprite.y_origin_bitmap_i %= @height if $game_system.loop_y
  371.         end
  372.         # handle opacity and tone
  373.         k2 = ((@distance_h * i).to_f /
  374.         (@distance_h * cos_angle + i * sin_angle)).to_i
  375.         k2 = 0 if k2 > 0
  376.         k_red = (- k2.to_f/k2lim * $game_system.map_gradual_tone.red).to_i
  377.         k_green = (- k2.to_f/k2lim * $game_system.map_gradual_tone.green).to_i
  378.         k_blue = (- k2.to_f/k2lim * $game_system.map_gradual_tone.blue).to_i
  379.         k_gray = (- k2.to_f/k2lim * $game_system.map_gradual_tone.gray).to_i
  380.         k2 = (- k2.to_f/k2lim * $game_system.map_gradual_opacity).to_i
  381.         sprite.tone = Tone.new(k_red, k_green, k_blue, k_gray)
  382.         sprite.opacity = 255 - k2
  383.         sprite.opacity *= ($game_system.map_opacity).to_f / 255
  384.         sprite.color = $game_system.map_tone
  385.         # white horizon's line
  386.         k = 500 / (j - height_limit)
  387.         if $game_system.white_horizon
  388.           tone_red = sprite.tone.red + k
  389.           tone_green = sprite.tone.green + k
  390.           tone_blue = sprite.tone.blue + k
  391.           tone_gray = sprite.tone.gray + k
  392.           sprite.tone = Tone.new(tone_red, tone_green, tone_blue, tone_gray)
  393.         end
  394.         @tone_values[j] = sprite.tone
  395.         @opacity_values[j] = sprite.opacity
  396.         # set sprite's graphics
  397.         sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  398.         sprite.length, 1)
  399.         @sprites.push(sprite)
  400.         if $game_system.loop_x && j < @pivot
  401.           # additional sprite to handle horizontal looping
  402.           sprite2 = Sprite.new(@viewport)
  403.           sprite2.x = 320
  404.           sprite2.y = j
  405.           sprite2.z = - 99999
  406.           sprite2.y_origin_bitmap = sprite.y_origin_bitmap
  407.           sprite2.y_origin_bitmap_i = sprite.y_origin_bitmap_i
  408.           sprite2.zoom_x = sprite.zoom_x
  409.           sprite2.length = sprite.length
  410.           sprite2.x_origin_bitmap_i = sprite.x_origin_bitmap_i - @width
  411.           sprite2.x_origin_bitmap = sprite.x_origin_bitmap_i - @width
  412.           sprite2.ox = sprite.ox
  413.           sprite2.bitmap = @map
  414.           sprite2.opacity = sprite.opacity
  415.           sprite2.color = sprite.color
  416.           sprite2.tone = sprite.tone
  417.           sprite2.src_rect.set(sprite2.x_origin_bitmap_i, sprite2.y_origin_bitmap_i,
  418.           sprite2.length, 1)
  419.           @sprites_loop_x.push(sprite2)
  420.         end}
  421.   end
  422.   #--------------------------------------------------------------------------
  423.   # * Update the screenlines sprites and the vertical sprites
  424.   #   compare tilemap's display with map's display
  425.   #--------------------------------------------------------------------------
  426.   def update
  427.     # update screenlines sprites
  428.     if @disp_y < $game_map.display_y
  429.       difference = $game_map.display_y - @disp_y
  430.       @disp_y += difference
  431.       (@sprites + @sprites_loop_x).each {|sprite|
  432.           sprite.y_origin_bitmap += difference.to_f / 4
  433.           sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap+0.5).to_i
  434.           sprite.y_origin_bitmap_i %= @height if $game_system.loop_y
  435.           sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  436.           sprite.length, 1)}
  437.     end
  438.     if @disp_y > $game_map.display_y
  439.       difference = @disp_y - $game_map.display_y
  440.       @disp_y -= difference
  441.       (@sprites + @sprites_loop_x).each {|sprite|
  442.           sprite.y_origin_bitmap -= difference.to_f / 4
  443.           sprite.y_origin_bitmap_i = (sprite.y_origin_bitmap+0.5).to_i
  444.           sprite.y_origin_bitmap_i %= @height if $game_system.loop_y
  445.           sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  446.           sprite.length, 1)}
  447.     end
  448.     if @disp_x < $game_map.display_x
  449.       difference = $game_map.display_x - @disp_x
  450.       @disp_x += difference
  451.       @sprites.each {|sprite|
  452.           sprite.x_origin_bitmap += difference.to_f / 4
  453.           sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i
  454.           sprite.x_origin_bitmap_i %= @width if $game_system.loop_x
  455.           sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  456.           sprite.length, 1)}
  457.       @sprites_loop_x.each {|sprite|
  458.           sprite.x_origin_bitmap += difference.to_f / 4
  459.           sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i
  460.           sprite.x_origin_bitmap_i %= @width
  461.           sprite.x_origin_bitmap_i -= @width
  462.           sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  463.           sprite.length, 1)}
  464.     end
  465.     if @disp_x > $game_map.display_x
  466.       difference = @disp_x - $game_map.display_x
  467.       @disp_x -= difference
  468.       @sprites.each {|sprite|
  469.           sprite.x_origin_bitmap -= difference.to_f / 4
  470.           sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i
  471.           sprite.x_origin_bitmap_i %= @width if $game_system.loop_x
  472.           sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  473.           sprite.length, 1)}
  474.       @sprites_loop_x.each {|sprite|
  475.           sprite.x_origin_bitmap -= difference.to_f / 4
  476.           sprite.x_origin_bitmap_i = (sprite.x_origin_bitmap).to_i
  477.           sprite.x_origin_bitmap_i %= @width
  478.           sprite.x_origin_bitmap_i -= @width
  479.           sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  480.           sprite.length, 1)}
  481.     end
  482.     # update vertical sprites
  483.     @sprites_V.each {|sprite| sprite.update}
  484.   end
  485.   #--------------------------------------------------------------------------
  486.   # * Update animation for animated tiles
  487.   #--------------------------------------------------------------------------
  488.   def update_animated
  489.     @index_animated += 1
  490.     @index_animated %= 4
  491.     map = @maps_list[@index_animated]
  492.     # update screenlines sprites
  493.     (@sprites + @sprites_loop_x).each {|sprite|
  494.         sprite.bitmap = map
  495.         sprite.src_rect.set(sprite.x_origin_bitmap_i, sprite.y_origin_bitmap_i,
  496.         sprite.length, 1)}
  497.     # update vertical sprites
  498.     @sprites_V_animated.each {|sprite| sprite.update_animated(@index_animated)}
  499.   end
  500.   #--------------------------------------------------------------------------
  501.   # * Create bitmaps representing the map
  502.   #--------------------------------------------------------------------------
  503.   def draw_map
  504.     data = $game_map.data
  505.     # Table where animated tiles are flagged
  506.     data_animated = Table.new($game_map.width, $game_map.height)
  507.     # bigger maps to handle horizontal looping
  508.     offset = ($game_system.loop_x ? 640 : 0)
  509.     @map = Bitmap.new(@width + offset, @height)
  510.     @maps_list.push(@map)
  511.     rect = Rect.new(0, 0, 32, 32)
  512.     # create autotiles graphics
  513.     RPG::Cache.clear
  514.     @autotiles = []
  515.     (0..6).each {|i|
  516.         autotile_name = $game_map.autotile_names[i]
  517.         fichier = RPG::Cache.autotile(autotile_name)
  518.         (0..3).each {|l|
  519.             data_autotile = Data_Autotiles.new(fichier,l)
  520.             data_autotile.number = 4*i + l
  521.             RPG::Cache.save_autotile(data_autotile, data_autotile.number)
  522.             @autotiles.push(data_autotile)}}
  523.     # scan map's data to draw it
  524.     (0...$game_map.height).each {|i| (0...$game_map.width).each {|j|
  525.         data_animated[j, i] = 0
  526.         # tile's ID for the first layer
  527.         value1 = data[j, i, 0].to_i
  528.         # prevent from drawing a vertical tile
  529.         value1 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value1]) ?
  530.         0 : value1)
  531.         # value1 != 0
  532.         if value1 != 0
  533.           # tile's ID for the second layer
  534.           value2 = data[j, i, 1].to_i
  535.           # prevent from drawing a vertical tile
  536.           value2 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value2]) ?
  537.           0 : value2)
  538.           # tile's ID for the third layer
  539.           value3 = data[j, i, 2].to_i
  540.           # prevent from drawing a vertical tile
  541.           value3 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?
  542.           0 : value3)
  543.           # value1 != 0, value2 = 0
  544.           if value2 == 0
  545.             # value1 != 0, value2 = 0, value3 = 0
  546.             if value3 == 0
  547.               # value1 associated with a normal autotile
  548.               if value1 > 383
  549.                 bitmap = RPG::Cache.tile($game_map.tileset_name, value1, 0)
  550.                 @map.blt(32*j, 32*i, bitmap, rect)
  551.                 if $game_system.loop_x && j.between?(0, 19)
  552.                   @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  553.                 end
  554.               # value1 associated with an autotile
  555.               else
  556.                 num = 4*((value1 / 48) - 1)
  557.                 bitmap = RPG::Cache.autotile_base(num, value1)
  558.                 if @autotiles[num].animated
  559.                   data_animated[j, i] = 1
  560.                 end
  561.                 @map.blt(32*j, 32*i, bitmap, rect)
  562.                 if $game_system.loop_x && j.between?(0, 19)
  563.                   @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  564.                 end
  565.               end
  566.             # value1 != 0, value2 = 0, value3 != 0
  567.             else
  568.               bitmap = RPG::Cache_Tile.load(value1, value3)
  569.               # value1 associated with an autotile
  570.               if value1 < 384
  571.                 num = 4*((value1 / 48) - 1)
  572.                 data_animated[j, i] = 1 if @autotiles[num].animated
  573.               end
  574.               # value3 associated with an autotile
  575.               if value3 < 384
  576.                 num = 4*((value3 / 48) - 1)
  577.                 data_animated[j, i] = 1 if @autotiles[num].animated
  578.               end
  579.               @map.blt(32*j, 32*i, bitmap, rect)
  580.               if $game_system.loop_x && j.between?(0, 19)
  581.                 @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  582.               end
  583.             end
  584.           # value1 != 0, value2 != 0, value3 = 0
  585.           elsif value3 == 0
  586.             bitmap = RPG::Cache_Tile.load(value1, value2)
  587.             # value1 associated with an autotile
  588.             if value1 < 384
  589.               num = 4*((value1 / 48) - 1)
  590.               data_animated[j, i] = 1 if @autotiles[num].animated
  591.             end
  592.             # value2 associated with an autotile
  593.             if value2 < 384
  594.               num = 4*((value2 / 48) - 1)
  595.               data_animated[j, i] = 1 if @autotiles[num].animated
  596.             end
  597.             @map.blt(32*j, 32*i, bitmap, rect)
  598.             if $game_system.loop_x && j.between?(0, 19)
  599.               @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  600.             end
  601.           # value1 != 0, value2 != 0, value3 != 0
  602.           else
  603.             bitmap = RPG::Cache_Tile.load2(value1, value2, value3)
  604.             # value1 associated with an autotile
  605.             if value1 < 384
  606.               num = 4*((value1 / 48) - 1)
  607.               data_animated[j, i] = 1 if @autotiles[num].animated
  608.             end
  609.             # value2 associated with an autotile
  610.             if value2 < 384
  611.               num = 4*((value2 / 48) - 1)
  612.               data_animated[j, i] = 1 if @autotiles[num].animated
  613.             end
  614.             # value3 associated with an autotile
  615.             if value3 < 384
  616.               num = 4*((value3 / 48) - 1)
  617.               data_animated[j, i] = 1 if @autotiles[num].animated
  618.             end
  619.             @map.blt(32*j, 32*i, bitmap, rect)
  620.             if $game_system.loop_x && j.between?(0, 19)
  621.               @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  622.             end
  623.           end
  624.         # value1 = 0
  625.         else
  626.           value2 = data[j, i, 1].to_i
  627.           value2 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value2]) ?
  628.           0 : value2)
  629.           value3 = data[j, i, 2].to_i
  630.           value3 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?
  631.           0 : value3)
  632.           # value1 = 0, value2 = 0
  633.           if value2 == 0
  634.             # value1 = 0, value2 = 0, value3 != 0
  635.             if value3 != 0
  636.               # value3 associated with a normal tile
  637.               if value3 > 383
  638.                 bitmap = RPG::Cache.tile($game_map.tileset_name, value3, 0)
  639.                 @map.blt(32*j, 32*i, bitmap, rect)
  640.                 if $game_system.loop_x && j.between?(0, 19)
  641.                   @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  642.                 end
  643.               # value3 associated with an autotile
  644.               else
  645.                 num = 4*((value3 / 48) - 1)
  646.                 bitmap = RPG::Cache.autotile_base(num, value3)
  647.                 if @autotiles[num].animated
  648.                   data_animated[j, i] = 1
  649.                 end
  650.                 @map.blt(32*j, 32*i, bitmap, rect)
  651.                 if $game_system.loop_x && j.between?(0, 19)
  652.                   @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  653.                 end
  654.               end
  655.             end
  656.           # value1 = 0, value2 != 0, value3 = 0
  657.           elsif value3 == 0
  658.             # value2 associated with a normal tile
  659.             if value2 > 383
  660.               bitmap = RPG::Cache.tile($game_map.tileset_name, value2, 0)
  661.               @map.blt(32*j, 32*i, bitmap, rect)
  662.               if $game_system.loop_x && j.between?(0, 19)
  663.                 @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  664.               end
  665.             # value2 associated with an autotile
  666.             else
  667.               num = 4*((value2 / 48) - 1)
  668.               bitmap = RPG::Cache.autotile_base(num, value2)
  669.               if @autotiles[num].animated
  670.                 data_animated[j, i] = 1
  671.               end
  672.               @map.blt(32*j, 32*i, bitmap, rect)
  673.               if $game_system.loop_x && j.between?(0, 19)
  674.                 @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  675.               end
  676.             end
  677.           # value1 = 0, value2 != 0, value3 != 0
  678.           else
  679.             bitmap = RPG::Cache_Tile.load(value2, value3)
  680.             # value2 associated with an autotile
  681.             if value2 < 384
  682.               num = 4*((value2 / 48) - 1)
  683.               data_animated[j, i] = 1 if @autotiles[num].animated
  684.             end
  685.             # value3 associated with an autotile
  686.             if value3 < 384
  687.               num = 4*((value3 / 48) - 1)
  688.               data_animated[j, i] = 1 if @autotiles[num].animated
  689.             end
  690.             @map.blt(32*j, 32*i, bitmap, rect)
  691.             if $game_system.loop_x && j.between?(0, 19)
  692.               @map.blt(32*(j+$game_map.width), 32*i, bitmap, rect)
  693.             end
  694.           end
  695.         end}}
  696.     # save the map's drawing in the Cache
  697.     RPG::Cache_Carte.save(@id, @map)
  698.     @map_ground = @map.clone
  699.     # save a copy of the map to handle flat events
  700.     RPG::Cache_Carte.save(@id, @map_ground, 4)
  701.     return if !$game_system.animated
  702.     # create 3 other maps in case of animated tiles
  703.     @map_2 = @map.clone
  704.     @map_3 = @map.clone
  705.     @map_4 = @map.clone
  706.     @maps_list.push(@map_2)
  707.     @maps_list.push(@map_3)
  708.     @maps_list.push(@map_4)
  709.     (0...$game_map.height).each {|i| (0...$game_map.width).each {|j|
  710.         next if data_animated[j, i].to_i == 0
  711.         # modify the tile if it is flagged as animated
  712.         value1 = data[j, i, 0].to_i
  713.         value2 = data[j, i, 1].to_i
  714.         value3 = data[j, i, 2].to_i
  715.         # prevent from drawing a vertical tile
  716.         value1 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?
  717.         0 : value3)
  718.         value2 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?
  719.         0 : value3)
  720.         value3 = (VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value3]) ?
  721.         0 : value3)
  722.         if value1 != 0
  723.           if value2 == 0
  724.             if value3 == 0
  725.               num = 4*((value1 / 48) - 1)
  726.               bitmap_2 = RPG::Cache.autotile_base(num+1, value1)
  727.               bitmap_3 = RPG::Cache.autotile_base(num+2, value1)
  728.               bitmap_4 = RPG::Cache.autotile_base(num+3, value1)
  729.               @map_2.blt(32*j, 32*i, bitmap_2, rect)
  730.               @map_3.blt(32*j, 32*i, bitmap_3, rect)
  731.               @map_4.blt(32*j, 32*i, bitmap_4, rect)
  732.               if $game_system.loop_x && j.between?(0, 19)
  733.                 @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  734.                 @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  735.                 @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  736.               end
  737.             else
  738.               bitmap_2 = RPG::Cache_Tile.load(value1, value3, 1)
  739.               bitmap_3 = RPG::Cache_Tile.load(value1, value3, 2)
  740.               bitmap_4 = RPG::Cache_Tile.load(value1, value3, 3)
  741.               @map_2.blt(32*j, 32*i, bitmap_2, rect)
  742.               @map_3.blt(32*j, 32*i, bitmap_3, rect)
  743.               @map_4.blt(32*j, 32*i, bitmap_4, rect)
  744.               if $game_system.loop_x && j.between?(0, 19)
  745.                 @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  746.                 @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  747.                 @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  748.               end
  749.             end
  750.           elsif value3 == 0
  751.             bitmap_2 = RPG::Cache_Tile.load(value1, value2, 1)
  752.             bitmap_3 = RPG::Cache_Tile.load(value1, value2, 2)
  753.             bitmap_4 = RPG::Cache_Tile.load(value1, value2, 3)
  754.             @map_2.blt(32*j, 32*i, bitmap_2, rect)
  755.             @map_3.blt(32*j, 32*i, bitmap_3, rect)
  756.             @map_4.blt(32*j, 32*i, bitmap_4, rect)
  757.             if $game_system.loop_x && j.between?(0, 19)
  758.               @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  759.               @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  760.               @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  761.             end
  762.           else
  763.             bitmap_2 = RPG::Cache_Tile.load2(value1, value2, value3, 1)
  764.             bitmap_3 = RPG::Cache_Tile.load2(value1, value2, value3, 2)
  765.             bitmap_4 = RPG::Cache_Tile.load2(value1, value2, value3, 3)
  766.             @map_2.blt(32*j, 32*i, bitmap_2, rect)
  767.             @map_3.blt(32*j, 32*i, bitmap_3, rect)
  768.             @map_4.blt(32*j, 32*i, bitmap_4, rect)
  769.             if $game_system.loop_x && j.between?(0, 19)
  770.               @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  771.               @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  772.               @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  773.             end
  774.           end
  775.         elsif value2 != 0
  776.           if value3 == 0
  777.             num = 4*((value2 / 48) - 1)
  778.             bitmap_2 = RPG::Cache.autotile_base(num+1, value2)
  779.             bitmap_3 = RPG::Cache.autotile_base(num+2, value2)
  780.             bitmap_4 = RPG::Cache.autotile_base(num+3, value2)
  781.             @map_2.blt(32*j, 32*i, bitmap_2, rect)
  782.             @map_3.blt(32*j, 32*i, bitmap_3, rect)
  783.             @map_4.blt(32*j, 32*i, bitmap_4, rect)
  784.             if $game_system.loop_x && j.between?(0, 19)
  785.               @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  786.               @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  787.               @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  788.             end
  789.           else
  790.             bitmap_2 = RPG::Cache_Tile.load(value2, value3, 1)
  791.             bitmap_3 = RPG::Cache_Tile.load(value2, value3, 2)
  792.             bitmap_4 = RPG::Cache_Tile.load(value2, value3, 3)
  793.             @map_2.blt(32*j, 32*i, bitmap_2, rect)
  794.             @map_3.blt(32*j, 32*i, bitmap_3, rect)
  795.             @map_4.blt(32*j, 32*i, bitmap_4, rect)
  796.             if $game_system.loop_x && j.between?(0, 19)
  797.               @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  798.               @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  799.               @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  800.             end
  801.           end
  802.         elsif value3 != 0
  803.           num = 4*((value3 / 48) - 1)
  804.           bitmap_2 = RPG::Cache.autotile_base(num+1, value3)
  805.           bitmap_3 = RPG::Cache.autotile_base(num+2, value3)
  806.           bitmap_4 = RPG::Cache.autotile_base(num+3, value3)
  807.           @map_2.blt(32*j, 32*i, bitmap_2, rect)
  808.           @map_3.blt(32*j, 32*i, bitmap_3, rect)
  809.           @map_4.blt(32*j, 32*i, bitmap_4, rect)
  810.           if $game_system.loop_x && j.between?(0, 19)
  811.             @map_2.blt(32*(j+$game_map.width), 32*i, bitmap_2, rect)
  812.             @map_3.blt(32*(j+$game_map.width), 32*i, bitmap_3, rect)
  813.             @map_4.blt(32*(j+$game_map.width), 32*i, bitmap_4, rect)
  814.           end
  815.         end}}
  816.     # save the three additional maps in the Cache
  817.     RPG::Cache_Carte.save(@id, @map_2, 1)
  818.     RPG::Cache_Carte.save(@id, @map_3, 2)
  819.     RPG::Cache_Carte.save(@id, @map_4, 3)
  820.   end
  821. end
  822.  
  823. #============================================================================
  824. # ■ Game_Map
  825. #----------------------------------------------------------------------------
  826. # Methods modifications to handle map looping
  827. #============================================================================
  828.  
  829. class Game_Map
  830.   #--------------------------------------------------------------------------
  831.   # * Scroll Down
  832.   #     distance : scroll distance
  833.   #--------------------------------------------------------------------------
  834.   alias scroll_down_mode7_game_map scroll_down
  835.   def scroll_down(distance)
  836.     if !$game_system.mode7
  837.       scroll_down_mode7_game_map(distance)
  838.       return
  839.     end
  840.     @display_y = @display_y + distance
  841.     unless $game_system.loop_y || $game_system.always_scroll
  842.       height = (self.height - 15) * 128
  843.       @display_y = height if @display_y > height
  844.     end
  845.   end
  846.   #--------------------------------------------------------------------------
  847.   # * Scroll Left
  848.   #     distance : scroll distance
  849.   #--------------------------------------------------------------------------
  850.   alias scroll_left_mode7_game_map scroll_left
  851.   def scroll_left(distance)
  852.     if !$game_system.mode7
  853.       scroll_left_mode7_game_map(distance)
  854.       return
  855.     end
  856.     @display_x = @display_x - distance
  857.     unless $game_system.loop_x || $game_system.always_scroll
  858.       @display_x = 0 if @display_x < 0
  859.     end
  860.   end
  861.   #--------------------------------------------------------------------------
  862.   # * Scroll Right
  863.   #     distance : scroll distance
  864.   #--------------------------------------------------------------------------
  865.   alias scroll_right_mode7_game_map scroll_right
  866.   def scroll_right(distance)
  867.     if !$game_system.mode7
  868.       scroll_right_mode7_game_map(distance)
  869.       return
  870.     end
  871.     @display_x = @display_x + distance
  872.     unless $game_system.loop_x || $game_system.always_scroll
  873.       width = (self.width - 20) * 128
  874.       @display_x = width if @display_x > width
  875.     end
  876.   end
  877.   #--------------------------------------------------------------------------
  878.   # * Scroll Up
  879.   #     distance : scroll distance
  880.   #--------------------------------------------------------------------------
  881.   alias scroll_up_mode7_game_map scroll_up
  882.   def scroll_up(distance)
  883.     if !$game_system.mode7
  884.       scroll_up_mode7_game_map(distance)
  885.       return
  886.     end
  887.     @display_y = @display_y - distance
  888.     unless $game_system.loop_y || $game_system.always_scroll
  889.       @display_y = 0 if @display_y < 0
  890.     end
  891.   end
  892.   #--------------------------------------------------------------------------
  893.   # * Determine Valid Coordinates
  894.   #     x          : x-coordinate
  895.   #     y          : y-coordinate
  896.   #   Allow the hero to go out of the map when map looping
  897.   #--------------------------------------------------------------------------
  898.   alias valid_mode7_game_map? valid?
  899.   def valid?(x, y)
  900.     return (valid_mode7_game_map?(x, y)) if !$game_system.mode7
  901.     if $game_system.loop_x
  902.       return ($game_system.loop_y || y >= 0 && y < height)
  903.     elsif $game_system.loop_y
  904.       return (x >= 0 && x < width)
  905.     end
  906.     return (x >= 0 && x < width && y >= 0 && y < height)
  907.   end
  908.   #--------------------------------------------------------------------------
  909.   # * Determine if Passable
  910.   #     x          : x-coordinate
  911.   #     y          : y-coordinate
  912.   #     d          : direction (0,2,4,6,8,10)
  913.   #                  *  0,10 = determine if all directions are impassable
  914.   #     self_event : Self (If event is determined passable)
  915.   #--------------------------------------------------------------------------
  916.   alias passable_mode7_game_map? passable?
  917.   def passable?(x, y, d, self_event = nil)
  918.     if !$game_system.mode7
  919.       passable_mode7_game_map?(x, y, d, self_event)
  920.       return(passable_mode7_game_map?(x, y, d, self_event))
  921.     end
  922.     return false unless valid?(x, y)
  923.     bit = (1 << (d / 2 - 1)) & 0x0f
  924.     events.each_value {|event|
  925.         if event.tile_id >= 0 && event != self_event &&
  926.            event.x == x && event.y == y && !event.through
  927.           if @passages[event.tile_id] & bit != 0
  928.             return false
  929.           elsif @passages[event.tile_id] & 0x0f == 0x0f
  930.             return false
  931.           elsif @priorities[event.tile_id] == 0
  932.             return true
  933.           end
  934.         end}
  935.     [2, 1, 0].each {|i|
  936.         tile_id = data[x % width, y % height, i] # handle map looping
  937.         if tile_id == nil
  938.           return false
  939.         elsif @passages[tile_id] & bit != 0
  940.           return false
  941.         elsif @passages[tile_id] & 0x0f == 0x0f
  942.           return false
  943.         elsif @priorities[tile_id] == 0
  944.           return true
  945.         end}
  946.     return true
  947.   end
  948. end
  949.  
  950. #============================================================================
  951. # ■ Game_Character
  952. #----------------------------------------------------------------------------
  953. # "update" method modifications to handle map looping
  954. #============================================================================
  955.  
  956. class Game_Character
  957.   attr_accessor :x
  958.   attr_accessor :y
  959.   attr_accessor :real_x
  960.   attr_accessor :real_y
  961.   attr_reader   :flat
  962.   attr_reader   :height
  963.   #--------------------------------------------------------------------------
  964.   # * Object Initialization
  965.   #--------------------------------------------------------------------------
  966.   alias initialize_mode7_game_character initialize
  967.   def initialize
  968.     initialize_mode7_game_character
  969.     init_mode7
  970.   end
  971.   #--------------------------------------------------------------------------
  972.   # * Mode7 Initialization
  973.   #--------------------------------------------------------------------------
  974.   def init_mode7
  975.     @flat = false
  976.     @height = 0.0
  977.   end
  978.   #--------------------------------------------------------------------------
  979.   # * Update
  980.   #--------------------------------------------------------------------------
  981.   alias update_mode7_game_character update
  982.   def update
  983.     if !$game_system.mode7
  984.       update_mode7_game_character
  985.       return
  986.     end
  987.     # if x-coordinate is out of the map
  988.     if !(x.between?(0, $game_map.width - 1))
  989.       difference = 128 * x - real_x
  990.       if self.is_a?(Game_Player)
  991.         # increase or decrease map's number
  992.         self.map_number_x += difference / (difference.abs)
  993.       end
  994.       # x-coordinate is equal to its equivalent in the map
  995.       self.x %= $game_map.width
  996.       self.real_x = 128 * x - difference
  997.     end
  998.     # if y-coordinate is out of the map
  999.     if !(y.between?(0, $game_map.height - 1))
  1000.       difference = 128 * y - real_y
  1001.       if self.is_a?(Game_Player)
  1002.         # increase or decrease map's number
  1003.         self.map_number_y += difference / (difference.abs)
  1004.       end
  1005.       # y-coordinate is equal to its equivalent in the map
  1006.       self.y %= $game_map.height
  1007.       self.real_y = 128 * y - difference
  1008.     end
  1009.     update_mode7_game_character
  1010.   end
  1011. end
  1012.  
  1013. #==============================================================================
  1014. # ■ Game_Event
  1015. #----------------------------------------------------------------------------
  1016. # Add methods to handle flat events and altitude for vertical event
  1017. #============================================================================
  1018.  
  1019. class Game_Event < Game_Character
  1020.   #--------------------------------------------------------------------------
  1021.   # * scan the event's commands list
  1022.   #     page : the scanned page (RPG::Event::Page)
  1023.   #--------------------------------------------------------------------------
  1024.   def check_commands(page)
  1025.     @height = 0.0
  1026.     command_list = page.list
  1027.     (0..command_list.length - 2).each {|k|
  1028.         command = command_list[k]
  1029.         if (command.parameters[0].to_s).include?('Height')
  1030.           @height = (command.parameters[0][7,command.parameters[0].length-1]).to_f
  1031.         end
  1032.         @flat = (command.parameters[0].to_s).include?('Flat')}
  1033.   end
  1034.   #--------------------------------------------------------------------------
  1035.   # * scan the event's commands list of the current page when refreshed
  1036.   #--------------------------------------------------------------------------
  1037.   alias refresh_mode7_game_character refresh
  1038.   def refresh
  1039.     refresh_mode7_game_character
  1040.     check_commands(@page) if @page != nil
  1041.   end
  1042. end
  1043.  
  1044. #============================================================================
  1045. # ■ Game_Player
  1046. #----------------------------------------------------------------------------
  1047. # Add attributes to have a well-working panorama's scrolling
  1048. #============================================================================
  1049.  
  1050. class Game_Player < Game_Character
  1051.   attr_accessor :map_number_x # map's number with X-looping
  1052.   attr_accessor :map_number_y # map's number with Y-looping
  1053.   #--------------------------------------------------------------------------
  1054.   # * Object Initialization
  1055.   #--------------------------------------------------------------------------
  1056.   alias initialize_mode7_game_player initialize
  1057.   def initialize
  1058.     initialize_mode7_game_player
  1059.     init_mode7
  1060.   end
  1061.   #--------------------------------------------------------------------------
  1062.   # * Mode 7 Initialization
  1063.   #--------------------------------------------------------------------------
  1064.   def init_mode7
  1065.     self.map_number_x = 0
  1066.     self.map_number_y = 0
  1067.     super
  1068.   end
  1069.   #--------------------------------------------------------------------------
  1070.   # * Handle the option : center around the hero
  1071.   #--------------------------------------------------------------------------
  1072.   alias center_mode7_game_player center
  1073.   def center(x, y)
  1074.     if !$game_system.mode7 || !$game_system.always_scroll
  1075.       center_mode7_game_player(x, y)
  1076.       return
  1077.     end
  1078.     $game_map.display_x = x * 128 - CENTER_X
  1079.     $game_map.display_y = y * 128 - CENTER_Y
  1080.   end
  1081. end
  1082.  
  1083. #============================================================================
  1084. # ■ Sprite
  1085. #----------------------------------------------------------------------------
  1086. # Add attributes to work efficiently with scanlines sprites
  1087. #============================================================================
  1088.  
  1089. class Sprite
  1090.   attr_accessor :y_origin_bitmap # bitmap's y-coordinate for the "src_rect.set"
  1091.   #method (float)
  1092.   attr_accessor :x_origin_bitmap # bitmap's x-coordinate for the "src_rect.set"
  1093.   #method (float)
  1094.   attr_accessor :y_origin_bitmap_i # bitmap's y-coordinate for the
  1095.   #"src_rect.set" method (integer)
  1096.   attr_accessor :x_origin_bitmap_i # bitmap's x-coordinate for the
  1097.   #"src_rect.set" method (integer)
  1098.   attr_accessor :length # sprite's width
  1099. end
  1100.  
  1101. #============================================================================
  1102. # ■ Sprite_Character
  1103. #----------------------------------------------------------------------------
  1104. # Calculate x-coordinate and y-coordinate for a mode7 map
  1105. #============================================================================
  1106.  
  1107. class Sprite_Character < RPG::Sprite
  1108.   attr_reader   :flat_indicator # true if the event is flat-drawn
  1109.   #--------------------------------------------------------------------------
  1110.   # * Object Initialization
  1111.   #--------------------------------------------------------------------------
  1112.   alias initialize_mode7_sprite_character initialize
  1113.   def initialize(viewport, character = nil)
  1114.     @flat_indicator = false
  1115.     initialize_mode7_sprite_character(viewport, character)
  1116.   end
  1117.   #--------------------------------------------------------------------------
  1118.   # * Update
  1119.   #--------------------------------------------------------------------------
  1120.   alias update_mode7_sprite_character update
  1121.   def update
  1122.     if !$game_system.mode7
  1123.       update_mode7_sprite_character
  1124.       return
  1125.     end
  1126.     if @flat_indicator
  1127.       if (!@character.flat || @character.moving? ||
  1128.         @tile_id != @character.tile_id ||
  1129.         @character_name != @character.character_name ||
  1130.         @character_hue != @character.character_hue)
  1131.         @flat_indicator = @character.flat
  1132.         # redraw the original ground
  1133.         maps_list = $scene.spriteset.tilemap.maps_list
  1134.         map_ground = $scene.spriteset.tilemap.map_ground
  1135.         rect = Rect.new(@flat_x_map, @flat_y_map, @flat_width, @flat_height)
  1136.         maps_list.each {|map|
  1137.             map.blt(@flat_x_map, @flat_y_map, map_ground, rect)
  1138.             if $game_system.loop_x && @flat_x_map.between?(0, 19 * 32)
  1139.               map.blt(@flat_x_map + 32 * $game_map.width, @flat_y_map, map_ground,
  1140.               rect)
  1141.             end}
  1142.       else
  1143.         return
  1144.       end
  1145.     end
  1146.     super
  1147.     if @tile_id != @character.tile_id ||
  1148.        @character_name != @character.character_name ||
  1149.        @character_hue != @character.character_hue
  1150.       @tile_id = @character.tile_id
  1151.       @character_name = @character.character_name
  1152.       @character_hue = @character.character_hue
  1153.       if @tile_id >= 384
  1154.         self.bitmap = RPG::Cache.tile($game_map.tileset_name,
  1155.           @tile_id, @character.character_hue)
  1156.         self.src_rect.set(0, 0, 32, 32)
  1157.         self.ox = 16
  1158.         self.oy = 32
  1159.       else
  1160.         self.bitmap = RPG::Cache.character(@character.character_name,
  1161.           @character.character_hue)
  1162.         @cw = bitmap.width / 4
  1163.         @ch = bitmap.height / 4
  1164.         self.ox = @cw / 2
  1165.         self.oy = @ch
  1166.         # pivot correction (intersection between the map and this sprite)
  1167.         self.oy -= 4
  1168.       end
  1169.     end
  1170.     self.visible = (!@character.transparent)
  1171.     if @tile_id == 0
  1172.       sx = @character.pattern * @cw
  1173.       sy = (@character.direction - 2) / 2 * @ch
  1174.       self.src_rect.set(sx, sy, @cw, @ch)
  1175.     end
  1176.     if @character.flat # event must be flat drawn
  1177.       return if $scene.spriteset == nil
  1178.       if @tile_id == 0
  1179.         @flat_x_map = @character.real_x / 4 - (@cw - 32) / 2
  1180.         @flat_y_map = @character.real_y / 4 - @ch + 32
  1181.         @flat_x0 = sx
  1182.         @flat_y0 = sy
  1183.         @flat_width = @cw
  1184.         @flat_height = @ch
  1185.       else
  1186.         @flat_x_map = @character.real_x / 4
  1187.         @flat_y_map = @character.real_y / 4
  1188.         @flat_x0 = 0
  1189.         @flat_y0 = 0
  1190.         @flat_width = 32
  1191.         @flat_height = 32
  1192.       end
  1193.       # modify the maps graphics
  1194.       maps_list = $scene.spriteset.tilemap.maps_list
  1195.       rect = Rect.new(@flat_x0, @flat_y0, @flat_width, @flat_height)
  1196.       maps_list.each {|map|
  1197.           map.blt(@flat_x_map, @flat_y_map, bitmap, rect, @character.opacity)
  1198.           if $game_system.loop_x && @flat_x_map.between?(0, 19 * 32)
  1199.             map.blt(@flat_x_map + 32 * $game_map.width, @flat_y_map, bitmap, rect,
  1200.             @character.opacity)
  1201.           end}
  1202.       @flat_indicator = true
  1203.       self.opacity = 0
  1204.       return
  1205.     end
  1206.     x_intermediate = @character.screen_x
  1207.     y_intermediate = @character.screen_y
  1208.     y_intermediate -= $game_temp.pivot + 4 if $game_system.mode7
  1209.     # if vertical looping
  1210.     if $game_system.loop_y
  1211.       h = 32 * $game_map.height
  1212.       y_intermediate = (y_intermediate + h / 2) % h - h / 2
  1213.     end
  1214.     # coordinates in a mode7 map
  1215.     self.y = (($game_temp.distance_h * y_intermediate *
  1216.     $game_temp.cos_angle).to_f / ($game_temp.distance_h - y_intermediate *
  1217.     $game_temp.sin_angle) + $game_temp.pivot)
  1218.     self.zoom_x = $game_temp.slope_value * y + $game_temp.corrective_value
  1219.     self.zoom_y = zoom_x
  1220.     self.x = 320 + zoom_x * (x_intermediate - 320)
  1221.     # if horizontal looping
  1222.     if $game_system.loop_x
  1223.       offset = ($game_map.width >= 24 ? 64 * zoom_x : 0)
  1224.       l = 32 * $game_map.width * zoom_x
  1225.       self.x = (x + offset) % l - offset
  1226.     end
  1227.     # Overworld Sprite Resize
  1228.     if @character.is_a?(Game_Player) && $game_system.ov
  1229.       self.zoom_x *= $game_system.ov_zoom
  1230.       self.zoom_y *= $game_system.ov_zoom
  1231.     end    
  1232.     self.z = @character.screen_z(@ch)
  1233.     # hide the sprite if it is beyond the horizon's line
  1234.     self.opacity = (y < $game_temp.height_limit ? 0 : @character.opacity)
  1235.     self.y -= 32 * @character.height * zoom_y # height correction
  1236.     self.blend_type = @character.blend_type
  1237.     self.bush_depth = @character.bush_depth
  1238.     if @character.animation_id != 0
  1239.       animation = $data_animations[@character.animation_id]
  1240.       animation(animation, true)
  1241.       @character.animation_id = 0
  1242.     end
  1243.   end
  1244. end
  1245.  
  1246. #============================================================================
  1247. # ■ Sprite_V (Vertical Sprites)
  1248. #----------------------------------------------------------------------------
  1249. #  Sprites corresponding to the vertical elements formed by tiles
  1250. #============================================================================
  1251.  
  1252. class Sprite_V < Sprite
  1253.   attr_accessor :x_map # sprite's x_coordinates (in squares) (Float)
  1254.   attr_accessor :y_map # sprite's y_coordinates (in squares) (Float)
  1255.   attr_accessor :square_y # sprite's y_coordinates (in squares) (Integer)
  1256.   attr_accessor :priority # sprite's priority
  1257.   attr_accessor :animated # True if animated
  1258.   attr_accessor :list_bitmap # list of sprite's bitmaps (Bitmap)
  1259.   #--------------------------------------------------------------------------
  1260.   # * Update
  1261.   #--------------------------------------------------------------------------
  1262.   def update
  1263.     square_y_corrected = square_y
  1264.     y_intermediate = 32 * y_map - $game_temp.pivot - $game_map.display_y / 4
  1265.     y_intermediate_reference = y_intermediate
  1266.     # if vertical looping
  1267.     if $game_system.loop_y
  1268.       y_intermediate = (y_intermediate + $game_temp.height / 2) %
  1269.       $game_temp.height - $game_temp.height / 2
  1270.       if y_intermediate_reference < y_intermediate
  1271.         square_y_corrected = square_y + $game_map.height
  1272.       elsif y_intermediate_reference > y_intermediate
  1273.         square_y_corrected = square_y - $game_map.height
  1274.       end
  1275.     end
  1276.     self.y = ($game_temp.distance_h * y_intermediate *
  1277.     $game_temp.cos_angle).to_f / ($game_temp.distance_h - y_intermediate *
  1278.     $game_temp.sin_angle) + $game_temp.pivot
  1279.     if y < $game_temp.height_limit
  1280.       # hide the sprite if it is beyond the horizon's line
  1281.       self.opacity = 0
  1282.       return
  1283.     end
  1284.     self.opacity = 255
  1285.     if $scene.spriteset != nil
  1286.       opacity_values = $scene.spriteset.tilemap.opacity_values
  1287.       tone_values = $scene.spriteset.tilemap.tone_values
  1288.       if opacity_values.has_key?(y)
  1289.         self.opacity = opacity_values[y]
  1290.         self.tone = tone_values[y]
  1291.       end
  1292.     end
  1293.     self.zoom_x = $game_temp.slope_value * y + $game_temp.corrective_value
  1294.     self.zoom_y = zoom_x
  1295.     x_intermediate = 32 * x_map - $game_map.display_x / 4
  1296.     self.x = 320 + (zoom_x * (x_intermediate - 320))
  1297.     # if horizontal looping
  1298.     if $game_system.loop_x
  1299.       offset = ($game_map.width >= 24 ? 64 * zoom_x : 0)
  1300.       l = 32 * $game_map.width * self.zoom_x
  1301.       self.x = (self.x + offset) % l - offset
  1302.     end
  1303.     self.z = (128 * square_y_corrected - $game_map.display_y + 3) / 4 +
  1304.     32 + 32 * priority
  1305.   end
  1306.   #--------------------------------------------------------------------------
  1307.   # * Update bitmap for animation
  1308.   #     index  : 0..3 : animation's index
  1309.   #--------------------------------------------------------------------------
  1310.   def update_animated(index)
  1311.     self.bitmap = @list_bitmap[index]
  1312.   end
  1313. end
  1314.  
  1315. #============================================================================
  1316. # ■ Spriteset_Map
  1317. #----------------------------------------------------------------------------
  1318. #  Modifications to call a mode7 map
  1319. #============================================================================
  1320.  
  1321. class Spriteset_Map
  1322.   attr_accessor :tilemap # just to be able to access the tilemap
  1323.   #--------------------------------------------------------------------------
  1324.   # * Defines map's options from its name
  1325.   # Refer to Game_System class
  1326.   #--------------------------------------------------------------------------
  1327.   def init_options
  1328.     map_data = $data_maps[$game_map.map_id]
  1329.     MODE7_SETTINGS.each_key {|keyword|
  1330.         if map_data.name2.include?(keyword)
  1331.           command_list = MODE7_SETTINGS[keyword]
  1332.           $game_system.mode7 = true
  1333.           $game_system.loop_x = command_list.include?("X")
  1334.           $game_system.loop_y = command_list.include?("Y")
  1335.           $game_system.always_scroll = command_list.include?("C")
  1336.           $game_system.animated = command_list.include?("A")
  1337.           $game_system.white_horizon = command_list.include?("H")
  1338.           $game_system.fixed_panorama = command_list.include?("P")
  1339.           $game_system.ov = command_list.include?("OV")
  1340.           command_list.each {|command|
  1341.               if command.include?("#")
  1342.                 $game_system.angle = (command.slice(1, 2)).to_i
  1343.                 if $game_system.angle < 0
  1344.                   $game_system.angle = 0
  1345.                 elsif $game_system.angle > 89
  1346.                   $game_system.angle = 89
  1347.                 end
  1348.                 break
  1349.               end}
  1350.           return
  1351.         end}
  1352.     $game_system.mode7 = map_data.name2.include?("[M7]")
  1353.     $game_system.loop_x = map_data.name2.include?("[X]")
  1354.     $game_system.loop_y = map_data.name2.include?("[Y]")
  1355.     $game_system.always_scroll = map_data.name2.include?("[C]")
  1356.     $game_system.animated = map_data.name2.include?("[A]")
  1357.     $game_system.white_horizon = map_data.name2.include?("[H]")
  1358.     $game_system.fixed_panorama = map_data.name2.include?("[P]")
  1359.     $game_system.ov = map_data.name2.include?("[OV]")
  1360.     if $game_system.mode7
  1361.       map_data.name2 =~ /\[#[ ]*([00-99]+)\]/i
  1362.       $game_system.angle = $1.to_i
  1363.       if $game_system.angle < 0
  1364.         $game_system.angle = 0
  1365.       elsif $game_system.angle > 89
  1366.         $game_system.angle = 89
  1367.       end
  1368.     end
  1369.   end
  1370.   #--------------------------------------------------------------------------
  1371.   # * Initialize Object
  1372.   #   Rewritten to call a map with mode7
  1373.   #--------------------------------------------------------------------------
  1374.   alias initialize_mode7_spriteset_map initialize
  1375.   def initialize
  1376.     if !$game_system.mode7
  1377.       initialize_mode7_spriteset_map
  1378.       return
  1379.     end
  1380.     init_options
  1381.     @viewport1 = Viewport.new(0, 0, 640, 480)
  1382.     @viewport2 = Viewport.new(0, 0, 640, 480)
  1383.     @viewport3 = Viewport.new(0, 0, 640, 480)
  1384.     @viewport2.z = 200
  1385.     @viewport3.z = 5000
  1386.     # mode7 map
  1387.     @tilemap = Tilemap_mode7.new(@viewport1)
  1388.     @panorama = Plane.new(@viewport1)
  1389.     # sprites drawn at the horizon's level have a negative z, and with a z value
  1390.     # of -100000 the panorama is still below
  1391.     @panorama.z = ($game_system.mode7 ? -100000 : -1000)
  1392.     @fog = Plane.new(@viewport1)
  1393.     @fog.z = 3000
  1394.     @character_sprites = []
  1395.     $game_map.events.keys.sort.each {|i|
  1396.         sprite = Sprite_Character.new(@viewport1, $game_map.events[i])
  1397.         @character_sprites.push(sprite)}
  1398.     @character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
  1399.     @weather = RPG::Weather.new(@viewport1)
  1400.     @picture_sprites = []
  1401.     (1..50).each {|i|
  1402.         @picture_sprites.push(Sprite_Picture.new(@viewport2,
  1403.           $game_screen.pictures[i]))}
  1404.     @timer_sprite = Sprite_Timer.new
  1405.     update
  1406.   end
  1407.   #--------------------------------------------------------------------------
  1408.   # * Dispose
  1409.   #--------------------------------------------------------------------------
  1410.   alias dispose_mode7_spriteset_map dispose
  1411.   def dispose
  1412.     if !$game_system.mode7
  1413.       dispose_mode7_spriteset_map
  1414.       return
  1415.     end
  1416.     @tilemap.dispose
  1417.     @panorama.dispose
  1418.     @fog.dispose
  1419.     @character_sprites.each {|sprite| sprite.dispose}
  1420.     @weather.dispose
  1421.     @picture_sprites.each {|sprite| sprite.dispose}
  1422.     @timer_sprite.dispose
  1423.     @viewport1.dispose
  1424.     @viewport2.dispose
  1425.     @viewport3.dispose
  1426.   end
  1427.   #--------------------------------------------------------------------------
  1428.   # * Update
  1429.   #--------------------------------------------------------------------------
  1430.   alias update_mode7_spriteset_map update
  1431.   def update
  1432.     if !$game_system.mode7
  1433.       update_mode7_spriteset_map
  1434.       return
  1435.     end
  1436.     if @panorama_name != $game_map.panorama_name ||
  1437.        @panorama_hue != $game_map.panorama_hue
  1438.       @panorama_name = $game_map.panorama_name
  1439.       @panorama_hue = $game_map.panorama_hue
  1440.       if @panorama.bitmap != nil
  1441.         @panorama.bitmap.dispose
  1442.         @panorama.bitmap = nil
  1443.       end
  1444.       if @panorama_name != ""
  1445.         @panorama.bitmap = RPG::Cache.panorama(@panorama_name, @panorama_hue)
  1446.       end
  1447.       Graphics.frame_reset
  1448.     end
  1449.     if @fog_name != $game_map.fog_name || @fog_hue != $game_map.fog_hue
  1450.       @fog_name = $game_map.fog_name
  1451.       @fog_hue = $game_map.fog_hue
  1452.       if @fog.bitmap != nil
  1453.         @fog.bitmap.dispose
  1454.         @fog.bitmap = nil
  1455.       end
  1456.       @fog.bitmap = RPG::Cache.fog(@fog_name, @fog_hue) if @fog_name != ''
  1457.       Graphics.frame_reset
  1458.     end
  1459.     # update animated tiles each 20 frames
  1460.     if Graphics.frame_count % 20 == 0 && $game_system.animated
  1461.       @tilemap.update_animated
  1462.     end
  1463.     @tilemap.update
  1464.     # if the panorama is fixed
  1465.     if $game_system.fixed_panorama
  1466.       @panorama.ox = 0
  1467.       @panorama.oy = 0
  1468.     # if it is a mode7 map
  1469.     else
  1470.       # to have a fluent panorama scrolling
  1471.       @panorama.ox = (128 * $game_map.width * $game_player.map_number_x +
  1472.       $game_player.real_x) / 8
  1473.       @panorama.oy = - (128 * $game_map.height * $game_player.map_number_y +
  1474.       $game_player.real_y) / 32
  1475.     end
  1476.     @fog.zoom_x = $game_map.fog_zoom / 100.0
  1477.     @fog.zoom_y = $game_map.fog_zoom / 100.0
  1478.     @fog.opacity = $game_map.fog_opacity
  1479.     @fog.blend_type = $game_map.fog_blend_type
  1480.     @fog.ox = $game_map.display_x / 4 + $game_map.fog_ox
  1481.     @fog.oy = $game_map.display_y / 4 + $game_map.fog_oy
  1482.     @fog.tone = $game_map.fog_tone
  1483.     @character_sprites.each {|sprite| sprite.update}
  1484.     @weather.type = $game_screen.weather_type
  1485.     @weather.max = $game_screen.weather_max
  1486.     @weather.ox = $game_map.display_x / 4
  1487.     @weather.oy = $game_map.display_y / 4
  1488.     @weather.update
  1489.     @picture_sprites.each {|sprite| sprite.update}
  1490.     @timer_sprite.update
  1491.     @viewport1.tone = $game_screen.tone
  1492.     @viewport1.ox = $game_screen.shake
  1493.     @viewport3.color = $game_screen.flash_color
  1494.     @viewport1.update
  1495.     @viewport3.update
  1496.   end
  1497. end
  1498.  
  1499. #============================================================================
  1500. # ■ Scene_Map
  1501. #============================================================================
  1502. class Scene_Map
  1503.   attr_accessor :spriteset # just need to access the spriteset
  1504. end
  1505.  
  1506. #============================================================================
  1507. # ■ Data_Autotiles
  1508. #----------------------------------------------------------------------------
  1509. # Creates the set of tiles from an autotile's file
  1510. #============================================================================
  1511.  
  1512. class Data_Autotiles < Bitmap
  1513.   # data list to form tiles from an atotiles file
  1514.   Data_creation = [[27,28,33,34],[5,28,33,34],[27,6,33,34],[5,6,33,34],
  1515.   [27,28,33,12],[5,28,33,12],[27,6,33,12],[5,6,33,12],[27,28,11,34],
  1516.   [5,28,11,34],[27,6,11,34],[5,6,11,34],[27,28,11,12],[5,28,11,12],
  1517.   [27,6,11,12],[5,6,11,12],[25,26,31,32],[25,6,31,32],[25,26,31,12],
  1518.   [25,6,31,12],[15,16,21,22],[15,16,21,12],[15,16,11,22],[15,16,11,12],
  1519.   [29,30,35,36],[29,30,11,36],[5,30,35,36],[5,30,11,36],[39,40,45,46],
  1520.   [5,40,45,46],[39,6,45,46],[5,6,45,46],[25,30,31,36],[15,16,45,46],
  1521.   [13,14,19,20],[13,14,19,12],[17,18,23,24],[17,18,11,24],[41,42,47,48],
  1522.   [5,42,47,48],[37,38,43,44],[37,6,43,44],[13,18,19,24],[13,14,43,44],
  1523.   [37,42,43,48],[17,18,47,48],[13,18,43,48],[13,18,43,48]]
  1524.   attr_accessor :number # autotile's number to identify it
  1525.   attr_accessor :animated # TRUE if the autotile is animated
  1526.   #--------------------------------------------------------------------------
  1527.   # * Initialize Object
  1528.   #     file   : autotiles file's bitmap (Bitmap)
  1529.   #     l      : 0..3 : pattern's number for animated autotiles
  1530.   #--------------------------------------------------------------------------
  1531.   def initialize(file, l)
  1532.     super(8*32, 6*32)
  1533.     create(file, l)
  1534.   end
  1535.   #--------------------------------------------------------------------------
  1536.   # * Create the tiles set
  1537.   #     file   : autotiles file's bitmap (Bitmap)
  1538.   #     l      : 0..3 : pattern's number for animated autotiles
  1539.   #--------------------------------------------------------------------------
  1540.   def create(file, l)
  1541.     l = (file.width > 96 ? l : 0)
  1542.     self.animated = (file.width > 96)
  1543.     (0..5).each {|i| (0..7).each {|j| Data_creation[8 * i + j].each {|number|
  1544.         number -= 1
  1545.         m = 16 * (number % 6)
  1546.         n = 16 * (number / 6)
  1547.         blt(32 * j + m % 32, 32 * i + n % 32, file,
  1548.         Rect.new(m + 96 * l, n, 16, 16))}}}
  1549.   end
  1550. end
  1551.  
  1552. #============================================================================
  1553. # ■ Data_Vertical_Sprites
  1554. #----------------------------------------------------------------------------
  1555. # Create a list of vertical sprites for the three layers of a map
  1556. # "V" for "Vertical" in the script
  1557. # "num" for "number"
  1558. #============================================================================
  1559.  
  1560. class Data_Vertical_Sprites
  1561.   attr_accessor  :list_sprites_V # list of vertical sprites
  1562.   attr_accessor  :list_sprites_V_animated # list of animated vertical sprites
  1563.   #--------------------------------------------------------------------------
  1564.   # * A little method to compare terrain_tags
  1565.   #     value  : tile's ID
  1566.   #     num    : reference terrain_tag's value
  1567.   #--------------------------------------------------------------------------
  1568.   def suitable?(value, num)
  1569.     return ($game_map.terrain_tags[value] == num)
  1570.   end
  1571.   #--------------------------------------------------------------------------
  1572.   # * This algorithm scans each layer and create a sprites formed by tiles
  1573.   #   in contact
  1574.   #     viewport : Viewport
  1575.   #--------------------------------------------------------------------------
  1576.   def initialize(viewport)
  1577.     @viewport = viewport
  1578.     # lists initialization
  1579.     self.list_sprites_V = []
  1580.     self.list_sprites_V_animated = []
  1581.     # @num_tiles : list of tiles coordinates that form a vertical sprite
  1582.     @num_tiles = []
  1583.     # create copy of map's data
  1584.     @dataV = ($game_map.data).clone
  1585.     # scan each layer, row and column
  1586.     (0..2).each {|h| (0..$game_map.height).each {|i| (0..$game_map.width).each {|j|
  1587.         value = @dataV[j, i, h].to_i
  1588.         # if tile's terrain tag is declared to give vertical sprites
  1589.         if VERTICAL_TILE_TERRAIN_TAGS.include?($game_map.terrain_tags[value])
  1590.           @reference_terrain_tag = $game_map.terrain_tags[value]
  1591.           @num_tiles.push([j, i])
  1592.           # the following algorithm is so complex that I really don't know how
  1593.           # it works exactly
  1594.           list_end = 0
  1595.           length = 0
  1596.           while j + length + 1 < $game_map.width &&
  1597.               suitable?(@dataV[j +length+ 1, i, h].to_i, @reference_terrain_tag)
  1598.             @num_tiles.push([j + length+ 1,i])
  1599.             length += 1
  1600.           end
  1601.           list_start = j
  1602.           list_end = length + j
  1603.           indicator = true
  1604.           row = 0
  1605.           j2 = j
  1606.           while indicator
  1607.             row += 1
  1608.             break if (i + row) == $game_map.height
  1609.             list_start2 = j2
  1610.             length2 = 0
  1611.             indicator = false
  1612.             if length >= 2
  1613.               ((j2 + 1)..(j2 + length -1)).each {|k|
  1614.                   if suitable?(@dataV[k, i + row, h].to_i,
  1615.                     @reference_terrain_tag)
  1616.                     if !indicator
  1617.                       list_start2 = k
  1618.                     else
  1619.                       length2 = k - list_start2
  1620.                     end
  1621.                     indicator = true
  1622.                     @num_tiles.push([k, i + row])
  1623.                   elsif !indicator
  1624.                     length2 -= 1
  1625.                   end}
  1626.             end
  1627.             if suitable?(@dataV[j2 + length, i + row, h].to_i,
  1628.               @reference_terrain_tag)
  1629.               length2 = j2 + length - list_start2
  1630.               indicator = true
  1631.               @num_tiles.push([j2 + length, i + row])
  1632.               length3 = 1
  1633.               while j2 + length + length3 < $game_map.width &&
  1634.                   suitable?(@dataV[j2 + length + length3, i + row, h].to_i,
  1635.                   @reference_terrain_tag)
  1636.                 @num_tiles.push([j2 + length + length3, i + row])
  1637.                 length3 += 1
  1638.                 length2 += 1
  1639.                 if j2 + length + length3 > list_end
  1640.                   list_end = j2 + length + length3
  1641.                 end
  1642.               end
  1643.             end
  1644.             if suitable?(@dataV[j2, i + row, h].to_i, @reference_terrain_tag)
  1645.               list_start3 = list_start2 - j2
  1646.               length2 = length2 + list_start3
  1647.               list_start2 = j2
  1648.               indicator = true
  1649.               @num_tiles.push([j2, i + row])
  1650.               length3 = 1
  1651.               while j2 - length3 >= 0 &&
  1652.                   suitable?(@dataV[j2 - length3, i + row, h].to_i,
  1653.                   @reference_terrain_tag)
  1654.                 @num_tiles.push([j2 - length3, i + row])
  1655.                 length3 += 1
  1656.                 length2 += 1
  1657.                 list_start2 -= 1
  1658.                 list_start = list_start2 if list_start2 < list_start
  1659.               end
  1660.             end
  1661.             length = length2
  1662.             j2 = list_start2
  1663.           end
  1664.           row -= 1
  1665.           # create a bitmap and a sprite from the tiles listed in @num_tiles
  1666.           create_bitmap(i, list_start, row, list_end - list_start, h)
  1667.           # clear the used tiles
  1668.           clear_data(h)
  1669.           # reinitialize the list of tiles
  1670.           @num_tiles = []
  1671.         end}}}
  1672.   end
  1673.   #--------------------------------------------------------------------------
  1674.   # * Clear the used data to prevent from reusing them
  1675.   #     layer  : current scanned layer
  1676.   #--------------------------------------------------------------------------
  1677.   def clear_data(layer)
  1678.     @num_tiles.each {|num| @dataV[num[0], num[1], layer] = 0}
  1679.   end
  1680.   #--------------------------------------------------------------------------
  1681.   # * Create a Bitmap from the listed tiles in @num_tiles and its associated
  1682.   #   sprite (Sprite_V)
  1683.   #     row     : start row's value
  1684.   #     column  : start column's value
  1685.   #     height  : sprite's height (in tiles)
  1686.   #     width   : sprite's width (in tiles)
  1687.   #     layer   : current scanned layer
  1688.   #--------------------------------------------------------------------------
  1689.   def create_bitmap(row, column, height, width, layer)
  1690.     bmp = Bitmap.new(32*(1+width), 32*(1+height))
  1691.     rect = Rect.new(0, 0, 32, 32)
  1692.     @num_tiles.sort! {|a, b|  -(a[1] - b[1])}
  1693.     sprite = Sprite_V.new(@viewport)
  1694.     # initialize sprite's attributes
  1695.     sprite.animated = false
  1696.     sprite.list_bitmap = []
  1697.     # draw the bitmap
  1698.     @num_tiles.each {|tile_coordinates|
  1699.         value = @dataV[tile_coordinates[0], tile_coordinates[1], layer].to_i
  1700.         # if tile is a normal tile
  1701.         if value > 383
  1702.           bitmap = RPG::Cache.tile($game_map.tileset_name, value, 0)
  1703.         else # tile is an autotile
  1704.           file = (value / 48) - 1
  1705.           num_file = 4 * file
  1706.           if !sprite.animated
  1707.             autotile_name = $game_map.autotile_names[file]
  1708.             fichier = RPG::Cache.autotile(autotile_name)
  1709.             sprite.animated = (fichier.width > 96 ? true : false)
  1710.           end
  1711.           bitmap = RPG::Cache.autotile_base(num_file, value)
  1712.         end
  1713.         bmp.blt(32 * (tile_coordinates[0] - column),
  1714.         32 * (tile_coordinates[1] - row), bitmap, rect)}
  1715.     sprite.list_bitmap.push(bmp)
  1716.     # create 3 additionnal bitmaps for animated sprites
  1717.     if sprite.animated
  1718.       (1..3).each {|j|
  1719.           bmp = Bitmap.new(32 * (1 + width), 32 * (1 + height))
  1720.           @num_tiles.each {|tile_coordinates|
  1721.               value = @dataV[tile_coordinates[0], tile_coordinates[1], layer].to_i
  1722.               if value > 383
  1723.                 bitmap = RPG::Cache.tile($game_map.tileset_name, value, 0)
  1724.               else
  1725.                 num_file = 4 * ((value / 48) - 1)
  1726.                 bitmap = RPG::Cache.autotile_base(num_file + j, value)
  1727.               end
  1728.               bmp.blt(32 * (tile_coordinates[0] - column),
  1729.               32 * (tile_coordinates[1] - row), bitmap, rect)}
  1730.           sprite.list_bitmap.push(bmp)}
  1731.     end
  1732.     value = @dataV[@num_tiles[0][0], @num_tiles[0][1], layer].to_i
  1733.     # set sprite's priority
  1734.     sprite.priority = $game_map.priorities[value]
  1735.     # set sprite's coordinates (in squares (32 * 32 pixels))
  1736.     sprite.x_map = (column.to_f) + bmp.width / 64
  1737.     sprite.x_map += 0.5 if width % 2 == 0
  1738.     sprite.y_map = (row + height).to_f + 0.5
  1739.     sprite.square_y = sprite.y_map.to_i # Integer
  1740.     # set the y_pivot (intersection between the map and the sprite)
  1741.     sprite.oy = bmp.height - 16
  1742.     sprite.ox = bmp.width / 2
  1743.     sprite.bitmap = sprite.list_bitmap[0]
  1744.     self.list_sprites_V.push(sprite)
  1745.     self.list_sprites_V_animated.push(sprite) if sprite.animated
  1746.   end
  1747. end
  1748.  
  1749. #============================================================================
  1750. # ■ RPG::Cache_Tile
  1751. #----------------------------------------------------------------------------
  1752. # The tiles resulting in a superimposing of several tiles are kept in memory
  1753. # for a faster call
  1754. # valueX : tile's ID
  1755. #============================================================================
  1756.  
  1757. module RPG::Cache_Tile
  1758.   @cache = {}
  1759.   #--------------------------------------------------------------------------
  1760.   # * Superimposing of two tiles, offset = pattern's number for animated
  1761.   # autotiles
  1762.   #--------------------------------------------------------------------------
  1763.   def self.load(value1, value2, offset=0)
  1764.     if !@cache.include?([value1, value2, offset])
  1765.       bitmap = Bitmap.new(32, 32)
  1766.       rect = Rect.new(0, 0, 32, 32)
  1767.       if value1 > 383 # normal tile
  1768.         bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value1, 0),
  1769.         rect)
  1770.       else # autotile
  1771.         num = 4*((value1 / 48) - 1) + offset
  1772.         bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value1), rect)
  1773.       end
  1774.       if value2 > 383 # normal tile
  1775.         bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value2, 0),
  1776.         rect)
  1777.       else # autotile
  1778.         num = 4*((value2 / 48) - 1) + offset
  1779.         bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value2), rect)
  1780.       end
  1781.       ###@cache[[value1, value2, offset]] = bitmap
  1782.       return bitmap
  1783.     end
  1784.     @cache[[value1, value2, offset]]
  1785.   end
  1786.   #--------------------------------------------------------------------------
  1787.   # * Superimposing of three tiles
  1788.   #--------------------------------------------------------------------------
  1789.   def self.load2(value1, value2, value3, offset = 0)
  1790.     if !@cache.include?([value1, value2, value3, offset])
  1791.       bitmap = Bitmap.new(32, 32)
  1792.       rect = Rect.new(0, 0, 32, 32)
  1793.       if value1 > 383 # normal tile
  1794.         bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value1, 0),
  1795.         rect)
  1796.       else # autotile
  1797.         num = 4*((value1 / 48) - 1) + offset
  1798.         bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value1), rect)
  1799.       end
  1800.       if value2 > 383 # normal tile
  1801.         bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value2, 0),
  1802.         rect)
  1803.       else # autotile
  1804.         num = 4*((value2 / 48) - 1) + offset
  1805.         bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value2), rect)
  1806.       end
  1807.       if value3 > 383 # normal tile
  1808.         bitmap.blt(0, 0, RPG::Cache.tile($game_map.tileset_name, value3, 0),
  1809.         rect)
  1810.       else # autotile
  1811.         num = 4*((value3 / 48) - 1) + offset
  1812.         bitmap.blt(0, 0, RPG::Cache.autotile_base(num, value3), rect)
  1813.       end
  1814.       ###@cache[[value1, value2, value3, offset]] = bitmap
  1815.       return bitmap
  1816.     end
  1817.     @cache[[value1, value2, value3, offset]]
  1818.   end
  1819.   #--------------------------------------------------------------------------
  1820.   # * Clear the Cache
  1821.   #--------------------------------------------------------------------------
  1822.   def self.clear
  1823.     @cache = {}
  1824.     GC.start
  1825.   end
  1826. end
  1827.  
  1828. #============================================================================
  1829. # ■ RPG::Cache_Carte
  1830. #----------------------------------------------------------------------------
  1831. # Maps drawn with mode7 are kept in memory to have a faster call the next
  1832. # times they need to be drawn
  1833. #============================================================================
  1834.  
  1835. module RPG::Cache_Carte
  1836.   @cache = {}
  1837.   #--------------------------------------------------------------------------
  1838.   # * Check if the map is in the Cache
  1839.   #   map_id : map's ID
  1840.   #--------------------------------------------------------------------------
  1841.   def self.in_cache(map_id)
  1842.     return @cache.include?(map_id)
  1843.   end
  1844.   #--------------------------------------------------------------------------
  1845.   # * Return the map's drawing (Bitmap)
  1846.   #   map_id : map's ID
  1847.   #   num    : pattern's number for animated autotiles
  1848.   #--------------------------------------------------------------------------
  1849.   def self.load(map_id, num = 0)
  1850.     return @cache[map_id][num]
  1851.   end
  1852.   #--------------------------------------------------------------------------
  1853.   # * Save the map's drawing in the Cache
  1854.   #   map_id : map's ID
  1855.   #   bitmap : map's drawing (Bitmap)
  1856.   #   num    : pattern's number for animated autotiles
  1857.   #--------------------------------------------------------------------------
  1858.   def self.save(map_id, bitmap, num = 0)
  1859.     @cache[map_id] = [] if !self.in_cache(map_id)
  1860.     @cache[map_id][num] = bitmap
  1861.   end
  1862.   #--------------------------------------------------------------------------
  1863.   # * Clear the Cache
  1864.   #--------------------------------------------------------------------------
  1865.   def self.clear
  1866.     @cache = {}
  1867.     GC.start
  1868.   end
  1869. end
  1870.  
  1871. #============================================================================
  1872. # ■ RPG::Cache
  1873. #----------------------------------------------------------------------------
  1874. # The tiles from autotiles files are kept in memory for a faster call
  1875. #============================================================================
  1876.  
  1877. module RPG::Cache
  1878.   #--------------------------------------------------------------------------
  1879.   # * Check if the map is in the Cache
  1880.   #   num    : autotiles file's ID
  1881.   #   value    : tile's ID
  1882.   #--------------------------------------------------------------------------
  1883.   def self.autotile_base(num, value)
  1884.     key = [num, value]
  1885.     if !@cache.include?(key) || @cache[key].disposed?
  1886.       @cache[key] = Bitmap.new(32, 32)
  1887.       num_tile = value % 48
  1888.       sx = 32 * (num_tile % 8)
  1889.       sy = 32 * (num_tile / 8)
  1890.       rect = Rect.new(sx, sy, 32, 32)
  1891.       @cache[key].blt(0, 0, self.load_autotile(num), rect)
  1892.     end
  1893.     @cache[key]
  1894.   end
  1895.   #--------------------------------------------------------------------------
  1896.   # * Save the tile's drawing in the Cache
  1897.   #   bitmap : tile's drawing (Bitmap)
  1898.   #   key    : tile's ID
  1899.   #--------------------------------------------------------------------------
  1900.   def self.save_autotile(bitmap, key)
  1901.     @cache[key] = bitmap
  1902.   end
  1903.   #--------------------------------------------------------------------------
  1904.   # * Return the tile's drawing (Bitmap)
  1905.   #   key    : tile's ID
  1906.   #--------------------------------------------------------------------------
  1907.   def self.load_autotile(key)
  1908.     @cache[key]
  1909.   end
  1910. end
  1911.  
  1912. #============================================================================
  1913. # ■ RPG::MapInfo
  1914. #============================================================================
  1915.  
  1916. class RPG::MapInfo
  1917.   # defines the map's name as the name without anything within brackets,
  1918.   # including brackets
  1919.   def name
  1920.     return @name.gsub(/\[.*\]/) {""}
  1921.   end
  1922.   #--------------------------------------------------------------------------
  1923.   # the original name with the codes
  1924.   def name2
  1925.     return @name
  1926.   end
  1927. end
  1928.  
  1929. #============================================================================
  1930. # ■ Game_Temp
  1931. #----------------------------------------------------------------------------
  1932. # Add attributes to this class / Avoid using too many global variables
  1933. #============================================================================
  1934.  
  1935. class Game_Temp
  1936.   attr_accessor :pivot # screenline's number of the slant's pivot
  1937.   attr_accessor :cos_angle # cosinus of the slant's angle
  1938.   attr_accessor :sin_angle # sinus of the slant's angle
  1939.   attr_accessor :height_limit # horizon's line
  1940.   attr_accessor :distance_h # distance between the map's center and the vanishing point
  1941.   attr_accessor :slope_value # intermediate value
  1942.   attr_accessor :corrective_value # intermediate value
  1943.   attr_accessor :height # map's height (in pixel)
  1944.   #--------------------------------------------------------------------------
  1945.   # * Object Initialization
  1946.   #--------------------------------------------------------------------------
  1947.   alias initialize_mode7_game_temp initialize
  1948.   def initialize
  1949.     initialize_mode7_game_temp
  1950.     self.pivot = 0
  1951.     self.cos_angle = 0.0
  1952.     self.sin_angle = 0.0
  1953.     self.height_limit = 0
  1954.     self.distance_h = 0
  1955.     self.slope_value = 0.0
  1956.     self.corrective_value = 0.0
  1957.     self.height = 0
  1958.   end
  1959. end
Advertisement
Add Comment
Please, Sign In to add comment