0

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

函数调用顺序不正确,或者之前的调用不成功。在 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?
        }
    }   
4

1 回答 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();
}

理想情况下,您需要在LoaderSound无法加载其内容的情况下为组件启用错误处理,以及上面的一些逻辑来处理这种情况。

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

于 2018-03-02T06:21:09.080 回答