Advertisement
Zeriab

[RGSS] Multi-panorama

Jul 20th, 2021
1,459
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 10.74 KB | None | 0 0
  1. ##
  2. # Animated panoramas setup model
  3. #
  4. module PanoramaSetup
  5.   PanoramaAnimFrame = Struct.new(:name, :wait)
  6.   PanoramaAnim = Struct.new(:frames, :start_index, :direction)
  7.  
  8.   ##
  9.   # Instance of an animation
  10.   #
  11.   class PanoramaInstance < Struct.new(:anim, :current_index, :running, :ticks)
  12.     def direction
  13.       return anim.direction
  14.     end
  15.    
  16.     def current_frame
  17.       return anim.frames[current_index]
  18.     end
  19.    
  20.     def current_name
  21.       current_frame.name
  22.     end
  23.    
  24.     def next_frame
  25.       self.current_index += 1
  26.       self.current_index %= anim.frames.size
  27.       self.ticks = 0
  28.     end
  29.    
  30.     def start
  31.       self.running = true
  32.       self.ticks = 0
  33.       self.current_index = anim.start_index
  34.     end
  35.    
  36.     def update
  37.       if running
  38.         self.ticks += 1
  39.         next_frame if self.ticks >= current_frame.wait
  40.       end
  41.     end
  42.    
  43.     def stop
  44.       self.running = false
  45.     end
  46.    
  47.     def resume
  48.       self.running = true
  49.     end
  50.   end
  51.  
  52.   # Symbol => animation setup map
  53.   Config = {}
  54.  
  55.   module_function
  56.   def create_default_anim
  57.     return PanoramaAnim.new([], 0, DIRECTION_DEFAULT)
  58.   end
  59.  
  60.   ##
  61.   # Fetch the animation setup associated with the given symbol
  62.   #
  63.   def fetch_anim(symbol)
  64.     anim = Config[symbol]
  65.     if anim.nil?
  66.       anim = create_default_anim
  67.       Config[symbol] = anim
  68.     end
  69.     return anim
  70.   end
  71.  
  72.   ##
  73.   # Add frames of the given filename at the end of the given animation.
  74.   # Wait determines how many frames are added.
  75.   #
  76.   def add_frame(symbol, name, wait)
  77.     anim = fetch_anim(symbol)
  78.     frame = PanoramaAnimFrame.new(name, wait)
  79.     anim.frames << frame
  80.   end
  81.  
  82.   ##
  83.   # Tiling direction setup
  84.   #
  85.   DIRECTION_DEFAULT = :both
  86.   DIRECTION_VALID = [:both, :horizontal, :vertical, :none]
  87.   def tile_direction(symbol, direction)
  88.     # Input validation
  89.     unless DIRECTION_VALID.include?(direction)
  90.       print "Panorama setup error.\n\nInvalid tiling direction #{direction.inspect} given for #{symbol.inspect}"
  91.       exit
  92.     end
  93.     # Update animation metadata
  94.     anim = fetch_anim(symbol)
  95.     anim.direction = direction
  96.   end
  97.  
  98.   ##
  99.   # Create an animation instance that can be used for playback
  100.   #
  101.   def create_instance(symbol)
  102.     anim = PanoramaSetup::Config[symbol]
  103.     return PanoramaInstance.new(anim, anim.start_index, true, 0)
  104.   end
  105. end
  106.  
  107.  
  108. ##
  109. # Store panoramas
  110. #
  111. class Game_Map
  112.   attr_sec_accessor :multi_panorama, '{}'
  113.  
  114.   ##
  115.   # Update panoramas
  116.   #
  117.   unless self.method_defined?('zeriab_multipan_gamemap_update')
  118.     alias zeriab_multipan_gamemap_update update
  119.   end
  120.   def update
  121.     zeriab_multipan_gamemap_update
  122.     for panorama in multi_panorama.values
  123.       panorama.update
  124.     end
  125.   end
  126.  
  127.   ##
  128.   # Accessors
  129.   #
  130.   def add_panorama(symbol, panorama)
  131.     multi_panorama[symbol] = panorama
  132.   end
  133.   def get_panorama(symbol)
  134.     multi_panorama[symbol]
  135.   end
  136.   def remove_panorama(symbol)
  137.     multi_panorama.delete(symbol)
  138.   end
  139.  
  140.   ##
  141.   # Clear panoramas on map transfers
  142.   #
  143.   unless self.method_defined?('zeriab_multipan_game_map_setup')
  144.     alias zeriab_multipan_game_map_setup :setup
  145.   end
  146.   def setup(*args)
  147.     multi_panorama.clear
  148.     zeriab_multipan_game_map_setup(*args)
  149.   end
  150. end
  151.  
  152. ##
  153. # Game panorama concept
  154. #
  155. class Game_Panorama
  156.   attr_accessor :symbol
  157.   attr_accessor :hue
  158.   attr_accessor :name  
  159.   attr_accessor :z
  160.   attr_accessor :x_div
  161.   attr_accessor :y_div
  162.   attr_accessor :offset_x
  163.   attr_accessor :offset_y
  164.   attr_accessor :ox
  165.   attr_accessor :oy
  166.   attr_accessor :move_ox
  167.   attr_accessor :move_oy
  168.  
  169.   attr_accessor :anim
  170.   attr_accessor :animated
  171.   attr_accessor :direction
  172.  
  173.   def initialize(symbol, name, hue)
  174.     self.symbol = symbol
  175.     self.hue = hue
  176.    
  177.     # Animation specifics
  178.     if name.is_a?(Symbol)
  179.       self.anim = PanoramaSetup.create_instance(name)
  180.       self.name = anim.current_name
  181.       self.direction = anim.direction
  182.       self.animated = true
  183.     else
  184.       self.name = name
  185.       self.animated = false
  186.       self.direction = :both
  187.     end
  188.    
  189.     # Defaults
  190.     self.z = -500
  191.     self.x_div = 8
  192.     self.y_div = 8
  193.     self.offset_x = 0
  194.     self.offset_y = 0
  195.     self.move_ox = 0
  196.     self.move_oy = 0
  197.   end
  198.  
  199.   def update
  200.     # Animate
  201.     if animated
  202.       anim.update
  203.       self.name = anim.current_name
  204.     end
  205.    
  206.     # Apply movement
  207.     self.offset_x += self.move_ox
  208.     self.offset_y += self.move_oy
  209.    
  210.     # Update panorama plane
  211.     self.ox = (self.offset_x + $game_map.display_x) / self.x_div
  212.     self.oy = (self.offset_y + $game_map.display_y) / self.y_div
  213.   end
  214.  
  215.   def stop
  216.     if animated
  217.       anim.stop
  218.     end
  219.   end
  220.  
  221.   ##
  222.   # Helpers
  223.   #
  224.   def is_plane?
  225.     return direction != :none
  226.   end
  227.   def is_full_plane?
  228.     return direction == :both
  229.   end
  230.   def is_partial_plane?
  231.     return is_horizontal? || is_vertical?
  232.   end
  233.   def is_horizontal?
  234.     return direction == :horizontal
  235.   end
  236.   def is_vertical?
  237.     return direction == :vertical
  238.   end
  239.   def is_sprite?
  240.     return direction == :none
  241.   end
  242. end
  243.  
  244. ##
  245. # Visual representation
  246. #
  247. class Plane_Panorama < Plane
  248.   attr_accessor :panorama
  249.  
  250.   def initialize(panorama, viewport)
  251.     if viewport != nil
  252.       super(viewport)
  253.     else
  254.       super()
  255.     end
  256.     self.panorama = panorama
  257.     refresh
  258.   end
  259.  
  260.   def update
  261.     # Update panorama plane
  262.     old_name = panorama.name
  263.     panorama.update
  264.     self.z = panorama.z
  265.     self.ox = panorama.ox
  266.     self.oy = panorama.oy
  267.     if panorama.name != old_name
  268.       refresh
  269.     end
  270.   end
  271.  
  272.   def refresh
  273.     self.bitmap = RPG::Cache.panorama(panorama.name, panorama.hue)
  274.   end
  275. end
  276.  
  277. ##
  278. # Manages a panorama plane where the tiling happens in one direction
  279. # The associated viewport is modified dynamically to manage the positioning
  280. # and to ensure no tiling is shown in the other direction.
  281. #
  282. class PartialPlane_Panorama < Plane_Panorama
  283.   attr_accessor :rect
  284.   def initialize(panorama, viewport = nil)
  285.     # Ensure we have a viewport to work with
  286.     if viewport.nil?
  287.       viewport = Viewport.new(0, 0, 640, 480)
  288.       viewport.z = panorama.z
  289.     end
  290.     # Store a reference to its rect. We will use this later for easy access
  291.     self.rect = viewport.rect
  292.     super(panorama, viewport)
  293.   end
  294.  
  295.   def refresh
  296.     super
  297.     # Bitmap is now available for access. Adjust viewport size
  298.     size_update
  299.   end
  300.  
  301.   def size_update
  302.     unless panorama.is_horizontal?
  303.       rect.height = bitmap.rect.height
  304.     end
  305.     unless panorama.is_vertical?
  306.       rect.width = bitmap.rect.width
  307.     end
  308.   end
  309.  
  310.   def update
  311.     old_name = panorama.name
  312.    
  313.     # Update model
  314.     panorama.update
  315.    
  316.     # Apply updated panorama properties
  317.     self.viewport.z = panorama.z
  318.     update_x(panorama.ox)
  319.     update_y(panorama.oy)
  320.    
  321.     # Name change implies a new animation frame
  322.     if panorama.name != old_name
  323.       refresh
  324.     end
  325.    
  326.     # Screen tone may change
  327.     unless $game_screen.nil?
  328.       self.tone = $game_screen.tone
  329.     end
  330.   end
  331.  
  332.   DISPLAY_TO_PIXEL_FACTOR = 4
  333.   def update_x(value)
  334.     if is_vertical?
  335.       self.ox = value
  336.     else
  337.       rect.x = -value / DISPLAY_TO_PIXEL_FACTOR
  338.     end
  339.   end
  340.   def update_y(value)
  341.     if is_horizontal?
  342.       self.oy = value
  343.     else
  344.       rect.y = -value / DISPLAY_TO_PIXEL_FACTOR
  345.     end
  346.   end
  347.  
  348.   def is_horizontal?
  349.     return panorama.is_horizontal?
  350.   end
  351.   def is_vertical?
  352.     return panorama.is_vertical?
  353.   end  
  354. end
  355.  
  356. ##
  357. # Sprite set updates
  358. #
  359. class Spriteset_Map
  360.   attr_sec_accessor :multi_panorama, '{}'
  361.  
  362.   alias zeriab_multipan_spritesetmap_update update
  363.   def update
  364.     zeriab_multipan_spritesetmap_update
  365.     # Update based upon game map panoramas
  366.     map_panorama = $game_map.multi_panorama
  367.     for symbol, panorama in map_panorama
  368.       plane = multi_panorama[symbol]
  369.       if !plane
  370.         plane = add_panorama(symbol, panorama)
  371.       end
  372.       plane.update
  373.     end
  374.     # Dispose remove panoramas
  375.     old_panoramas = multi_panorama.keys - map_panorama.keys
  376.     for symbol in old_panoramas
  377.       dispose_panorama(symbol)
  378.     end
  379.   end
  380.  
  381.   def add_panorama(symbol, game_panorama)
  382.     if game_panorama.is_full_plane?
  383.       plane_panorama = Plane_Panorama.new(game_panorama, @viewport1)
  384.     else
  385.       plane_panorama = PartialPlane_Panorama.new(game_panorama)
  386.     end
  387.     multi_panorama[symbol] = plane_panorama
  388.     plane_panorama
  389.   end
  390.  
  391.   def dispose_panorama(symbol)
  392.     # Clean-up panorama
  393.     panorama = multi_panorama[symbol]
  394.     return unless panorama
  395.     panorama.dispose unless panorama.disposed?
  396.     multi_panorama[symbol] = nil
  397.   end
  398. end
  399.  
  400. ##
  401. # Interpreter integration
  402. #
  403. class Interpreter
  404.   def create_panorama(symbol, name, hue)
  405.     panorama = Game_Panorama.new(symbol, name, hue)
  406.     $game_map.add_panorama(symbol, panorama)
  407.   end
  408.  
  409.   def remove_panorama(symbol)
  410.     $game_map.remove_panorama(symbol)
  411.   end
  412.  
  413.   def update_panorama_name(symbol, name)
  414.     panorama = $game_map.get_panorama(symbol)
  415.     panorama.name = name if panorama
  416.   end
  417.   def update_panorama_hue(symbol, hue)
  418.     panorama = $game_map.get_panorama(symbol)
  419.     panorama.hue = hue if panorama
  420.   end
  421.  
  422.   def update_panorama_z(symbol, z)
  423.     panorama = $game_map.get_panorama(symbol)
  424.     panorama.z = z if panorama
  425.   end
  426.  
  427.   def update_panorama_xdiv(symbol, x_div)
  428.     panorama = $game_map.get_panorama(symbol)
  429.     panorama.x_div = x_div if panorama
  430.   end
  431.  
  432.   def update_panorama_ydiv(symbol, y_div)
  433.     panorama = $game_map.get_panorama(symbol)
  434.     panorama.y_div = y_div if panorama
  435.   end
  436.  
  437.   def update_panorama_ox(symbol, offset_x)
  438.     panorama = $game_map.get_panorama(symbol)
  439.     panorama.offset_x = offset_x if panorama
  440.   end
  441.  
  442.   def update_panorama_oy(symbol, offset_y)
  443.     panorama = $game_map.get_panorama(symbol)
  444.     panorama.offset_y = offset_y if panorama
  445.   end
  446.  
  447.   def move_panorama_ox(symbol, move_ox)
  448.     panorama = $game_map.get_panorama(symbol)
  449.     panorama.offset_x += move_ox if panorama
  450.   end
  451.  
  452.   def move_panorama_oy(symbol, move_oy)
  453.     panorama = $game_map.get_panorama(symbol)
  454.     panorama.offset_y += move_oy if panorama
  455.   end
  456.  
  457.   def start_move_panorama_ox(symbol, move_ox)
  458.     panorama = $game_map.get_panorama(symbol)
  459.     panorama.move_ox = move_ox if panorama
  460.   end
  461.  
  462.   def start_move_panorama_oy(symbol, move_oy)
  463.     panorama = $game_map.get_panorama(symbol)
  464.     panorama.move_oy = move_oy if panorama
  465.   end
  466.  
  467.   def stop_move_panorama(symbol)
  468.     start_move_panorama_ox(symbol, 0)
  469.     start_move_panorama_oy(symbol, 0)
  470.   end
  471.  
  472.   def stop_panorama(symbol)
  473.     panorama = $game_map.get_panorama(symbol)
  474.     unless panorama.nil?
  475.       panorama.stop
  476.       stop_move_panorama(symbol)
  477.     end
  478.   end
  479. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement