Dynamic Sound Emitting Events
Version: 1.0.5
Author: modern algebra
Date: 30 March 2014
Version History
- <Version 1.0.5> 2014.03.30 - Added the min_volume feature
- <Version 1.0.4> 2012.10.27 - Added the source_radius feature
- <Version 1.0.3> 2012.10.04 - Necessary bug fixes from the changes in 1.0.2
- <Version 1.0.2> 2012.10.03 - Fixed a bug where emissions would keep playing when the player transfers to a new map that has no BGS or BGM set to autoplay.
- <Version 1.0.1> 2012.10.01 - Introduced an option to help reduce lag
- <Version 1.0.0> 2012.09.30 - Original Release
Description
This script allows you to create events that emit sounds whose volume depends on the distance that the event is from the player. In other words, the closer the player is to the event, the louder the sound. It works for SEs, MEs, BGMs and BGSes.
Features
- Can easily make it seem as if any sound is coming from an event, by varying the volume.
- Can set automatic SEs for realistic animal noises whose volume also varies by distance.
- Can set all the relevant properties, from maximum volume to pitch to radius.
- Can set a source radius, within which the sound will play at maximum volume
- Can enlargen the emission source to a rectangle of any size without repeating emission events.
- Simple and intuitive comment settings
Instructions
Paste the script into its own slot in the Script Editor, above Main but below Materials.
For instructions on setting the sound emitting events up, see the header of the script.
Script
#==============================================================================
# Dynamic Sound Emitting Events
# Version: 1.0.5
# Author: modern algebra (rmrk.net)
# Date: 30 March 2014
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Description:
#
# This script allows you to create events that emit sounds whose volume
# depends on the distance that the event is from the player. In other words,
# the closer the player is to the event, the louder the sound. It works for
# SEs, MEs, BGMs and BGSes, but note that you can only use one BGM or BGS at
# a time, so you can't have a map BGM or BGS simultaneously, nor can you have
# more than one event play a BGM or BGS.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Instructions:
#
# Paste this script into its own slot in the Script Editor, above Main but
# below Materials.
#
# To set this script up, you need to insert an event comment as the first
# line on an event's page. If you need more space, you can also create more
# comments immediately after the first. Next, you need to insert codes in
# the following formats:
#
# \emit_BGM {
# name = ""
# min_volume = 0
# max_volume = 80
# pitch = 100
# radius = 15
# source_radius = 0
# }
#
# Change BGM to whatever type of sound effect you want to emit. It can be
# BGM, BGS, SE, or ME. Each event can only emit one type of sound. The values
# listed for each property above are the default values if you choose to omit
# them. The only one that is required to be directly set everytime is the
# name. They also do not need to all be on separate lines, you can also
# separate them by semicolons. All the properties do what you would expect:
#
# name = ""
# Place the name of the sound file you want to play between the " "
# min_volume = 0
# Replace 0 with the volume of the sound when completely out of range.
# max_volume = 80
# Replace 80 with the maximum volume of the sound
# pitch = 100
# Replace 100 with the pitch you want for the sound.
# radius = 15
# Replace 15 with the radius of the sound. Unless the player is within
# that number of squares, he or she won't hear the sound at all. As he
# or she approaches the event, the volume will increase proportionate
# to the max_volume.
# source_radius = 0
# This is the radius around the source where the sound is at maximum
# volume. This is added to the radius, so if, for instance, this is 2
# and radius is 6, then the sound will play at max volume when within
# a radius of 2 of the event, and the sound will only be silent
# completely once the player is outside of a radius of 8.
#
# If you are using SEs or MEs, then there are two additional properties.
# Firstly, you can set a range for the pitch, and the pitch will be chosen
# at random from within that range, like this:
#
# pitch = 75...125
#
# In that example, the pitch would be somewhere between 75 and 125 each time
# it played, and it would reselect randomly every time it plays. The other
# thing you can set for SEs and MEs is the time, which you choose in frames
# (60 frames is 1 second) and this similarly allows you to choose either an
# integer or a range. Example 1:
#
# time = 120
#
# In that example, the SE would play every 120 frames (2 seconds) exactly.
# Example 2:
#
# time = 600...900
#
# In this example, the time would be selected randomly from that range,
# meaning it would play every 600-900 frames (10-15 seconds). So one time it
# might be 12 seconds, another time it might be 11, etc..
#
# Finally, there is one more feature. If you want the source of the sound to
# be bigger than just one square (for instance, if you want it to be a
# waterfall that is 4 squares across and 3 squares down), then you can do that
# by placing the event at the upper left corner of the rectangle and adding
# the x and y additions in square brackets right after the BGM/BGS/SE/ME
# setting, like so:
#
# \emit_BGS[x, y] { ... }
#
# In the waterfall case, it would be [3, 2], since the first square is
# already included.
#``````````````````````````````````````````````````````````````````````````````
# EXAMPLES:
#
# \emit_BGM { name = "Fire" }
#
# This event would emit the "Fire" BGM. Since no other properties are set,
# they assume the default values: volume = 80; pitch = 100; radius = 15.
#
# \emit_BGS[0, 4] {
# name = "River"; volume = 100;
# radius = 10 }
#
# This event would emit the "River" BGS. Its source is extended to include
# the 4 squares below the event, so the source will be 5 squares, including
# the event's square. The volume when you are on any of those squares is
# 100, and as you move away, the volume will decrease proportionate to the
# square to which you are closest. The radius is 10, so once you are no
# longer within 10 squares of any of the source squares, you will no longer
# hear it.
#
# \emit_SE { name = "Dog";
# radius = 12; pitch = 90..120;
# time = 420...720; source_radius = 3 }
#
# This event will play the "Dog" SE every 7 - 12 seconds. When it does,
# its pitch will be randomly selected from between 90 and 120. The
# source_radius is 3, so the SE will play at max volume if within three
# squares of the dog, and since the radius is 12 squares, this means that
# the total radius is 15 squares.
#``````````````````````````````````````````````````````````````````````````````
# If you are worried about lag, then please go to line 149 and change the
# value of SMOOTH_TRANSITION to false.
#==============================================================================
$imported = {} unless $imported
$imported[:MA_DynamicSoundEmittingEvents] = true
#==============================================================================
# ** Sound Emitter
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# This class holds sound emission data and updating methods
#==============================================================================
class MA_SoundEmitter
#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
# EDITABLE REGION
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# SMOOTH_TRANSITION - When this value is set to true, changes in volume will
# sound slightly smoother as the player or event moves. If set to false, then
# the increments by which the volume jumps is quite a bit greater, but this
# should only be very noticeable at small radiuses. For the best effect, I
# recommend you set this value to true, but if you are worried about lag
# then you should set it to false.
SMOOTH_TRANSITION = true
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# End EDITABLE REGION
#////////////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Public Instance Variables
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
attr_accessor :event_id
attr_accessor :sound_type
attr_accessor :radius
attr_accessor :source_radius
attr_accessor :min_volume
attr_accessor :max_volume
attr_accessor :pitch
attr_accessor :time
attr_accessor :size_x
attr_accessor :size_y
attr_reader :filename
attr_reader :audiofile
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Object Initialize
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def initialize(event_id = 0)
@event_id = event_id
clear
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Clear
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def clear
RPG.const_get(@sound_type).stop if audiofile && @sound_type == :BGM || @sound_type == :BGS
@sound_type = :SE
@radius = 15
@source_radius = 0
@min_volume = 0
@max_volume = 80
@pitch = 100
@time = 600..900
@player_x, @player_y = -1, -1
@event_x, @event_y = -1, -1
@size_x, @size_y = 0, 0
load_audiofile("")
reset_timer
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Frame Update
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def update
return unless audiofile && $game_map.events[event_id]
case @sound_type
when :SE, :ME
return unless update_se_me?
audiofile.volume = calc_volume if recalc_vol?
audiofile.pitch = calc_pitch
reset_timer
when :BGM, :BGS
return unless recalc_vol?
new_vol = calc_volume # Distance calculation
# If variation < 3 and not transitioning to limit
return if audiofile.volume == new_vol ||
(audiofile.volume.between?(new_vol - 2, new_vol + 2) &&
(audiofile.volume != 0 && new_vol != 0) &&
(audiofile.volume != max_volume && new_vol != max_volume))
audiofile.volume = new_vol
end
audiofile.play
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Update SE/ME?
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def update_se_me?
if @timer > 0 # If timer not counted down
@timer -= 1 # Reduce timer
return false
end
return true
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Recalculate Volume?
# * Reset Position Vars
#``````````````````````````````````````````````````````````````````````````
# Done this way to account for the value of SMOOTH_TRANSITION
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pos_val = SMOOTH_TRANSITION ? "real_" : ""
madsee_pos_methods = <<POS_END
def recalc_vol?
event = $game_map.events[event_id]
!(@player_x == $game_player.#{pos_val}x && @event_x == event.#{pos_val}x &&
@player_y == $game_player.#{pos_val}y && @event_y == event.#{pos_val}y)
end
def reset_position_vars
event = $game_map.events[event_id]
@player_x, @player_y = $game_player.#{pos_val}x, $game_player.#{pos_val}y
@event_x, @event_y = event.#{pos_val}x, event.#{pos_val}y
end
POS_END
eval(madsee_pos_methods)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Reset Timer
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def reset_timer
@timer = time.is_a?(Integer) ? time : time.first + rand(time.last - time.first)
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Calculate Volume
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def calc_volume
reset_position_vars
r = radius + source_radius + 1
# Get real horizontal distance between emitter and player
raw_dist_x = @player_x - @event_x
dist_x = raw_dist_x > 0 ? [raw_dist_x - @size_x, 0].max : -raw_dist_x
if $game_map.loop_horizontal? # Accomodate if map looping
loop_x = [$game_map.width - dist_x - @size_x, 0].max
dist_x = loop_x if loop_x < dist_x
end
return min_volume if dist_x > r
# Get real vertical distance between emitter and player
raw_dist_y = @player_y - @event_y
dist_y = raw_dist_y > 0 ? [raw_dist_y - @size_y, 0].max : -raw_dist_y
if $game_map.loop_vertical? # Accomodate if map loops vertically
loop_y = [$game_map.height - dist_y - @size_y, 0].max
dist_y = loop_y if loop_y < dist_y
end
return min_volume if dist_y > r
# Get diagonal distance
dist = Math.hypot(dist_x, dist_y)
return min_volume + (dist > r ? 0 : (([(r - dist) / (r - source_radius), 1].min)*(max_volume - min_volume)).to_i)
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Calculate Pitch
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def calc_pitch
pitch.is_a?(Integer) ? pitch : pitch.first + rand(pitch.last - pitch.first)
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Load AudioFile
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def load_audiofile(filename = @filename)
@filename = filename
@audiofile = RPG.const_get(@sound_type).new(@filename)
@audiofile.pitch = calc_pitch
end
alias :"filename=" :load_audiofile
end
#==============================================================================
# ** Game_Map
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Summary of Changes:
# aliased methods - setup
#==============================================================================
class Game_Map
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Setup Events
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
alias madsee_setup_3kq4 setup
def setup(*args)
# Clear Emitters if they were present in last map, primarily to stop the
# them if they are playing BGMs or BGSes.
@events.values.each { |e|
e.madsee_emitter.clear if e.madsee_emitter } if @events
madsee_setup_3kq4(*args) # Call original method
end
end
#==============================================================================
# ** Game_Event
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Summary of Changes:
# aliased methods - initialize; clear_page_settings; setup_page_settings;
# update
# new method - madsee_emitter; madsee_setup_emitter; ma_collect_init_comment
#==============================================================================
class Game_Event
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Public Instance Variables
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
attr_reader :madsee_emitter
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Setup Page Settings
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
alias madsee_stuppges_6ag6 setup_page_settings
def setup_page_settings(*args)
madsee_stuppges_6ag6(*args) # Call original method
madsee_setup_emitter
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Clear Page Settings
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
alias madsee_clrpageset_4sm7 clear_page_settings
def clear_page_settings(*args)
madsee_clrpageset_4sm7(*args) # Call original method
@madsee_emitter.clear if @madsee_emitter
@madsee_emitter = nil
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Setup Emitter
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def madsee_setup_emitter
# Collect First comment
comment = ma_collect_init_comment
if comment[/\\EMIT[_ ](BGM|BGS|ME|SE)\[?(\d*)[;;,\s]*(\d*)\]?\s*\{(.+?)\}/mi]
@madsee_emitter ? @madsee_emitter.clear : @madsee_emitter = MA_SoundEmitter.new(@id)
@madsee_emitter.sound_type = $1.upcase.to_sym
@madsee_emitter.size_x = $2.to_i
@madsee_emitter.size_y = $3.to_i
props = $4.dup
props.gsub!(/(?<!file)name/i) { "filename" }
props.gsub!(/(?<!_)volume/i) { "max_volume" }
props.split(/[\n;]+/).each { |expression|
if expression[/\A\s*(.+?)\s*=\s*(.+?)\s*\Z/]
@madsee_emitter.send(:"#{$1.downcase}=", eval($2)) rescue msgbox("#{$1.downcase} is not a valid property for a Sound Emitting Event")
end
}
@madsee_emitter.audiofile.pitch = @madsee_emitter.calc_pitch
@madsee_emitter.reset_timer
@madsee_emitter = nil if @madsee_emitter.filename.empty?
else
@madsee_emitter.clear if @madsee_emitter
@madsee_emitter = nil
end
end
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Collect First Comment
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def ma_collect_init_comment
comment, i = "", 0
while !@list[i].nil? && (@list[i].code == 108 || @list[i].code == 408)
comment += @list[i].parameters[0] + "\n"
i += 1
end
comment
end unless self.method_defined?(:ma_collect_init_comment)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# * Frame Update
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
alias madsee_updt_1ex0 update
def update(*args)
madsee_updt_1ex0(*args) # Call original method
@madsee_emitter.update if @madsee_emitter
end
end
Credit
Thanks
- Yin, for alerting me to some lag and inspiring the option to turn SMOOTH_TRANSITION off
Support
Please post in this topic at RMRK if you have any comments, questions, suggestions, or error reports. Even if this topic is really old, do not be afraid to necropost. Please do not send me a private message, as I would like other people who might have the same problem to be able to see the solution.
Known Compatibility Issues
I am currently unaware of any compatibility problems, but please let me know if you encounter any. There might be problems with pixel movement or isometric scripts.
Demo
See attached (http://rmrk.net/index.php?action=dlattach;topic=46842.0;attach=30454).
Author's Notes
The VX version of this script was terribly written and laggy. I have tried to improve it and I think I have succeeded, but please let me know if you are encountering any issues with lag when using this script.
Terms of Use
I adopt RMRK's default Terms of Use (http://rmrk.net/index.php/topic,45481.0.html).
For some reason this causes a lot of lag for me. (Only when I am within range of a sound emitting object. No matter the map) But it works fine in the demo, so it must be incompatibility or something.
Edit:
It's not so much lag, it's more like... slow motion.
How many sound emitting events are there on the map. Also it is weird that it doesn't happen in the demo. Could you maybe upload the project or a recreation of the error if you can?
It's just one event (fire). It happens on 2 maps the first map is my test map which probably should lag since it has so much stuff on it, but the first map of the game also has the same fire. It doesn't really have anything except the a few lines of text and a fire place. I'll PM it to you in a bit
Thanks, I will take a look.
Alright, well, wow, you have a lot of scripts and I think they are partially responsible (I'm only getting around 42 FPS even without this script), but I could definitely notice the slowdown you were talking about. Currently, the script is written to respond to changes in the real position of the sprites whenever they move (8 changes per move), and it appears that the repeated call of the play method is what is causing the slowdown. Now, I don't know that there's any way I can fix that and keep the more gradual change in volume, but I can add an option so that the script only responds to changes in logical position. In other words, the script will only shift once per move. It will be less gradual and that might be noticeable especially at low radius emissions, but it won't cause the lag.
Ahh, well, I knew that much. I just noticed that you said to mention if we find any lag :P (In my case, you can say extra lag) Although having the extra option would be a great addition for people like me (who don't really have everything optimized). Though I should probably do some cleaning up anyway to get rid of the 47fps frame rate I'm getting even without this. Either way, I like this script, so I'll most likely be using it :) Thanks.
Alright, I added that option. Get the script from the first post and just change the SMOOTH_TRANSITION constant at line 137 to false.
And thank you for reporting the lag. It has helped to improve this script, and for that I am always grateful.
Awesome! That was fast too.
The new version is great, no lag at all with or without the smoothing. I don't know if you made extra changes or if my cleanup really helped, but it's working much better now!
I did modify smooth mode a little bit, since I figured minor changes in volume were generally not noticeable. It wasn't enough to make a difference in my copy of your test map though, so whatever cleanup you did likely made a difference too.
Updated to 1.0.2 to fix a bug where BGM- and BGS-emitting events would keep playing when the player transfers to a new map that has no autoplaying BGMs or BGSes.
With the new version there is an error at the game start (In the demo too):
---------------------------
Dynamic Sound Emitting Events 1.0.1
---------------------------
Script 'Sound Emitting Events' line 366: NoMethodError occurred.
undefined method `defined?' for #<Array:0x868178c>
---------------------------
OK
---------------------------
This is the line
end unless methods.defined?(:ma_collect_init_comment)
Sorry, it should be:
end unless self.method_defined?(:ma_collect_init_comment)
Now I'm getting two different errors, one in my game and one in the demo.
Demo's error:
---------------------------
Dynamic Sound Emitting Events 1.0.1
---------------------------
Script 'Sound Emitting Events' line 294: NoMethodError occurred.
undefined method `madsee_setupevents_3kq4' for #<Game_Map:0x88eda98>
---------------------------
OK
---------------------------
That line is:
madsee_setupevents_3kq4(*args) # Call original method
I fixed it by renaming it without the events part (I thought it was calling the wrong alias or something)
Then I get the same error as with my game in the demo:
---------------------------
Dynamic Sound Emitting Events 1.0.1
---------------------------
Script 'Sound Emitting Events' line 181: NameError occurred.
undefined local variable or method `event' for #<MA_SoundEmitter:0x88ebc98>
---------------------------
OK
---------------------------
That line is:
return unless audiofile && event
I "fixed" that by adding:
event = $game_map.events[event_id] before that line, but I'm not sure if that breaks anything or not.
You were right on renaming the alias. I think the undefined 'event' is supposed to be @event_id (though that's my first impression looking at the attrs, so I don't actually know).
My question to you Modern is, why does this section of the script have lack of colour in the script editor? even keywords ;9 I've never seen that before.
(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg4host.net%2Fupload%2F04202634506dd4dab7310.png&hash=520b31eb62e879d9c00df1f1193516a8473ff683)
You're right about the fixes, Yin. Sorry for not testing the update, and thank you for the quick report.
@D&P3 - Will get back to you on the details soon, but as I am short on time for the moment, that is basically just weird syntax for creating a string.
EDIT::
@D&P3 - Alright, so basically, that is a heredoc (http://rubyquicktips.com/post/4438542511/heredoc-and-indent), and it is just a way to write a string and have tab and newline characters processed more naturally. I don't know why the interpreter chooses to make heredocs black.
Anyway, I chose to use a heredoc since I find that much easier to write and read than putting it in a regular string. It is a mistake to use _END_ as my delimiter though, so I should change that. I copied it from old code I think.
And the reason I do it that way and use eval in this script to interpret is just because I figure there is no need to always check the value of SMOOTH_TRANSITION every time the method is called, so I should just write the method differently depending on whether SMOOTH_TRANSITION is on. It is effectively the same as:
if SMOOTH_TRANSITION
def recalc_vol?
event = $game_map.events[event_id]
!(@player_x == $game_player.real_x && @event_x == event.real_x &&
@player_y == $game_player.real_y && @event_y == event.real_y)
end
def reset_position_vars
event = $game_map.events[event_id]
@player_x, @player_y = $game_player.real_x, $game_player.real_y
@event_x, @event_y = event.real_x, event.real_y
end
else
def recalc_vol?
event = $game_map.events[event_id]
!(@player_x == $game_player.x && @event_x == event.x &&
@player_y == $game_player.y && @event_y == event.y)
end
def reset_position_vars
event = $game_map.events[event_id]
@player_x, @player_y = $game_player.x, $game_player.y
@event_x, @event_y = event.x, event.y
end
end
Alright, I updated this script to 1.0.4 and added a new source_radius feature. This allows you to set a radius around the event at which the sound will play at maximum volume, and where it will only start to decrease once the player is outside of that radius.
Thank you for the update!
Ah alright, I see what you're doing; guess I've still got things to learn :P
Can I set a direction from which the sound comes from? Say, engine of the car is at the front, you hear the hum of engine louder from front of it than behind?
No, there's no way to do that. You could make the source a bigger rectangle, and that would sort of have that effect if the rectangle protrudes in the direction you want to be louder.
Hello, sorry for the bump. Is there a way to make the sound not disappear at all after you moved far away but just remain in low volume?
Not yet, but I will add a min_volume feature.
Alright, I updated to 1.0.5 and added the min_volume feature.
Thank you very much! <3
There is no smooth transition between music (like if you wanted to have it so there's the slums, the garden, the rich area, and the marketplace, of a town) or waterfall/flames.
Because RPGMaker allows for multiple sound effects but not BGM or BGS.
So, perhaps might you be interested in making it so that RPGMaker can handle multiple of those for this script?
I know that might sound a bit wild, but most modern games I know can fade between one song to another or flame to flame.
I don't expect that I will do that anytime soon. Sorry!
You'll be better off with a crossfade script in that case.
Tried NeonBlack's Crossfade script and all it did was make the BGS' volume stuck where it was.
Without it,
Put two flames 3 squares from either side of the character with a range of 3 (to test) and the BGS fade would often get stuck priorizing the flame on left.
Defaultly, the radius for flames is 15. But flames are often placed in areas within one another's radius or have radius
that cross one another.
I tried to make it by putting audio in the SE folder and had it so an area would emit music once then emit it once more in certain amount of time, but it just did not work out or sound well. Lol.
Hello MA, I was just wondering, I have a sound emitting BGM and SE just not far from it, but for some reason the SE isn't playing. This is what my event looks like:
http://puu.sh/8phBT/03f75ac6f1.png
Did I do something wrong? :o
Not a major thing, but although it goes over two comments you don't need to repeat the "\emit_se {" code. It should just be:
@> | Comment | : | \emit_SE{ |
: | | : | filename = "[redacted] Theme" |
: | | : | min_volume = 25 |
: | | : | max_volume = 100 |
@> | Comment | : | radius = 10 |
: | | : | source_radius = 1 |
: | | : | } |
What was happening was that it ended up just reading the stuff after the second \emit_SE{, which did not include a filename and so nothing played.
Ooh that makes sense. Thank you :D
Zip file for the demo is corrupt :(
Hi foulu. Thank you for bringing that to my attention. I re-uploaded a copy of the demo. I no longer have VX Ace though, so I could not open it to make sure it is the most recent version or not.