Chaos Project

RPG Maker => RPG Maker Scripts => RMVX Script Database => Topic started by: modern algebra on July 26, 2008, 11:59:26 pm

Title: [VX] Sound Emitting Areas
Post by: modern algebra on July 26, 2008, 11:59:26 pm
Sound Emitting Area
Authors: modern algebra
Version: 1.0b
Type: Music Environment Effect
Key Term: Environment Add-on



Introduction

This script allows you to set a bgm, bgs, se, or me to areas and itdynamically changes the volume depending on how far the player is from the area, creating the impression that the sound is emitting from that area.


Version History




Features




Screenshots

Not applicable for this script. See the Demo for a better understanding of the script.


Demo

http://www.sendspace.com/file/n2nu5f


Script
Spoiler: ShowHide

#==============================================================================
#  Sound Emitting Areas (VX)
#  Version 1.0b
#  Author: modern algebra (rmrk.net)
#  Date: July 26, 2008
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Description:
#    This script allows you to set a bgm, bgs, se, or me to areas and it
#    dynamically changes the volume depending on how far the player is from the
#    area, creating the impression that the sound is emitting from that area.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Instructions:
#    See the CONFIGURABLE REGION at line 45
#==============================================================================

#==============================================================================
# ** RPG::Area
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Summary of Changes:
#    new instance variables - se_frames, se_frame_variance, me_frames,
#                             me_frame_variance
#    new methods - setup_sound_emissions, bgm, bgs, me, se, bgm?, bgs?, se?,
#                me?, volume, update_se, update_me
#==============================================================================

class RPG::Area
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Public Instance Variables
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  attr_reader   :se_frames
  attr_reader   :se_frame_variance
  attr_reader   :me_frames
  attr_reader   :me_frame_variance
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Setup Sound Emissions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def setup_sound_emissions
    # Set Default Values
    @bgs_name, @bgs_pitch, @bgs_radius, @bgs_max_volume = '', 100, 10, 100
    @bgm_name, @bgm_pitch, @bgm_radius, @bgm_max_volume = '', 100, 10, 100
    @se_name, @se_pitch, @se_radius, @se_max_volume = '', 100, 10, 100
    @me_name, @me_pitch, @me_radius, @me_max_volume = '', 100, 10, 100
    @se_frames, @se_frame_variance, @me_frames, @me_frame_variance = 20, 0, 20, 0
    case @id
    #\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    #  !*!*! CONFIGURABLE REGION
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #  Set this region up in this way:
    #   
    #    when area_id
    #      @bgm_name = 'Name of BGM you wish to emit'
    #      @bgm_pitch = the pitch of the BGM, from 50 to 150
    #      @bgm_radius = the radius, in squares, of BGM range.
    #      @bgm_max_volume = The maximum volume of the BGM
    #      @bgs_name = 'Name of BGS you wish to emit'
    #      @bgs_pitch = the pitch of the BGS, from 50 to 150
    #      @bgs_radius = the radius, in squares, of BGS range.
    #      @bgs_max_volume = The maximum volume of the BGS
    #      @se_name = 'Name of SE you wish this area to emit'
    #      @se_pitch = the pitch of the SE, from 50 to 150
    #      @se_radius = the radius, in squares, of the SE range
    #      @se_max_volume = the maximum volume of the SE
    #      @se_frames = the average number of frames between playing the SE
    #      @se_frame_variance = how many more or less frames off the average is the range
    #      @me_name = 'Name of ME you wish this area to emit'
    #      @me_pitch = the pitch of the ME, from 50 to 150
    #      @me_radius = the radius, in squares, of the ME range
    #      @me_max_volume = the maximum volume of the ME
    #      @me_frames = the average number of frames between playing the ME
    #      @me_frame_variance = how many more or less frames off the average is the range
    #
    #  You can omit any of the above stats and they will set to default values,
    #    which are there are no names set, pitch = 100, radius = 10,
    #    max_volume = 100, frames = 20, and frame_variance = 0.
    #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    when 1 # Waterfall
      # BGS
      @bgs_name = 'River'
      @bgs_radius = 15
      @bgs_max_volume = 110
    when 4 # Chicken Coop
      # SE
      @se_name = 'Chicken'
      @se_max_volume = 75
      @se_frames = 120        # 120 average number of frames between chicken SE
      @se_frame_variance = 40 # [(120-40) - (120+40)] = 80-160 => Frame Range
    #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    #  !*!*! END CONFIGURABLE REGION
    #////////////////////////////////////////////////////////////////////////
    end
    # Initialize frame counts
    @se_frame_count = @se_frames + rand (2*@se_frame_variance) - @se_frame_variance
    @me_frame_count = @me_frames + rand (2*@me_frame_variance) - @me_frame_variance
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Update Sound
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def update_sound
    bgm.play if @bgm_name != ''
    bgs.play if @bgs_name != ''
    update_se if @se_name != ''
    update_me if @me_name != ''
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * BGM
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def bgm
    @bgm = RPG::BGM.new (@bgm_name, 0, @bgm_pitch) if @bgm == nil
    @bgm.volume = volume (@bgm_radius, @bgm_max_volume)
    return @bgm
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * BGS
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def bgs
    @bgs = RPG::BGS.new (@bgs_name, 0, @bgs_pitch) if @bgs == nil
    @bgs.volume = volume (@bgs_radius, @bgs_max_volume)
    return @bgs
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * SE
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def se
    @se = RPG::SE.new (@se_name, 0, @se_pitch) if @se == nil
    @se.volume = volume (@se_radius, @se_max_volume)
    return @se
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * SE Update
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def update_se
    if @se_frame_count == 0
      se.play
      @se_frame_count = @se_frames + rand (2*@se_frame_variance) - @se_frame_variance
    else
      @se_frame_count -= 1
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * ME
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def me
    @me = RPG::ME.new (@me_name, 0, @me_pitch) if @me == nil
    @me.volume = volume (@me_radius, @me_max_volume)
    return @me
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * ME Update
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def update_me
    if @me_frame_count == 0
      me.play
      @me_frame_count = @me_frames + rand (2*@me_frame_variance) - @me_frame_variance
    else
      @me_frame_count -= 1
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Volume
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def volume (radius, max_volume)
    x, y = $game_player.x, $game_player.y
    # Determine distance between position and the sound emitting object
    xd, yd = x - @rect.x, y - @rect.y
    # Evaluate X distance
    xd > 0 ? xd = x.between? (@rect.x, @rect.x + @rect.width) ? 0 : xd - @rect.width : xd *= -1
    # Evaluate Y distance
    yd > 0 ? yd = y.between? (@rect.y, @rect.y + @rect.height) ? 0 :yd - @rect.height : yd *= -1
    # Calculate the total distance
    total_distance = Math.sqrt(xd*xd + yd*yd).ceil.to_i
    # Get the percentage of max volume
    percent = (total_distance.to_f / radius.to_f)*100
    percent = (100 - [percent, 100].min).to_f / 100.0
    return (percent*max_volume.to_f).to_i
  end
end

#==============================================================================
# ** Game_Map
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Summary of Changes:
#    aliased method - update, setup
#==============================================================================

class Game_Map
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Setup
  #    map_id : the ID of the map
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias modalg_dynamic_snd_emit_stup_rn4 setup
  def setup(map_id)
    # Run Original Method
    modalg_dynamic_snd_emit_stup_rn4 (map_id)
    # Get all areas that belong to this map
    @areas = []
    $data_areas.values.each { |area| @areas.push (area) if map_id == area.map_id }
    # Ensure Area Sound Effects are setup
    @areas.each { |i| i.setup_sound_emissions if i.se_frames == nil }
    @advanced_areas_included = false
    begin
      # Test for exception thrown on .active?
      $data_areas[1].active?
      @advanced_areas_included = true
    rescue
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Update
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias modalg_dyn_sound_emitting_objects_upd_4h3 update
  def update
    # Run Original Map
    modalg_dyn_sound_emitting_objects_upd_4h3
    # For all area
    @areas.each { |area|
      next if @advanced_areas_included && !area.active?
      area.update_sound
    }
  end
end



Instructions

See inside the script.


Compatibility

There should not be any Compatibility errors. If there are, post either here or RMRK.net .


Credits and Thanks




Author's Notes

Please post at rmrk.net for the swiftest support, as I am not as active here as I should be.

This script is based off of the version I wrote for RMXP with a number of significant alterations. This script is completely compatible with my Advanced Areas script (http://rmrk.net/index.php/topic,25247.0.html), and I recommend it if you do not want the sounds playing all the time, as the Advanced Areas script includes a way to turn the area off by a switch and this script will recognize that command as well.