0

所以在过去的几天里,我一直在努力尝试在我的游戏中添加一个音频滑块,我已经做到了,所以,让我先说我已经非常努力,我很想完全理解解决方案,但此时我真的只想要解决方案,所以越具体越好。

我想了很多方法,但我的动作脚本技能太差了,无法实现。让我稍微解释一下我的设置。我有一个功能齐全的类,它是一个音频滑块。它播放音乐、幻灯片,一切都很完美。现在,我把它贴在我的文档类中。我认为一开始就调用这个函数是最简单的(当我的标题屏幕出现时),即使我不希望现在在标题屏幕上播放音乐。所以我想我会打电话给它,然后根本不播放音乐。所以现在我从我的文档类中调用了它。现在,我希望能够单击选项按钮,然后 addChild 音频滑块。我实际上已经完成了这个并且它有效。最后....困难的部分。我想单击“玩游戏”按钮,然后让音乐开始播放,同时链接到可能已经被移动的选项滑块。真的……只是一个标准的音频滑块。

我真的坚持将选项屏幕音频滑块与游戏中实际播放的音乐联系起来。我想我会调用 Volume() 函数(我的音频滑块),然后一旦我的播放屏幕启动,再次调用它,然后从我的播放屏幕类中运行 Volume() 类的方法。不过,这似乎会导致问题……这就是我失去它的地方。通过再次调用 Volume() 类,我是否完全恢复了我的音频?就像这是否意味着我正在删除我在选项面板中使用音频滑块所做的一切?似乎是……因为它只是以默认值开始播放。

所以这里有一些我正在做的详细代码。我正在考虑使用导航事件,但就像我说的,我还不是最伟大的闪存程序员,当我在遇到麻烦之前尝试使用它们时。这是我在代码中的主要关注点。

1) 在我的 playScreen 类(称为 SimpleMenuMain)中调用 new_Volume。当我调用 Volume() 时,这是否会清除我在文档类中所做的一切?

2) 在 Volume() 类快结束时,我做了一个 stopMusic 函数。每当我从我的文档类中调用它时,它只有在我还没有按下 play game 时才有效,这进一步让我相信在按下 play game 之前我正在删除我在选项面板中所做的任何事情。

3)我应该使用导航事件(自定义事件)吗?如果是这样,我该怎么做?我一般都知道如何使用它们(我已经在这个游戏中使用了 5 个),但是我所有的导航事件都进入了我的文档类,所以我猜它们有一些我不太理解的微妙之处。我有一个自定义事件类..我也会发布它。

感谢您的所有帮助=)这一直在杀死我。我会将这些课程缩减为相关信息。

文档类

package 
{
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.ProgressEvent;

    public class SMGDocClass extends MovieClip 
    {
        public var playScreen:SimpleMenuMain;
        public var titleScreen:TitleScreen;
        public var gameOver:GameOver;
        public var loadingProgress:LoadingProgress;
        public var optionScreen:OptionScreen;
        public var new_Volume:Volume;

        public function SMGDocClass() 
        {
            loadingProgress = new LoadingProgress();
            loadingProgress.x = 0;
            loadingProgress.y = 0;
            addChild( loadingProgress );
            loaderInfo.addEventListener( Event.COMPLETE, onCompletelyDownloaded,false,0,true );
            loaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgressMade,false,0,true );
        }

        public function showTitleScreen():void
        {
            titleScreen = new TitleScreen();
            titleScreen.addEventListener(NavigationEvent.START,onRequestStart,false,0,true);
            titleScreen.addEventListener(NavigationEvent.OPTIONS,onRequestOptions,false,0,true);
            titleScreen.x = 0;
            titleScreen.y = 0;
            addChild(titleScreen);
            removeChild(loadingProgress);
            new_Volume = new Volume();
            new_Volume.stopMusic();

            stage.focus = playScreen;
            stage.stageFocusRect = false;
        }

        public function onStickman1Death(stickman1Event:Stickman1Event):void
        {
            var finalScore:Number = playScreen.getFinalScore();
            var finalClockTime:Number = playScreen.getFinalClockTime();

            gameOver = new GameOver();
            gameOver.addEventListener(NavigationEvent.RESTART,onRequestRestart,false,0,true);
            gameOver.addEventListener(NavigationEvent.MAINMENU,onRequestMainMenu,false,0,true);
            gameOver.x = 5;
            gameOver.y = 6;
            gameOver.setFinalScore( finalScore );
            gameOver.setFinalClockTime( finalClockTime );
            addChild(gameOver);
            new_Volume.stopMusic();

            removeChild(playScreen);
            playScreen = null;

        }

        public function onRequestStart( navigationEvent:NavigationEvent ):void
        {
        playScreen = new SimpleMenuMain();
        playScreen.addEventListener( Stickman1Event.DEAD, onStickman1Death,false,0,true );
        playScreen.x = 0;
        playScreen.y = 0;
        addChild( playScreen );

        dispatchEvent(new Stickman1Event(Stickman1Event.DEAD));

        removeChild(titleScreen);
        titleScreen = null;

        stage.focus = playScreen;
        stage.stageFocusRect = false;
        }

        public function restartGame():void
        {
            playScreen = new SimpleMenuMain();
            playScreen.addEventListener(Stickman1Event.DEAD, onStickman1Death,false,0,true);
            playScreen.x = 0;
            playScreen.y = 0;
            addChild(playScreen);

            removeChild(gameOver);
            gameOver = null;
        }


        public function onRequestMainMenu( navigationEvent:NavigationEvent):void
        {
            titleScreen = new TitleScreen();
            titleScreen.addEventListener(NavigationEvent.START,onRequestStart,false,0,true);
            titleScreen.addEventListener(NavigationEvent.OPTIONS,onRequestOptions,false,0,true);
            titleScreen.x = 0;
            titleScreen.y = 0;
            while(numChildren > 0) 
            {
                removeChildAt(0);
            }
            addChild(titleScreen);

            stage.focus = playScreen;
            stage.stageFocusRect = false;

        }

        public function onCompletelyDownloaded( event:Event ):void
        {
            gotoAndStop(3);
            showTitleScreen();
        }

        public function onProgressMade( progressEvent:ProgressEvent ):void
        {       
            loadingProgress.setValue( Math.floor( 100 * loaderInfo.bytesLoaded / loaderInfo.bytesTotal ) );
        }

        public function onRequestOptions(navigationEvent:NavigationEvent):void
        {
            optionScreen = new OptionScreen();
            optionScreen.addEventListener(NavigationEvent.MAINMENU,onRequestMainMenu,false,0,true);
            optionScreen.x = 0;
            optionScreen.y = 0;
            addChild(optionScreen);

            removeChild(titleScreen);

        }

    }
}

播放屏幕类

package  {

    import flash.display.MovieClip;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.ui.Mouse;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;
    import flash.events.Event;
    import flash.media.SoundChannel;

    public class SimpleMenuMain extends MovieClip {

        public var gameTimer:Timer;
        public var stickman1:Stickman1;
        public var new_Volume:Volume;


        public function SimpleMenuMain() {

            currentLevelData = new LevelData( 1 );
            setBackgroundImage();

            new_Volume = new Volume();

            gameTimer = new Timer(25);
            gameTimer.addEventListener(TimerEvent.TIMER, onTick, false, 0, true);
            gameTimer.start();

            addEventListener( Event.ADDED_TO_STAGE, onAddToStage );
        }

        public function onAddToStage(event:Event):void
        {
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPress,false,0,true);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyRelease,false,0,true);
        }

        public function onTick(timerEvent:TimerEvent):void
        {

            var stickman1HasBeenHit:Boolean = false;
            var i:int = army1.length - 1;
            var enemy1:Enemy1;
            while ( i > -1 )
            {
                enemy1 = army1[i];
                if (enemySpeed == 1)
                {
                    enemy1.moveABit(3,-1.5);
                }
                if (enemySpeed == 2)
                {
                    enemy1.moveABit(3.6,-1.8);
                }
                if ( PixelPerfectCollisionDetection.isColliding( stickman1, enemy1, this, true ) ) 
                {
                    getFinalScore();
                    gameTimer.stop();
                    bgmSoundChannel.stop();
                    stickman1HasBeenHit = true;
                }
                if ( enemy1.y > 400 )
                {
                    removeChild( enemy1 );
                    army1.splice( i, 1 );
                }
                i = i - 1;
            }

            var i:int = army2.length - 1;
            var enemy2:Enemy2;
            while ( i > -1 )
            {
                enemy2 = army2[i];
                if (enemySpeed2 == 1)
                {
                    enemy2.moveABit(6,-3);
                }

                if (PixelPerfectCollisionDetection.isColliding(stickman1, enemy2, this, true ) )

                {
                    gameTimer.stop();
                    bgmSoundChannel.stop();
                    stickman1HasBeenHit = true;
                }
                if ( enemy2.y > 400 )
                {
                    removeChild( enemy2 );
                    army2.splice( i, 1 );
                }
                i = i - 1;
            }


            if (stickman1HasBeenHit)
            {
                dispatchEvent(new Stickman1Event(Stickman1Event.DEAD));
            }
        }
}

卷类

package {

        import flash.display.Sprite;
        import flash.display.Graphics;
        import flash.events.MouseEvent;
        import flash.events.Event;
        import flash.net.URLRequest;
        import flash.media.Sound;
        import flash.media.SoundChannel;
        import flash.media.SoundTransform;
        import flash.geom.Rectangle;

        public class Volume extends Sprite {

                public var snd:Sound = new Sound();
                public var channel:SoundChannel = new SoundChannel();
                //URLRequest=new URLRequest("solitude.wav");
                //Make sure you pass URLRequest an audio file on your computer.
                public var req:BackgroundMusic = new BackgroundMusic();
                public var boundary:Rectangle;
                public var sprite:Sprite;
                public var slider:Sprite;
                public var xPos:Number;
                public var yPos:Number;
                public var vol:Number;

                /*
                Our request is loaded into the sound object and plays through
                our channel. Volume is initially set at 50% and passed as a
                transformation to our our channels soundTransform property
                (a fancy way of saying volume). The init() function is called.  
                */

                public function Volume() {
                        this.addEventListener(Event.ADDED_TO_STAGE, onStage,false,0,true);
                        startMusic();
                }

                /*

                The init function creates and draws a rectangle and circle
                to the stage and centers them based on the height and
                width of the stage. In addition, a rectangle object is
                created to 'contain' the sliding circle, like an imaginary box.
                We pass -100 as the x value because it is added relative
                to our sprite. If we set its x value at 0, or the sprites default x
                value,the boundary would stop and start at the slider sprite. Change
                -100 to 0 in the rectangle object to get a better idea of its use.

                */

                public function onStage(e:Event):void
                {
                    //We remove it immediately so that it doesn't get called multiple times
                    //As the instance is added to the display list tree
                    this.removeEventListener(Event.ADDED_TO_STAGE, onStage);

                    xPos = 320;
                    yPos = 132;

                    /* Now that we have a reference to the stage, let's go ahead and create our slider */
                    init();
                }

                public function init():void {
                        sprite = new Sprite();
                        channel.stop();
                        sprite.graphics.beginFill(0x999999);
                        sprite.graphics.drawRect(xPos,yPos,100,5);
                        sprite.graphics.endFill();
                        addChild(sprite);
                        sprite.x-=sprite.width/2;
                        slider = new Sprite();
                        slider.graphics.beginFill(0xFF0000);
                        slider.graphics.drawCircle(xPos+50,yPos, 15);
                        slider.graphics.endFill();
                        addChild(slider);
                        slider.addEventListener(MouseEvent.MOUSE_DOWN, dragSlider);
                        stage.addEventListener(MouseEvent.MOUSE_UP, stopSlider);
                        boundary=new Rectangle(-100,0,100,0);
                }

                /*

                dragSlider runs when the use holds the mouse button down. A
                startDrag method is used on our sprite where we specify boundary
                as our dragging limits. A new event handler designed
                to change the mouse volume is subsequenlty called per frame, where
                the slider.x property determines volume.

                */

                public function dragSlider(event:MouseEvent):void {
                        slider.startDrag(false,boundary);
                        slider.removeEventListener(MouseEvent.CLICK, dragSlider);
                        slider.addEventListener(Event.ENTER_FRAME, changeVolume);
                }

                /*

                Stops dragging and removes the event listener to save on space. Again,
                volume will be based on the sliders current x position, which is
                constantly being recalculated per frame because we used an
                ENTER_FRAME event.

                */

                public function stopSlider(event:MouseEvent):void {
                        slider.stopDrag();
                        slider.removeEventListener(MouseEvent.MOUSE_UP, stopSlider);
                }

                /*

                This function is constantly recalculating the vol variable
                based on the sliders x position, relative to the length of
                our rectangle. Creates a decimal range from 0 to 1, where 1
                represents 100% volume and 0 represents mute. Anything exceeding
                100% causes distortion.

                */

                public function changeVolume(event:Event):void {
                        vol=1+Math.round(slider.x)/100;
                        channel.soundTransform=new SoundTransform(vol);
                }

                public function onBackgroundMusicFinished(event:Event):void
                {
                    channel = req.play();
                    channel.addEventListener( Event.SOUND_COMPLETE, onBackgroundMusicFinished );
                    vol=1;
                    channel.soundTransform=new SoundTransform(vol);
                }

                public function startMusic():void
                {
                    channel=req.play();
                    channel.addEventListener( Event.SOUND_COMPLETE, onBackgroundMusicFinished,false,0,true );
                    vol=1;
                    channel.soundTransform=new SoundTransform(vol);
                }

                public function playMusic():void
                {
                    channel = req.play();
                }

                public function stopMusic():void
                {
                    channel.stop();
                }

        }

}

导航事件类

package  
{
    import flash.events.Event;
    public class NavigationEvent extends Event 
    {
        public static const RESTART:String = "restart";
        public static const START:String = "start";
        public static const MAINMENU:String = "mainmenu";
        public static const OPTIONS:String = "options";
        public static const STOPMUSIC:String = "stopmusic"

        public function NavigationEvent( type:String, bubbles:Boolean = false, cancelable:Boolean = false ) 
        { 
            super( type, bubbles, cancelable );

        } 

        public override function clone():Event 
        { 
            return new NavigationEvent( type, bubbles, cancelable );
        }

        public override function toString():String 
        { 
            return formatToString( "NavigationEvent", "type", "bubbles", "cancelable", "eventPhase" ); 
        }
    }
}

选项屏幕类

package  {

    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.ui.Mouse;
    import flash.net.SharedObject;
    import flash.events.Event;


    public class OptionScreen extends MovieClip {

        public var mainMenuButton:SimpleButton;
        private var new_Volume:Volume;
        public var myEvent:Event;

        public function OptionScreen() {

            Mouse.show();
            new_Volume = new Volume();
            addChild(new_Volume);
            mainMenuButtonOptions.addEventListener(MouseEvent.CLICK, onClickMainMenu,false,0,true);
        }

        public function onClickMainMenu(mouseEvent:MouseEvent):void
        {
            dispatchEvent( new NavigationEvent(NavigationEvent.MAINMENU));
        }
    }

}

最后......标题屏幕类

package 
{
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;

    public class TitleScreen extends MovieClip 
    {
        public var startButton:SimpleButton;

        public function TitleScreen() 
        {
            Mouse.show();
            startButton.addEventListener( MouseEvent.CLICK, onClickStart,false,0,true );
            titleOptionsButton.addEventListener( MouseEvent.CLICK, onClickOptions,false,0,true );
        }

        public function onClickStart( event:MouseEvent ):void
        {
            dispatchEvent( new NavigationEvent( NavigationEvent.START ) );
        }

        public function onClickOptions( event:MouseEvent ):void
        {
            dispatchEvent( new NavigationEvent( NavigationEvent.OPTIONS ) );
        }


    }
}
4

1 回答 1

1

您可以在单个 SoundChannel 上或在 SoundMixer 类上全局更改音量。您当前的实现是前者,并在每次实例化类时定义。

请参阅 Adob​​e 的控制音量和平移

您还可以使用 SoundMixer 类的 soundTransform 属性一次为所有声音设置全局音量和声像值,如以下示例所示:

SoundMixer.soundTransform = new SoundTransform(1, -1);

您还可以存储您的卷并将其作为全局/静态变量引用。

public static var soundLevel:Number = 100;

public function changeVolume(event:Event):void {
    soundLevel = 1+Math.round(slider.x)/100;
    channel.soundTransform=new SoundTransform(soundVolume);
}

这样,任何滑块对象都会更改相同的变量。当然,您需要将 N 个 soundObjects 更新为 new soundLevel,这就是为什么使用SoundMixer是更好的解决方案。

  1. 不会。类的新实例Volume不会覆盖之前创建的 SoundChannel。然而,因为Volume是一个 DisplayObject,如果它的唯一引用是在舞台上,并且开始你的游戏需要一个不同的帧,那么旧的 Volume 对象将从 DisplayList 中删除并且可能被垃圾收集。

  2. 听起来你肯定会在帧之间移动,在这种情况下,旧的 Volume 对象将从 DisplayList 中删除并进行 GC 处理。这出现了很多,但我会重申:不要使用舞台框架。有更好的(不那么令人头疼的)方法来编程你需要的东西。

  3. 您对导航事件的选择是自由裁量的。您可以轻松编写一个 nav 类来处理来自系统的所有输入事件,并适当地调用您的方法。就个人而言,我不喜欢 Flash 风格的事件。除了通常的变量嫌疑人之外,我通常还想将其他数据传递给我的方法,从而导致由自定义事件引起的混乱。您还可以通过全局状态跟踪来清除它,并简单地从您的通用方法中引用您的当前状态以确定它们对任何给定导航事件的响应。

于 2013-07-23T18:27:32.730 回答