在Adobe Animate ActionScript 3.0中循环

问题描述 投票:0回答:1

我正在尝试使用Adobe Animate CC中的ActionScript 3.0运行代码以显示30个不同的图像,每个图像都有自己的30秒音乐剪辑。我在尝试循环播放集时遇到问题(在播放所播放图像的歌曲后加载下一个图像)。我可以加载第一张图像和30秒的歌曲,但它不会继续循环播放到该集合。我有一个数字var我用来指向我系统上的艺术文件和歌曲。在尝试移动到下一个图像和声音文件之前,我成功检查以确保声音文件已完成播放,但是当我尝试将代码封装在循环中时,它会咳出错误:

以错误顺序调用的函数或之前的调用未成功。在flash.media::sound/_load()在flash.media::Sound/load()

任何帮助表示赞赏。谢谢。

import flash.display.MovieClip;
import flash.display.Loader;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.events.Event;

var songart:Number = 1;

// Create directory variables
var imgs:String = "F:/Synthsation/Web and Flash Design/Adobe     Animate/Duke_Nukem_TLB_Album_Art/Album_Art/";
var music:String = "F:/Synthsation/Web and Flash Design/Adobe Animate/Duke_Nukem_TLB_Album_Art/Song_Tracks/";

// Create Loader and movie clip variables
var imageLoader:Loader = new Loader();
var songclip:Sound = new Sound();

// Begin processing
// Loop through the album art and load the appropriate music clip
// set songart to begin at 1 and loop until completed

//  for (songart = 1; songart < 31; songart++) {
while (songart < 31) {

    // Convert the song number into a string 
    var songString:String = String(songart);

    // ------ QUEUE UP THE MUSIC ----------
    var mp3request:URLRequest = new URLRequest(music + songString + ".mp3");
    songclip.load(mp3request);

    // Create sound channel variable and tie it to sound object
    var channel:SoundChannel = songclip.play();
        songclip.play(); 

    // ------ LOAD THE PICTURE -----
    var picrequest:URLRequest = new URLRequest(imgs + songString + ".jpg");
    imageLoader.load(picrequest);

    // Add picture and position at top left of stage
    addChild (imageLoader);
    imageLoader.x = 0;
    imageLoader.y = 0;

     channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); 
    // Determine if the song has finished playing. If so loop to next iteration
    function onPlaybackComplete(event:Event): void
    {
    //  trace("DONE PLAYING!");
        trace(songart);
    //removeChild (imageLoader);    < --- necessary for next image?
        }
    }   
loops actionscript-3 iteration adobe-animate
1个回答
0
投票

这是一个普通的初学者(没有冒犯,我们都经历过)对Flash Player工作方式的误解。显然,Flash Player在逐帧的基础上执行事物,每个帧包括两个主要阶段:1)脚本和事件执行然后2)阶段渲染和外部(如加载和网络)操作。然后,除非你是编程动画,否则你甚至不需要在逐帧术语中思考,只是假设它是一个事件驱动的异步环境。没有主线程,只有事件处理程序(入口点是应用程序启动事件的事件处理程序,帧脚本是进入此帧的播放头的事件处理程序),这些事件处理程序预计将在一个给定时刻执行,而不再是。

因此,如果像你一样循环它,那么整个脚本会立即在同一个Sound实例上执行。是的,您正尝试同时将30个音频加载到同一个Sound实例。当然,它失败了。 Loader实例也是如此。

您需要的是组件方法。首先,您需要一个能够执行粒度操作的组件:通过索引加载图像和声音,播放音频,报告音频播放完毕,处理所有内容:

package
{
    import flash.display.Sprite;
    import flash.display.Loader;

    import flash.media.Sound;
    import flash.media.SoundChannel;

    import flash.events.Event;
    import flash.net.URLRequest;

    public class SoundImage extends Sprite
    {
        private static const IMG:String = "F:/Synthsation/Web and Flash Design/Adobe Animate/Duke_Nukem_TLB_Album_Art/Album_Art/";
        private static const SND:String = "F:/Synthsation/Web and Flash Design/Adobe Animate/Duke_Nukem_TLB_Album_Art/Song_Tracks/";

        private var Image:Loader;

        private var Audio:Sound;
        private var Channel:SoundChannel;

        public function start(index:int):void
        {
            // Load image by index.
            // There are no () brackets, it is not an error.
            // If there are no arguments you can omit them with "new" operator.
            Image = new Loader;
            Image.load(new URLRequest(IMG + index + ".jpg"));

            addChild(Image);

            // Load audio by index.
            Audio = new Sound;
            Audio.load(new URLRequest(SND + index + ".mp3"));

            // Play audio and listen for it to complete.
            Channel = Audio.play();
            Channel.addEventListener(Event.SOUND_COMPLETE, onDone); 
        }

        private function onDone(e:Event):void
        {
            // Remove the subscription.
            Channel.removeEventListener(Event.SOUND_COMPLETE, onDone);

            // Let all the subscribers know the audio is done.
            dispatchEvent(new Event(Event.COMPLETE));
        }

        public function dispose():void
        {
            // Always do the clean-up to avoid memory leaks
            // and unhandled things lying dormant somewhere.

            // Sanity check to avoid errors if you call that twice.
            // Or if you call it without actually starting it.
            if (!Image) return;

            // Yes, remove the subscription, because you might want
            // to stop the component before audio is done playing.
            Channel.removeEventListener(Event.SOUND_COMPLETE, onDone);

            Channel.stop();
            Channel = null;

            Audio.close();
            Audio = null;

            removeChild(Image);

            Image.unloadAndStop(true);
            Image = null;
        }
    }
}

然后,要播放单个条目,您需要

var SI:SoundImage = new SoundImage;

SI.start(10);
addChild(SI);

如果你想逐个玩它们,想法是创建一个,然后等待(当然是以异步事件驱动的方式)直到完成,然后继续下一个:

var SI:SoundImage;
var songIndex:int;

playNext();

function playNext():void
{
    songIndex++;

    SI = new SoundImage;

    // Listen for SI to complete playing audio.
    SI.addEventListener(Event.COMPLETE, onSong);
    SI.start(songIndex);

    addChild(SI);
}

function onSong(e:Event):void
{
    removeChild(SI);

    // Unsubscribe from event to release the instance.
    SI.removeEventListener(Event.COMPLETE, onSong);

    // Clean up things.
    SI.dispose();
    SI = null;

    // Proceed to the next entry.
    playNext();
}

理想情况下,如果Loader或Sound无法加载其内容,以及上面的一些逻辑来处理这种情况,您需要使用错误处理来赋予组件权限。

附:我没有检查脚本,我的目标是解释你的错误和正确的方法。

© www.soinside.com 2019 - 2024. All rights reserved.