Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##
- # Animated panoramas setup model
- #
- module PanoramaSetup
- PanoramaAnimFrame = Struct.new(:name, :wait)
- PanoramaAnim = Struct.new(:frames, :start_index, :direction)
- ##
- # Instance of an animation
- #
- class PanoramaInstance < Struct.new(:anim, :current_index, :running, :ticks)
- def direction
- return anim.direction
- end
- def current_frame
- return anim.frames[current_index]
- end
- def current_name
- current_frame.name
- end
- def next_frame
- self.current_index += 1
- self.current_index %= anim.frames.size
- self.ticks = 0
- end
- def start
- self.running = true
- self.ticks = 0
- self.current_index = anim.start_index
- end
- def update
- if running
- self.ticks += 1
- next_frame if self.ticks >= current_frame.wait
- end
- end
- def stop
- self.running = false
- end
- def resume
- self.running = true
- end
- end
- # Symbol => animation setup map
- Config = {}
- module_function
- def create_default_anim
- return PanoramaAnim.new([], 0, DIRECTION_DEFAULT)
- end
- ##
- # Fetch the animation setup associated with the given symbol
- #
- def fetch_anim(symbol)
- anim = Config[symbol]
- if anim.nil?
- anim = create_default_anim
- Config[symbol] = anim
- end
- return anim
- end
- ##
- # Add frames of the given filename at the end of the given animation.
- # Wait determines how many frames are added.
- #
- def add_frame(symbol, name, wait)
- anim = fetch_anim(symbol)
- frame = PanoramaAnimFrame.new(name, wait)
- anim.frames << frame
- end
- ##
- # Tiling direction setup
- #
- DIRECTION_DEFAULT = :both
- DIRECTION_VALID = [:both, :horizontal, :vertical, :none]
- def tile_direction(symbol, direction)
- # Input validation
- unless DIRECTION_VALID.include?(direction)
- print "Panorama setup error.\n\nInvalid tiling direction #{direction.inspect} given for #{symbol.inspect}"
- exit
- end
- # Update animation metadata
- anim = fetch_anim(symbol)
- anim.direction = direction
- end
- ##
- # Create an animation instance that can be used for playback
- #
- def create_instance(symbol)
- anim = PanoramaSetup::Config[symbol]
- return PanoramaInstance.new(anim, anim.start_index, true, 0)
- end
- end
- ##
- # Store panoramas
- #
- class Game_Map
- attr_sec_accessor :multi_panorama, '{}'
- ##
- # Update panoramas
- #
- unless self.method_defined?('zeriab_multipan_gamemap_update')
- alias zeriab_multipan_gamemap_update update
- end
- def update
- zeriab_multipan_gamemap_update
- for panorama in multi_panorama.values
- panorama.update
- end
- end
- ##
- # Accessors
- #
- def add_panorama(symbol, panorama)
- multi_panorama[symbol] = panorama
- end
- def get_panorama(symbol)
- multi_panorama[symbol]
- end
- def remove_panorama(symbol)
- multi_panorama.delete(symbol)
- end
- ##
- # Clear panoramas on map transfers
- #
- unless self.method_defined?('zeriab_multipan_game_map_setup')
- alias zeriab_multipan_game_map_setup :setup
- end
- def setup(*args)
- multi_panorama.clear
- zeriab_multipan_game_map_setup(*args)
- end
- end
- ##
- # Game panorama concept
- #
- class Game_Panorama
- attr_accessor :symbol
- attr_accessor :hue
- attr_accessor :name
- attr_accessor :z
- attr_accessor :x_div
- attr_accessor :y_div
- attr_accessor :offset_x
- attr_accessor :offset_y
- attr_accessor :ox
- attr_accessor :oy
- attr_accessor :move_ox
- attr_accessor :move_oy
- attr_accessor :anim
- attr_accessor :animated
- attr_accessor :direction
- def initialize(symbol, name, hue)
- self.symbol = symbol
- self.hue = hue
- # Animation specifics
- if name.is_a?(Symbol)
- self.anim = PanoramaSetup.create_instance(name)
- self.name = anim.current_name
- self.direction = anim.direction
- self.animated = true
- else
- self.name = name
- self.animated = false
- self.direction = :both
- end
- # Defaults
- self.z = -500
- self.x_div = 8
- self.y_div = 8
- self.offset_x = 0
- self.offset_y = 0
- self.move_ox = 0
- self.move_oy = 0
- end
- def update
- # Animate
- if animated
- anim.update
- self.name = anim.current_name
- end
- # Apply movement
- self.offset_x += self.move_ox
- self.offset_y += self.move_oy
- # Update panorama plane
- self.ox = (self.offset_x + $game_map.display_x) / self.x_div
- self.oy = (self.offset_y + $game_map.display_y) / self.y_div
- end
- def stop
- if animated
- anim.stop
- end
- end
- ##
- # Helpers
- #
- def is_plane?
- return direction != :none
- end
- def is_full_plane?
- return direction == :both
- end
- def is_partial_plane?
- return is_horizontal? || is_vertical?
- end
- def is_horizontal?
- return direction == :horizontal
- end
- def is_vertical?
- return direction == :vertical
- end
- def is_sprite?
- return direction == :none
- end
- end
- ##
- # Visual representation
- #
- class Plane_Panorama < Plane
- attr_accessor :panorama
- def initialize(panorama, viewport)
- if viewport != nil
- super(viewport)
- else
- super()
- end
- self.panorama = panorama
- refresh
- end
- def update
- # Update panorama plane
- old_name = panorama.name
- panorama.update
- self.z = panorama.z
- self.ox = panorama.ox
- self.oy = panorama.oy
- if panorama.name != old_name
- refresh
- end
- end
- def refresh
- self.bitmap = RPG::Cache.panorama(panorama.name, panorama.hue)
- end
- end
- ##
- # Manages a panorama plane where the tiling happens in one direction
- # The associated viewport is modified dynamically to manage the positioning
- # and to ensure no tiling is shown in the other direction.
- #
- class PartialPlane_Panorama < Plane_Panorama
- attr_accessor :rect
- def initialize(panorama, viewport = nil)
- # Ensure we have a viewport to work with
- if viewport.nil?
- viewport = Viewport.new(0, 0, 640, 480)
- viewport.z = panorama.z
- end
- # Store a reference to its rect. We will use this later for easy access
- self.rect = viewport.rect
- super(panorama, viewport)
- end
- def refresh
- super
- # Bitmap is now available for access. Adjust viewport size
- size_update
- end
- def size_update
- unless panorama.is_horizontal?
- rect.height = bitmap.rect.height
- end
- unless panorama.is_vertical?
- rect.width = bitmap.rect.width
- end
- end
- def update
- old_name = panorama.name
- # Update model
- panorama.update
- # Apply updated panorama properties
- self.viewport.z = panorama.z
- update_x(panorama.ox)
- update_y(panorama.oy)
- # Name change implies a new animation frame
- if panorama.name != old_name
- refresh
- end
- # Screen tone may change
- unless $game_screen.nil?
- self.tone = $game_screen.tone
- end
- end
- DISPLAY_TO_PIXEL_FACTOR = 4
- def update_x(value)
- if is_vertical?
- self.ox = value
- else
- rect.x = -value / DISPLAY_TO_PIXEL_FACTOR
- end
- end
- def update_y(value)
- if is_horizontal?
- self.oy = value
- else
- rect.y = -value / DISPLAY_TO_PIXEL_FACTOR
- end
- end
- def is_horizontal?
- return panorama.is_horizontal?
- end
- def is_vertical?
- return panorama.is_vertical?
- end
- end
- ##
- # Sprite set updates
- #
- class Spriteset_Map
- attr_sec_accessor :multi_panorama, '{}'
- alias zeriab_multipan_spritesetmap_update update
- def update
- zeriab_multipan_spritesetmap_update
- # Update based upon game map panoramas
- map_panorama = $game_map.multi_panorama
- for symbol, panorama in map_panorama
- plane = multi_panorama[symbol]
- if !plane
- plane = add_panorama(symbol, panorama)
- end
- plane.update
- end
- # Dispose remove panoramas
- old_panoramas = multi_panorama.keys - map_panorama.keys
- for symbol in old_panoramas
- dispose_panorama(symbol)
- end
- end
- def add_panorama(symbol, game_panorama)
- if game_panorama.is_full_plane?
- plane_panorama = Plane_Panorama.new(game_panorama, @viewport1)
- else
- plane_panorama = PartialPlane_Panorama.new(game_panorama)
- end
- multi_panorama[symbol] = plane_panorama
- plane_panorama
- end
- def dispose_panorama(symbol)
- # Clean-up panorama
- panorama = multi_panorama[symbol]
- return unless panorama
- panorama.dispose unless panorama.disposed?
- multi_panorama[symbol] = nil
- end
- end
- ##
- # Interpreter integration
- #
- class Interpreter
- def create_panorama(symbol, name, hue)
- panorama = Game_Panorama.new(symbol, name, hue)
- $game_map.add_panorama(symbol, panorama)
- end
- def remove_panorama(symbol)
- $game_map.remove_panorama(symbol)
- end
- def update_panorama_name(symbol, name)
- panorama = $game_map.get_panorama(symbol)
- panorama.name = name if panorama
- end
- def update_panorama_hue(symbol, hue)
- panorama = $game_map.get_panorama(symbol)
- panorama.hue = hue if panorama
- end
- def update_panorama_z(symbol, z)
- panorama = $game_map.get_panorama(symbol)
- panorama.z = z if panorama
- end
- def update_panorama_xdiv(symbol, x_div)
- panorama = $game_map.get_panorama(symbol)
- panorama.x_div = x_div if panorama
- end
- def update_panorama_ydiv(symbol, y_div)
- panorama = $game_map.get_panorama(symbol)
- panorama.y_div = y_div if panorama
- end
- def update_panorama_ox(symbol, offset_x)
- panorama = $game_map.get_panorama(symbol)
- panorama.offset_x = offset_x if panorama
- end
- def update_panorama_oy(symbol, offset_y)
- panorama = $game_map.get_panorama(symbol)
- panorama.offset_y = offset_y if panorama
- end
- def move_panorama_ox(symbol, move_ox)
- panorama = $game_map.get_panorama(symbol)
- panorama.offset_x += move_ox if panorama
- end
- def move_panorama_oy(symbol, move_oy)
- panorama = $game_map.get_panorama(symbol)
- panorama.offset_y += move_oy if panorama
- end
- def start_move_panorama_ox(symbol, move_ox)
- panorama = $game_map.get_panorama(symbol)
- panorama.move_ox = move_ox if panorama
- end
- def start_move_panorama_oy(symbol, move_oy)
- panorama = $game_map.get_panorama(symbol)
- panorama.move_oy = move_oy if panorama
- end
- def stop_move_panorama(symbol)
- start_move_panorama_ox(symbol, 0)
- start_move_panorama_oy(symbol, 0)
- end
- def stop_panorama(symbol)
- panorama = $game_map.get_panorama(symbol)
- unless panorama.nil?
- panorama.stop
- stop_move_panorama(symbol)
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement