Skip navigation
fonzio1
Currently Being Moderated

jump to appropriate frame of animation

Nov 16, 2011 3:07 AM

hi guys

 

thanks for reading and here is the problem im facing

 

i have a clock, and a background

 

the background contains an animated ocean (100 frames)

 

there are four sky themes which change on the appropriate hour to night-time, morning, sunset, sunrise (could just use alpha to show another here although maybe processor intensive)

 

ok so the ocean could animate on its own and only the sky would need to change, that would be the easy part

 

but when it gets to night-time the ocean needs to jump to the night-time version of itself

 

so if the user presses the hour button, and the ocean is on daytime at frame 80, how would i say play night version at frame 81

 

so that the ocean doesnt skip animation??

 

thanks in advance

fonzio

 
Replies
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 16, 2011 3:28 AM   in reply to fonzio1
    myNightOcean.gotoAndPlay(myDayOcean.currentFrame + 1);
    
     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 16, 2011 3:31 AM   in reply to fonzio1

    You can also fix case that myDayOcean is already at the last frame and you want it to go to the first frame:

     

    myNightOcean.gotoAndPlay((myDayOcean.currentFrame + 1) % myDayOcean.totalFrames);
    

     
    |
    Mark as:
  • Currently Being Moderated
    Nov 22, 2011 8:19 AM   in reply to fonzio1

    If you have labels as you indicate then chances are you only need to specify them alone...

     

    if (hours == 9){

        sea_mc.gotoAndPlay("nightsea");

    }

     

    What you were otherwise trying to do with that label will most likely produce an error.  Anytime you get errors you should include the complete error message in your posting.

     
    |
    Mark as:
  • Currently Being Moderated
    Nov 22, 2011 9:14 AM   in reply to fonzio1

    You should explain in better detail how you have your sea_mc movieclip designed.  You make it sound like you have different moiveclips running in parallel but your code seems to say you have them running serially.

     
    |
    Mark as:
  • Currently Being Moderated
    Nov 22, 2011 9:37 AM   in reply to fonzio1

    No, it is not clear.  You start off saying sea_mc contains 100 frames.  Then you talk as if there are a couple of sets of 100 frames, meaning there might be 200 frames.  So if you can clear that explanation up, that will be helpful... if you include a screenshot of your timeline that might even be more helpful.

     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 22, 2011 11:26 AM   in reply to fonzio1

    wow daytime_sea and sunset_sea are labels, not separate movieclips?

    then your code should look like this (if timeline you showed us belongs to one names "sea_mc"

     

    if (hours == 9){
        sea_mc.gotoAndPlay(sea_mc.currentFrame + 101);
    }
    

     

    If you jumped 100 frames forward, you'd be in the exact frame of night sea, so you want to add (100 + 1) frames.

     

    There are ways to get the frame number on which the label is, if you want to use labels and not exact numbers (in case you make your animation shorter or longer..)

     

    import flash.display.FrameLabel;
    import flash.display.MovieClip;
     
    if(hours == 9) {
         switchToNight();
    }
    else if(hours == 1) { // whatever time you want
         switchToDay();
    }
     
    function switchToNight():void {
         var nightSeaFrame:int = getLabelFrameNumber(sea_mc, "sunset_sea");
         sea_mc.gotoAndPlay(nightSeaFrame + sea_mc.currentFrame + 1);
    }
     
    function switchToDay():void {
         var nightSeaFrame:int = getLabelFrameNumber(sea_mc, "sunset_sea");
         sea_mc.gotoAndPlay(sea_mc.currentFrame - nightSeaFrame + 1);
    }
     
     
    /*     UTILS     */
     
    function getLabelFrameNumber(target:MovieClip, label:String):int {
        var index:int = getLabelIndex(target, label);
        if (index == -1) return -1;
        return FrameLabel(target.currentLabels[index]).frame;
    }
     
    function getLabelIndex(target:MovieClip, label:String):int {
        for (var i:int = 0; i < target.currentLabels.length; i++) {
            if (FrameLabel(target.currentLabels[i]).name == label) {
                return i;
            }
        }
        return -1;
    }
    
     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 23, 2011 7:20 AM   in reply to fonzio1

    You need to define intervals, let's say:

    0 - 7: night

    7 - 18: day

    18 - 24: night

     

    then your code should look like:
    if(hours < 7 || hours > 18) {
         shitchToNight();
    }
    else {
         switchToDay();
    }
    

     

    You should improve your methods so you don't jump to nightmode when already in night mode.

     

    function switchToNight():void {
         if(sea_mc.currentLabel == "sunset_sea") return;
         var nightSeaFrame:int = getLabelFrameNumber(sea_mc, "sunset_sea");
         sea_mc.gotoAndPlay(nightSeaFrame + sea_mc.currentFrame + 1);
    }
     
    function switchToDay():void {
         if(sea_mc.currentLabel != "sunset_sea") return;
         var nightSeaFrame:int = getLabelFrameNumber(sea_mc, "sunset_sea");
         sea_mc.gotoAndPlay(sea_mc.currentFrame - nightSeaFrame + 1);
    }
    
     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 23, 2011 8:10 AM   in reply to fonzio1

    I didn't test it since I wrote it in notepad

    Let me know if it works. I believe the code is quite self-explanatory and you should be able to modify the hours easily. Note that the labels in PHASES Array are names of your frame labels so you should modify them accordingly. Also the fact that each phase has the same ammount of frames stays unchanged.

     

    i

    mport flash.display.FrameLabel;
    import flash.display.MovieClip;
     
    const PHASES:Array = [
      {
        hour: 20,
        label: "night"
      },
      {
        hour: 19,
        label: "sunset"
      },
      {
        hour: 7,
        label: "day"
      },
      {
        hour: 6,
        label: "sunrise"
      },
      {
        hour: 0,
        label: "night"
      }
    ];
     
    // you call this function whenewer you want to test hour and possibly change day time
    function checkPhase(hour:Number):void {
      for(var i:int = 0; i < PHASES.length; i++) {
        if(PHASES[i].hour < hour) {
          showPhase(PHASES[i].label);
          return;
        }
      }
      trace("Something went wrong, this line shouldn't execute.")
    }
     
    function showPhase(phase:String):void {
      if(phase == sea_mc.currentLabel) return;
     
      var currentPhaseStart:int = getLabelFrameNumber(sea_mc.currentLabel);
      var frameOffset:int = sea_mc.currentFrame - currentPhaseStart;
     
      var newPhaseStart:int = getLabelFrameNumber(phase);
     
      sea_mc.gotoAndPlay(newPhaseStart + frameOffset);
    }
     
     
    /*     UTILS     */
     
    function getLabelFrameNumber(target:MovieClip, label:String):int {
        var index:int = getLabelIndex(target, label);
        if (index == -1) return -1;
        return FrameLabel(target.currentLabels[index]).frame;
    }
     
    function getLabelIndex(target:MovieClip, label:String):int {
        for (var i:int = 0; i < target.currentLabels.length; i++) {
            if (FrameLabel(target.currentLabels[i]).name == label) {
                return i;
            }
        }
        return -1;
    }
    
     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 23, 2011 11:12 AM   in reply to fonzio1

    wow totally into notepad?, damn i hope to have those kind of skills someday, the code is beyond me, everything works, no errors except the sea remains in daytime whatever the time

    i have changed the numbers to the times i would like each to show and put in the correct labels

    the numbers and labels are fine

     

     

    wondering could the problem be hour?, been checking by hours you see, although it comes up as a keyword if i try to change it here, i suppose i could change hours to hour throughout the code and see if that works, anyway let me know what you think and i will change if you say i should.

    the "hour" in my code is just input parameter in function. you have to call the function checkPhase and pass your "hours". Just add this line:

     

    checkPhase(hours);
    

     

     

    Also is there a reason label "nighttime_sea" is listed twice?, there is no zero in my code as it becomes 24 and then moves to 1.

    Yes, as you can see the algorithm for finding the right day phase goes from the first element in array (highest hour) and goes to the last one (lowest hour). If you put 24 inside, it will finish right at the first item, because 24 > 20 and the phase will be night. If you pass 1, it will finish at the last item, because only 1 > 0. The reason night is mentioned twice is, that hours overflow at night (24) and begin from 0 again, so night is both at the highest and at the lowest hour.

     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 23, 2011 3:01 PM   in reply to fonzio1

    I don't know what's problem exactly (maybe constant in a function).

    Anyways, the code I gave you wasn't meant to be inside a function. Put all my code outside the function hoursrules() and leave only checkPhase(hours) there.

     

    Also, enable Permit debugging in Publish settings so you can paste errormessage with the exact line number.

     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 23, 2011 3:57 PM   in reply to fonzio1

    sorry about that, notepad...

    everywhere where I call getLabelFrameNumber, you have to add first parameter sea_mc, like that:

     

    var currentPhaseStart:int = getLabelFrameNumber(sea_mc, sea_mc.currentLabel);
    
     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 23, 2011 11:57 PM   in reply to fonzio1

    Hours should be getting smaller in the array, I used "0" by purpose as last element. You changed it to "24", which is not right.

     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 24, 2011 3:11 AM   in reply to fonzio1

    No problem. I added few comments but the code is quite self-explanatory. For more information you might need deeper understanding of classes and properties used.

    You can find this information in ActionScript 3.0 language reference.

     

    import flash.display.FrameLabel;
    import flash.display.MovieClip;
     
    // an array that defines which day phase starts at what hour
    const PHASES:Array = [
      {
        hour: 20,
        label: "night"
      },
      {
        hour: 19,
        label: "sunset"
      },
      {
        hour: 7,
        label: "day"
      },
      {
        hour: 6,
        label: "sunrise"
      },
      {
        hour: 0,
        label: "night"
      }
    ];
     
    // the actual function that checks what day phase it is and shows it
    function checkPhase(hour:Number):void {
      for(var i:int = 0; i < PHASES.length; i++) {
         // find appropriate day phase
        if(PHASES[i].hour < hour) {
          showPhase(PHASES[i].label);
          return;
        }
      }
      trace("Something went wrong, this line shouldn't execute.")
    }
     
    // finds right frame to show
    function showPhase(phase:String):void {
         // if the phase is currently set, no need to set it again
      if(phase == sea_mc.currentLabel) return;
     
         // get frame number for start of current phase
      var currentPhaseStart:int = getLabelFrameNumber(sea_mc, sea_mc.currentLabel);
         // get number of frames the animation ran in current phase
      var frameOffset:int = sea_mc.currentFrame - currentPhaseStart;
         // get frame number for start of new phase
      var newPhaseStart:int = getLabelFrameNumber(sea_mc, phase);
         // add offset frames so the animation continues from the exact point and call gotoandplay
      sea_mc.gotoAndPlay(newPhaseStart + frameOffset);
    }
     
     
    /*     UTILS     */
     
    // self-explanatory function, uses methods and properties in flash.display.MovieClip
    function getLabelFrameNumber(target:MovieClip, label:String):int {
        var index:int = getLabelIndex(target, label);
        if (index == -1) return -1;
        return FrameLabel(target.currentLabels[index]).frame;
    }
     
    // self-explanatory function, uses methods and properties in flash.display.MovieClip
    function getLabelIndex(target:MovieClip, label:String):int {
        for (var i:int = 0; i < target.currentLabels.length; i++) {
            if (FrameLabel(target.currentLabels[i]).name == label) {
                return i;
            }
        }
        return -1;
    }
    
     
    |
    Mark as:
  • Peter Celuch
    505 posts
    Nov 17, 2005
    Currently Being Moderated
    Nov 24, 2011 11:01 AM   in reply to fonzio1

    The questions no longer relate to the original one so you should ask it as a new question (as a new thread) - this way you get more people to look at it. I'm not sure about the crashes. And EMBED button should suffice. You should set appropriate characters to be embed (lowercase, uppercase, numbers..).

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points