[XP] Ryex's Dynamic Sounds UPDATE:Version 2 is out!

Started by Ryex, October 18, 2009, 01:50:39 am

Previous topic - Next topic

Ryex

October 18, 2009, 01:50:39 am Last Edit: November 19, 2010, 06:28:19 pm by Ryexander
Ryex's Dynamic Sounds
Authors: Ryex
Version: 2.04
Type: Sound Effect
Key Term: Custom Environment System



Introduction

This is a dynamic sound system built on the DEE.



Features


  • Creates Dynamic BGS Sound effects
  • Creates Dynamic SE Sound effects
  • Can be easily set up through events
  • Sources and pieces can be muted
  • SE effects can be set up to repeat every x number of frames



Screenshots

NA



Demo

UPDATE: this is a new demo with no lag
Media Fire



Script

UPDATE NO LAG
http://docs.google.com/Doc?docid=0AUKLI9M5vfiOZGdiNXdnMjVfMjFjMzI4Zm5jNg&hl=en

NOTE: if you get the script from here you also need to install the DEE
http://forum.chaos-project.com/index.php?topic=4809.msg89394#new

place the DEE ABOVE Dynamic Sounds

Blizz ABS Plug in

this plug in enables sources that are placed in enemy event to automatically be muted when the enemy dies it is included in the demo (disabled read the top for instructions to re-enable it) or you can get it below
http://docs.google.com/Doc?docid=0AUKLI9M5vfiOZGdiNXdnMjVfMjJkcjJrbWdjbg&hl=en



Instructions

There is a manual located here in PDF form it describes everything you need to know to use this system.


NOTE: It is required to have the DEE installed for this script to work.





Compatibility

should work with just about any thing



Credits and Thanks


  • Ryex



Author's Notes

Thanks to the update on the DEE the system has NO more lag. enjoy and comment.

Updated to version 2 lots of new features! requires the updated DEE v1.6 to work.
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

G_G

Well I tried the demo its actually really great. I like the dynamic 3-D ish sounds.
I'll look into the script to see if I can try and fix the lag.

Blizzard

Alright, let's see...

1. Math.sqrt is a quite expensive method. Instead of using something like this:

Code: DEE code!
            distance = Math.sqrt(((client.x - j) ** 2) + ((client.y - i) ** 2))
           return true if distance <= piece.power - 1


you should better use something like this:

            squared_distance = (client.x - j) ** 2 + (client.y - i) ** 2
           return true if squared_distance <= (piece.power - 1) ** 2


** is way less expensive than Math.sqrt. Just be careful not to mess up your code, I took a look at it. In any case decrease calculating the same stuff to a minimum. You have a lot of RAM at your disposal and Ruby is a slow language. So trade in CPU time for RAM expense any time you can.

2. Your source update is too CPU heavy (hence the lag). I noticed that you keep calling effective_power which seems to be quite a CPU heavy method. Rather than updating it constantly, it would be a good idea to edit Client#update. I noticed that you add stuff to @source_effective_powers without adding stuff to @sources_in_range and call effective_power regardless if the source is actually in range. I think you should put it both in the if branch.

3. Generally that update is too heavy. Rather than calculating how the effective power is each time, you should create a variable that that indicates how big the effective_power is by default and then simply use a modifier depending on the range. This should take off a load of unnecessary calculation. In fact you should first find the closest source and only then only for that source call the effective_power method. This should take a load off the CPU.

4. The rest of the lag comes from high ranges of the sources.

5. Suggestion: It would be a very good idea if you made the sources work via events since like this it works for one map only. If you make the config work with event comments, keep in mind that you should limit it to having comments in the first line or else noticeable lag can occur when refreshing the map. If you decide to use event names, keep in mind that you won't be able to switch a source, except if you allow renaming the event and reevaluating the source configuration in the name. I suggest the latter since it's faster, I did the same in Blizz-ABS.

6. If you give me credit for this, I won't love you anymore. ._.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Hellfire Dragon

This is really cool Rye :o
Now if the lag was problem was fixed it would definitely be an awesome script ^_^

Ryex

*contemplates what blizz says*


well here is my new "in_range?" method. I think that this is about as good as it gets. instead of all the Math.sqrt it tests two boxes and uses squared_distance <= power - 1 squared on the corners.

Spoiler: ShowHide

Code: New DEE code

def in_range? (client)
      if client.is_a?(DEE::Client)
        @pieces.each { |piece|
          if (client.x >= piece.x && client.x <= (piece.x + piece.width - 1))
            if (client.y >= piece.y - piece.power && client.y <= (piece.y + piece.height - 1 + piece.power))
              return true
            end
          end
          if (client.x >= piece.x - piece.power && client.x <= (piece.x + piece.width - 1 + piece.power))
            if (client.y >= piece.y && client.y <= (piece.y + piece.height - 1))
              return true
            end
          end
          squared_distance = (client.x - piece.x) ** 2 + (client.y - piece.y) ** 2
          return true if squared_distance <= (piece.power - 1) ** 2
          squared_distance = (client.x - (piece.x + piece.width - 1)) ** 2 + (client.y - piece.y) ** 2
          return true if squared_distance <= (piece.power - 1) ** 2
          squared_distance = (client.x - (piece.x + piece.width - 1)) ** 2 + (client.y - (piece.y + piece.height - 1)) ** 2
          return true if squared_distance <= (piece.power - 1) ** 2
          squared_distance = (client.x - piece.x) ** 2 + (client.y - (piece.y + piece.height - 1)) ** 2
          return true if squared_distance <= (piece.power - 1) ** 2
        }
        return false
      else
        return false
      end
    end


and ya useing effective_power with every source on the map was stupid. if instead I use it only with the sources that are in range, that will decrease lag.

also, I think I can get the same results in the effective_power method by testing 5 boxes and uses Math.sqrt 4 times, I can't remove it altogether because I still need the exact distance on the corners...

just that should dramatically reduce the amount of calculations per update. thanks for point ing out the alternate for Math.sqrt and telling me it was an expensive function. (though now that I think about it I should of been able to tell that).

I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

I hope you were able to decrease the lag significantly. :)

Hm... I think you don't really need the "** 2" in the second part of the method. If I understand your code right, the client will always be diagonally positioned to the source if the first two conditions don't apply. It would be enough to just check the sum of their coordinate differences.

C       C

  SSS  
  SSS  
  SSS  

C       C


See what I mean? C are the possible client positions while S is the area covered by the source. Instead of using a squared distance, you can simply used a sum of the x and y differences and it will work. Adding is a cheaper operation that multiplying after all.

Another suggestion I have is to use a different way to check sources with a low width and height (i.e. 1 map square). These sources can easily treated as circular sources and instead of that whole block of code, it would be enough if you just checked the client's distance to the center of the source. It might not seem much, but if i.e. every second source is a point source and you can reduce the calculations for point sources by half, you'd have an improvement of 25% which is incredibly much.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Ryex

I was just thinking the same thing i'll add special handling for point (one pixel) and strip (line of pixel) sources
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

No wonder Blizz-ABS and RMX-OS don't lag. I just realized how much I learned to think outside of the box and look at the situation from a higher level of abstraction when I read my post above again and noticed how out-of-place my suggestions really are. O_o

My first suggestion above would remove all uses of **, right? I took a look at Blizz-ABS today and noticed that there is only one single place where I use Math.sqrt. And I use it to calculate Math.sqrt(2) which can easily be calculated in advance, put into a constant and used later one without ever calling Math.sqrt again. o.o;
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Ryex

source shapes: ShowHide


and to your edit. not exactly, if the first part of the in_range? method isn't true the source can still be in the 1/4 of a circle at the corners
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

Nope. You checked that already in the first 2 if blocks. The code wouldn't even get to that position if the client was located in the orange/yellow/red area.



Also, you need to modify your method a bit. There's no need to calculate the power (because that would be wrong) if you're inside the source rectangle. It should be 100% there, shouldn't it?

Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Ryex

wait what? what do you mean calculate power? where dose it do that?
also are you saying that there is a way other than

squared_distance = (client.x - piece.x) ** 2 + (client.y - piece.y) ** 2
return true if squared_distance <= (piece.power - 1) ** 2

to test the blue part in the corners?
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

Nevermind, I thought you were trying to find the closest corner.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Ryex

UPDATE: No more lag! no really before I had it skipping 10 frames before updating and I still had a 10 FPS drop
with the new update to the DEE I had it updating every frame and there was still no lag. YAY!
but really, leave the Update_Dynamic_Sound frame skip constant at 10 unless you notice choppy volume changes. even if there is no noticeable lag it still adds unnecessary calculations that in combination with other system or a slow comp can cause lag.
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Calintz

WOW!!
This is great!!

It's an orgasm for my ears!!
This really does deserve a level up. Great job Ryexander.

Subsonic_Noise

This is indeed awesome. It will definitely get you on lvl69 :V:

Aqua


Ryex

October 20, 2009, 12:51:45 am #16 Last Edit: October 20, 2009, 01:10:28 am by Ryexander
Just to give you an idea of whats comming...
Quote from:  RRR Topic
User:
I like the idea of using events you can plop anywhere on your map to control where sound comes from, using cords in a script has a lot of guess work and if you later chose that it be better for the sound to be coming from a slightly diff area you'd have to sort out and redo all the cords.

I'd also think using the tile flags be nice way to do it for stuff you always want one sound to come from like water and use diff flags for diff sounds, or just one. *shrugs* In both games I'm working on I have just one script that uses tile flags so thats not much of a prob.

I do like how this works however and feel it would bring a lot more depth to my(and any) game. If it can be more ease of use designed smile.gif

Me:


well I'm sure of one thing I'm NOT doing it from tile tags I'm sorry but when I think about the lag that would create I cringe. Idea dropped.

but ya for events it will end up working something like this

create a comment in the first line

then you would add a line like


SoundSource BGS Point 013-Fire03 300


where BGS is the type of sound
Point is the shape of the source
013-Fire03 is the file name
and 300 is the range of the sound in pixels

another think that will come in V2.0 is the ability to have SE (sound effect) sources.
ie. you have a SE source on top of an anvil that plays every 3 seconds and gets louder as you get nearer it.
or anything like that.



UPDATE:
v1.21 of the DEE fixes a bug when there is more than one map. if your using the script please update the DEE
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Ryex

October 25, 2009, 02:47:50 am #17 Last Edit: October 25, 2009, 02:25:20 pm by Ryexander
ok so in my event set up of sources I'm considering changing the sources array in the sound_source class to a hash. that way I can support methods to move sources while in game as well at other things base on a name you give the source it would also make it a whole lot easier to add pieces to a source.
but then i could also do it by creating a new has that bonds names to array indexes. which would be better?

also in terms of adding sources what kind of tage should i use to identify information
should I check for a \ in front of the key word or not, should I require []s around data that needs to be collected? or should I just check after the key word for data without []s? that sort of thing.

also for the SE effect playing every some many seconds should I use a Time.now object or go with Graphics.frame_rate/40

also I'm thinking about adding $globals to turn the Dynamic BGS's and SE's off individually. will this be used do you think?
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

It's up to you on ho you implement it.

I rather suggest using Graphics.frame_count/40 than Time.now.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Taiine

Yay you quoted me from the other forum xD

Looking good so fare :3 I still can't wait for this! The demo to my older rm2k remake in rmxp is almost done. Be a nice showcase of how this works in a real game :3