Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Help With Volume Slider

Explorer ,
Mar 08, 2019 Mar 08, 2019

So I was following a tutorial to add a volume slider to my flash project - and all went well until the point of actually making the slider control the volume.

Unfortunately the video only showed how to use the slider to control the opacity of a symbol, rather than the volume of sound.

So I'm hoping someone can help me finish it~

This is the code I have for the slider's .as file, which is working fine;

package  {

import flash.display.MovieClip;

import flash.events.MouseEvent;

import flash.geom.Rectangle;

public class SFXSlider extends MovieClip {

  var myRect:Rectangle = new Rectangle(0, 0, 60, 0)

  public function SFXSlider() {

   // constructor code

 

   SFXKnobInst1.addEventListener(MouseEvent.MOUSE_DOWN, startMove);

   stage.addEventListener(MouseEvent.MOUSE_UP, stopMove);

 

  }

  private function startMove (e:MouseEvent){

   SFXKnobInst1.startDrag(false, myRect);

  }

  private function stopMove (e:MouseEvent){

   SFXKnobInst1.stopDrag();

  }

}

}

SFXSlider = Name of slider

SFXKnobInst1 = Name of control knob instance

So as I said before, I need to make it control the volume now. However, this is just one of two visually identical sliders to control two different types of sound (one for sound effects, one for music) - so I also need know how define all sound effects as a separate 'type' of sound to the music, and have the two sliders control each separately. (The music slider/knob will be same names only with MUS instead of SFX in the names)

Please keep in mind i'm a newbie and clueless about coding Also, here's the tutorial I was following incase needed for some reason: Creating a Custom Slider With startDrag() Method in Flash Using AS3 - YouTube

Please & Thanks~

1.8K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Mar 08, 2019 Mar 08, 2019

Hi.

Here is a sample of how you can achieve this.

If you are going to use OOP, try to let things the more generic, modular, and dynamic as possible.

In this demo, I created a class for a generic slider that has the only purpose of returning a number from 0 to 1. I called this returned value ratio.

The Audio class has methods to play and stop sounds and also to change their volume. The methods are static which means you don't need to create an instance of the Audio class to use them. You only have to

...
Translate
Community Expert ,
Mar 08, 2019 Mar 08, 2019

Hi.

Here is a sample of how you can achieve this.

If you are going to use OOP, try to let things the more generic, modular, and dynamic as possible.

In this demo, I created a class for a generic slider that has the only purpose of returning a number from 0 to 1. I called this returned value ratio.

The Audio class has methods to play and stop sounds and also to change their volume. The methods are static which means you don't need to create an instance of the Audio class to use them. You only have to write Audio.play(...), for example.

Also, you can separate your sounds in different channels by assigning an id to them. In my case, i used "bgm" and "sfx".

In the FLA, I added click events to the buttons to play a BGM and a SFX that live in the Library.

The slider class can inform the ratio value everytime it changes through a callback function called update that is a property of the callBacks object. Just call the Audio.volume method inside of the update function using the returned ratio value as an argument.

It's hard to explain OOP concepts. I hope it all makes some sense.

Please let me know if you have any questions.

AS3 code:

FLA

import flash.events.MouseEvent;

var bgmIsPlaying:Boolean = false;

function toggleBGM(e:MouseEvent):void

{

    if (bgmIsPlaying)

        Audio.stop("bgm");      

    else

        Audio.play(new ActiveBGM(), "bgm", bgmSlider.ratio);

  

    bgmIsPlaying = !bgmIsPlaying;

}

function playSFX(e:MouseEvent):void

{

    Audio.play(new LaserSFX(), "sfx", sfxSlider.ratio);

}

bgmButton.addEventListener(MouseEvent.CLICK, toggleBGM);

sfxButton.addEventListener(MouseEvent.CLICK, playSFX);

bgmSlider.callBacks.update = function(ratio):void

{

    Audio.volume("bgm", ratio);

};

sfxSlider.callBacks.update = function(ratio):void

{

    Audio.volume("sfx", ratio);

};

Audio.as

package

{

    import flash.media.SoundChannel;

    import flash.media.SoundTransform;   

    public class Audio

    {

        public static var channels:Object = {};

       

        public static function play(sound:*, channel:String, volume:Number = 1):void

        {

            var soundTransform:SoundTransform = new SoundTransform();

           

            if (!channels[channel])

                channels[channel] = new SoundChannel();

           

            channels[channel] = sound.play();

            soundTransform.volume = volume;

            channels[channel].soundTransform = soundTransform;

        }

       

        public static function stop(channel:String):void

        {

            if (channels[channel])

                channels[channel].stop();

        }

       

        public static function volume(channel:String, volume:Number):void

        {

            if (channels[channel])

            {

                var soundTransform:SoundTransform = new SoundTransform();               

                soundTransform.volume = volume;

                channels[channel].soundTransform = soundTransform;

            }

        }

    }

}

Slider.as

package

{

    import flash.display.Sprite;

    import flash.events.Event;

    import flash.events.MouseEvent;

    import flash.geom.Rectangle;

    public class Slider extends Sprite

    {

        public var ratio:Number;

        public var callBacks:Object = {};

       

        public function Slider()

        {

            if (stage)

                start(null);

            else

                addEventListener(Event.ADDED_TO_STAGE, start);

        }

       

        public function start(e:Event):void

        {

            ratio = getRatio();

           

            removeEventListener(Event.ADDED_TO_STAGE, start);

            addEventListener(MouseEvent.MOUSE_DOWN, _startMovingButton);

        }

       

        public function getRatio():Number

        {

            return button.x / (rec.width - button.width);

        }

       

        private function _startMovingButton(e:MouseEvent):void

        {

            stage.addEventListener(MouseEvent.MOUSE_MOVE, _moveButton);

            stage.addEventListener(MouseEvent.MOUSE_UP, _stopMovingButton);

        }

       

        private function _moveButton(e:MouseEvent):void

        {

            button.x = mouseX;

           

            if (button.x < 0)

                button.x = 0;

            else if (button.x > rec.width - button.width)

                button.x = rec.width - button.width;

           

            ratio = getRatio();

           

            if (callBacks.update)

                callBacks.update(ratio);

        }

       

        private function _stopMovingButton(e:MouseEvent):void

        {

            stage.removeEventListener(MouseEvent.MOUSE_MOVE, _moveButton);

            stage.removeEventListener(MouseEvent.MOUSE_UP, _stopMovingButton);

        }       

    }

}

FLA download:

animate_cc_as3_volume_slider.zip - Google Drive

Regards,

JC

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 09, 2019 Mar 09, 2019

Oh, thank you for the reply~

I'm having trouble figuring out how to apply all of this to my own project with the custom slider I have made already, though.

See, I don't want any play/pause buttons, as the music will always be playing by default and the SFX is triggered on different frames throughout the flash.

For example, I have variations of this code on different frames to trigger the different SFX sounds on those frames;

var soundsA:Array=['sound1','sound2','sound3','sound4'];

var S=Class(getDefinitionByName(soundsA[Math.floor(4*Math.random())]));

var s=new S();

s.play();

The music on the other hand is just sat in the timeline using the sound section of the properties panel.

Is it possible to get this to work with what I have already? I was hoping it would be as simple as categorizing different types of sounds together in classes then having my slider adjust the volume of those classes, without any kind of play/pause or other user input involved~

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 09, 2019 Mar 09, 2019

Hi.

Sure.

To handle the sounds without buttons, we just have to modify the FLA code a bit. The external classes files remain the same.

AS3 code:

FLA

var sfxs:Array =

[

    LaserSFX,

    LoseSFX,

    CoinsSFX,

    HealSFX,

    ConfirmSFX

];

function playRandomSFX():void

{

    Audio.play(new sfxs[uint(sfxs.length * Math.random())], "sfx", sfxSlider.ratio);

}

bgmSlider.callBacks.update = function(ratio):void

{

    Audio.volume("bgm", ratio);

};

sfxSlider.callBacks.update = function(ratio):void

{

    Audio.volume("sfx", ratio);

};

if (!this.started)

{

    Audio.play(new ActiveBGM(), "bgm", bgmSlider.ratio);

    this.started = true;

}

Then you just have to call the playRandomSFX function whenever you need a random SFX to be played. And the sliders will take care of the SFX and BGM volumes.

I've updated the link with a new FLA.

FLA download:

animate_cc_as3_volume_slider.zip - Google Drive

Please let me know if you still need help.

Regards,

JC

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 09, 2019 Mar 09, 2019

Okay - I've tried setting it up like that, but I keep getting 2 errors for every frame I try to call the function on.

playRandomSFX():  produces;

Scene 1, Layer 'Actions', Frame 80, Line 1, Column 23 1078: Label must be a simple identifier.

Scene 1, Layer 'Actions', Frame 80 1084: Syntax error: expecting identifier before end of program.

I also don't know if I need to link the Audio.as file to the FLA in someway? I don't know how to though...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 09, 2019 Mar 09, 2019

Please don't forget to examine the details of the FLAs I provided. Including the Library symbols.

Anyway, if you still can't apply the sample codes to your case, I'll need to see your code to help you.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 09, 2019 Mar 09, 2019

I have been trying to - but as I said in my OP, I'm a complete newbie to animate cc (and flash in general)

This is a lot more complicated than I had hoped - I was thinking I maybe just needed to add a few class names to different sound files then add a few more lines to the code I'm using for my slider (shown in first post) to control them...I didn't really expect or want to have to recode my whole FLA and/or use completely new slider scripts.

I thank you for your attempt to help and really hope I'm not coming across as ungrateful - but this is all just going completely over my head now, and so I'm thinking I'll just do without volume controls...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 09, 2019 Mar 09, 2019

Don't give up. Take your time. No need to understand everything now.

Just focus on the FLA code. Run some tests, Google your doubts. Coding requires patience, trial and error, research and often frustration. This is how the things are.

But again, if you don't mind, share your file and I'll be happy to take a look at it.

Regards,

JC

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 11, 2019 Mar 11, 2019

Ok, I've finally got it working for the SFX ❤️

There's a couple more things I need to do now though;

First - I need to know how to add the possibility of no sound playing at all randomly, and a way to adjust the chance of each sound (or no sound) playing in a way that still works with your sliders. For example, this is what I was using before without volume sliders;

var probA:Array = [.2,.2,.2,.4];

var soundsA:Array=['sound1','sound2','sound3','no sound'];

var i:int = indexF(Math.random());

if(SoundsA!='no sound'){

var S=Class(getDefinitionByName(soundsA));

var s=new S();

s.play();

}

function indexF(r:Number):int{

var s:Number=0;

for(var i:int=0;i<probA.length;i++){

s+=probA;

if(r<s){

return i;

}

}

}

Second -  I want the BGM/Music set up in a certain way - Is there a way to specifically code the same functions you get from the default Properties>Sound>Sync options (Event, Stop, Start, Stream, Loop, Repeat, etc.) so that I can trigger them on certain frames and still have them respond to the BGM volume slider? Or perhaps simply leave them to be controlled by the timeline without coding as is, and just have them classed as "bgm" so the slider affects them?

(The reason for this is I actually have 2 music files, an 'Intro' and a 'Main' file - the intro starts on frame 2 and loops in the first scene (frames 3-62), then stops and switches to the main theme after the user clicks a button to continue on, and this file then loops uninterrupted and indefinitely throughout the rest of the flash from scene 2 (frames 63-92) onwards)

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 12, 2019 Mar 12, 2019

This is awesome. Congrats!

So I applied two minor changes to the Audio class. But you don't have to worry about the internals. You only need to know know that you can pass a 4th argument to change the number of times the sound loops. Like this:

Audio.play(new QueenBGM(), "bgm", bgmSlider.ratio, 9999); // 9999 is the number of loops. Use a high number to have the sound repeating for a long, long time.

I also applied your chances function, included a null item in the sounds array for no sound, and changed the BGM towards the end so you can see how it can be done.

You'll have to use code because as far as I can tell there's no way to access timeline sounds with AS3.

And last but no least I've updated the download link.

FLA code:

[Frame 1]

var probA:Array = [0.1, 0.1, 0.1, 0.1, 0.3, 0.3];

var sfxs:Array =

[

    null,

    LaserSFX,

    LoseSFX,

    CoinsSFX,

    HealSFX,

    ConfirmSFX

];

function playRandomSFX():void

{

    var randomSound:* = sfxs[indexF(Math.random())];

   

    trace(randomSound);

   

    if (randomSound)

        Audio.play(new randomSound(), "sfx", sfxSlider.ratio);

}

function indexF(r:Number):int

{

    var s:Number = 0;

   

    for(var i:int = 0; i < probA.length; i++)

    {

        s += probA;

        if(r < s)

            return i;

    }

   

    return -1;

}

bgmSlider.callBacks.update = function(ratio):void

{

    Audio.volume("bgm", ratio);

};

sfxSlider.callBacks.update = function(ratio):void

{

    Audio.volume("sfx", ratio);

};

if (!this.started) // this is needed to make sure the function won't be called more than once

{

    Audio.play(new ActiveBGM(), "bgm", bgmSlider.ratio);

    this.started = true;

}

[Frame 120]

playRandomSFX();

[Frame 240]

playRandomSFX();

[Frame 360]

playRandomSFX();

[Frame 480]

if (!this.looped) // this is needed to make sure the function won't be called more than once

{

    Audio.play(new QueenBGM(), "bgm", bgmSlider.ratio, 9999);

    this.looped = true;

}

playRandomSFX();

[Frame 600]

playRandomSFX();

[Frame 720]

gotoAndPlay("loop");

FLA download:

animate_cc_as3_volume_slider.zip - Google Drive

Please let me know if it helps you.

Regards,

JC

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 12, 2019 Mar 12, 2019

Alright, bgm slider is working now too~ :3

I'm having problems with some of the SFX now though - they are loading with no errors and playing according to the output, but I can't actually hear them...

It's only happening with some of the sounds too, which is confusing me. I can't see any mistakes in the code, and there are no errors showing up anywhere. It almost sounds like some are being cut off before they finish, or are sped up - while others I can't hear at all.

I didn't mention that only *some* sound groups were supposed to have the chance of not playing, whereas others always play something...so maybe it was something that was changed in the audio.as?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 12, 2019 Mar 12, 2019

Hi.

I included a instruction to stop the sound playing in the channel before playing another. Could this be the issue?

Because maybe your sounds are being played with a small delay/gap between each other.

I can revert this change and then if you want to stop a sound playing in a sound channel, you can do this manually. Is it OK for you?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 12, 2019 Mar 12, 2019

Yes! I actually just realised that's what was happening myself

I have some sound effects that should overlap each other - but with the new code they are indeed cutting each other off instead~

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 13, 2019 Mar 13, 2019

OK. Nice.

I've updated the link with a 4th step/folder.

Now everytime you need play a sound without overlapping the previous one in the same channel, you're gonna have to call Audio.stop first.

But in most cases you're only gonna need to do this with BGMs because SFXs will most likely not gonna need this approach.

I hope this helps.

Regards,

JC

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 13, 2019 Mar 13, 2019

Everything is working perfectly now~

I really cannot thank you enough for all the help and patience, this was the last part of my project and I've got it mostly finished now ❤️

I think I have even learned a few things also - so sincerely, thank you!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 13, 2019 Mar 13, 2019
LATEST

You're welcome!

I'm really glad you managed to get your project mostly finished.

Have a nice development and learning and week!

Regards,

JC

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines