Flash 帮助:使用setInterval()以可变速度播放MovieClip

Flash 帮助:使用setInterval()以可变速度播放MovieClip,flash,actionscript-3,Flash,Actionscript 3,我正在尝试使用setInterval逐帧播放MovieClip。总的来说,我试图通过改变设置间隔时间来模拟电影剪辑的加速和减速 基本上,当用户移动滑块时,MovieClip需要根据滑块值加速或减速 编辑:上述代码在一定程度上起作用。正如滑块更新updateClip()一样,MovieClip实际上以一种速度播放。但是MovieClip不会以速度可变值播放。如果删除ClearInterval(),则MovieClip仅以一种速度播放,但当滑块更改时会加倍。我要找的是以与速度值相同的速率播放的电影剪

我正在尝试使用setInterval逐帧播放MovieClip。总的来说,我试图通过改变设置间隔时间来模拟电影剪辑的加速和减速

基本上,当用户移动滑块时,MovieClip需要根据滑块值加速或减速

编辑:上述代码在一定程度上起作用。正如滑块更新updateClip()一样,MovieClip实际上以一种速度播放。但是MovieClip不会以速度可变值播放。如果删除ClearInterval(),则MovieClip仅以一种速度播放,但当滑块更改时会加倍。我要找的是以与速度值相同的速率播放的电影剪辑

对不起,如果我说不通的话。我不是个爱炫耀的人


编辑:最终版本更新(感谢大家的大力帮助)


使用ActionScript3时,应该使用类而不是setInterval

// add imports

import flash.utils.Timer;
import flash.events.TimerEvent;

//  add to variable declarations

var timer : Timer = null;

//  this goes instead of clearInterval and setInterval, after you've set "speed"

if (timer == null) setTimer();

//  and here is the function

function setTimer() 
{
    timer = new Timer (speed, 1);
    timer.addListener (TimerEvent.TIMER_COMPLETE, updateGrass);
    timer.start();
}
//  and the updateGrass method

function updateGrass( ev:TimerEvent ) 
{
    if (grass_mc.currentFrame>249) grass_mc.gotoAndStop(1);
    else grass_mc.nextFrame();
    setTimer();
}

只要有用就好。 我有几个建议可能会有所帮助:

  • 您可能希望使用计时器而不是setInterval,因为它为您提供了一些方便的额外选项
  • 尝试远离复制和粘贴代码,请遵循
  • 让我们将其分解为几个部分: -原始帧速率(每秒帧数比) -任意电影剪辑(具有n个帧) -用于更新播放的变量

    想法很简单,您必须基于变量更新电影剪辑的当前帧。您可以使用该变量来控制更新频率(您的间隔),或者 控制跟踪动态帧的变量

    下面是一个关于如何控制时间/间隔的示例:

    var metro:Number = 1000/stage.frameRate;//'metronome' - convert fps to millis
    slider.addEventListener(Event.CHANGE, sliderUpdate);//slider values must be > 0 (e.g. 0.01)
    var updater:Timer = new Timer(metro);
    updater.addEventListener(TimerEvent.TIMER, frameUpdate);
    updater.start();
    
    function frameUpdate(event:TimerEvent):void {
        clip.gotoAndStop(updater.currentCount%clip.totalFrames);//loop at total frames (a frame variable + if(frame > totalFrame) might be faster
    }
    function sliderUpdate(event:Event):void{
        updater.delay = metro / slider.value;
    }
    
    因此,电影剪辑不会一直更新,您可以使用滑块更新的变量来控制它。请注意,帧速率从“帧度量单位”转换为毫秒

    以下是一个修改版本,其中考虑了滑块的负值和零值:

    var metro:Number = 1000/stage.frameRate;
    slider.addEventListener(Event.CHANGE, sliderUpdate);
    var updater:Timer = new Timer(metro);
    updater.addEventListener(TimerEvent.TIMER, frameUpdate);
    updater.start();
    
    function frameUpdate(event:TimerEvent):void {//if it's negative value - go backwards/subtract from total
        clip.gotoAndStop(slider.value < 0 ? (clip.totalFrames-updater.currentCount%clip.totalFrames) : updater.currentCount%clip.totalFrames);
    }
    function sliderUpdate(event:Event):void{//watchout for 0 value
        updater.delay = metro / Math.abs(slider.value == 0 ? 0.001 : slider.value);
    }
    

    对于小于数百毫秒的时间间隔,计时器是个糟糕的主意。我会使用
    ENTER\u FRAME
    事件和
    getTimer
    以毫秒为单位获取当前时间,然后使用
    stop()
    nextFrame()
    手动控制剪辑。我同意alxx——使用计时器似乎很好,但我认为输入帧的方法更好,特别是如果你想让你的MovieClip运行得比SWF的帧速快。我写了一篇关于我是如何做到这一点的博文:。

    那么你已经发布了你的解决方案了?或者你的意思是你的代码没有按预期工作(如何工作?)对不起,schellmax,我已经对这个问题进行了编辑。谢谢你的帮助George。非常感谢。我确实尝试过实现您的第二个示例。然而,我的电影唇似乎没有更新@丹尼·克罗夫特,嗯,我已经测试过了,效果很好。你的草地第一帧上有停止点吗?你有幻灯片更新的痕迹吗?看看这里:感谢weltraumpirat,特别是包括我的变量名和注释。我确实尝试过实现这个解决方案,它确实有效,但是当我移动滑块时,MovieClip只播放(一帧然后停止)。我试图实现的是MoveClip以速度变量的速率“播放”,例如模仿电影剪辑的加速和减速。希望这有道理?有道理。对不起,我忘了重新设置计时器了。我编辑了我的答案。再次感谢weltraumpirat,但是无论速度变量有多大,MovieClip似乎都在加速?它似乎一点也不慢。请检查您对
    速度的计算。剪辑将根据此处设置的内容进行更新。
    
    var metro:Number = 1000/stage.frameRate;
    slider.addEventListener(Event.CHANGE, sliderUpdate);
    var updater:Timer = new Timer(metro);
    updater.addEventListener(TimerEvent.TIMER, frameUpdate);
    updater.start();
    
    function frameUpdate(event:TimerEvent):void {//if it's negative value - go backwards/subtract from total
        clip.gotoAndStop(slider.value < 0 ? (clip.totalFrames-updater.currentCount%clip.totalFrames) : updater.currentCount%clip.totalFrames);
    }
    function sliderUpdate(event:Event):void{//watchout for 0 value
        updater.delay = metro / Math.abs(slider.value == 0 ? 0.001 : slider.value);
    }
    
    var frame:Number = 0,roundFrame:Number;
    this.addEventListener(Event.ENTER_FRAME, frameUpdate);
    function frameUpdate(event:Event):void {
        frame += slider.value;
        roundFrame = Math.floor(Math.abs(frame))%clip.totalFrames;
        if(slider.value > 0) clip.gotoAndStop(roundFrame);  
        else                 clip.gotoAndStop(clip.totalFrames-roundFrame);
    }