Normally my preloader is 20 frames and looks like this:
Frame 1 Actionscript:
var amountLoaded:Number = _root.getBytesLoaded()/_root.getBytesTotal();
preloader._width = amountLoaded * 200;
loadText.text = Math.round(amountLoaded * 100) + "%";
if(_root.getBytesLoaded() == _root.getBytesTotal()) {
gotoAndPlay(21);
}
else {
gotoAndPlay(1);
}
On Frame 20, we obviously have:
this.gotoAndPlay(1);
This works fine, but it is only the home page I want the intro of my flash to play. Therefore, I use FlashVars on every other page than the home page to tell the animation where it should skip to.
To do this, I have placed this on the first frame after the preloader:
gotoAndPlay(AdFrame);
and in every page except the home page, I have added this Flash Variable:
<param name="FlashVars" value="AdFrame=39" />
My question:
How can I skip the preloader entirely if the animation is loaded?
My failed attempt:
I have tried moving my preloader to start on frame 2, and on frame one, changed:
var amountLoaded:Number = _root.getBytesLoaded()/_root.getBytesTotal();
preloader._width = amountLoaded * 200;
loadText.text = Math.round(amountLoaded * 100) + "%";
if(_root.getBytesLoaded() == _root.getBytesTotal()) {
gotoAndPlay(AdFrame);
}
else {
gotoAndPlay(2);
}
But it still does not bypass the preloader.
Any idea on how I can skip the preloader entirely if the content is loaded?
If I understand this correctly, your condition does not evaluate to true because on the first frame the values returned by the getBytesLoaded and getBytesTotal methods are not the same even when the SWF is loaded from the browser cache.
If this is the case, you could try waiting before checking the load status. Simply moving your code to frame 2 and the start of your preloader animation to frame 3 might be enough. (It's a long time since I've had to work with the timeline but I seem to remember that waiting a frame was often a good rule of thumb).
Alternatively you could pause for a short interval on the first frame before executing your check:
stop();
var interval = setInterval(function() {
clearInterval(interval);
var amountLoaded:Number = _root.getBytesLoaded()/_root.getBytesTotal();
preloader._width = amountLoaded * 200;
loadText.text = Math.round(amountLoaded * 100) + "%";
if(_root.getBytesLoaded() == _root.getBytesTotal()) {
gotoAndStop(3);
}
else {
gotoAndStop(2);
}
}, 500);
You can play around with the interval duration (half a second may be excessive). Note that the interval will be executed each time the play-head is returned to the first frame which, depending on the length of your interval, may not be a problem. If it is a problem, you could consider setting a boolean flag the first time the interval is executed so you can avoid executing it again on subsequent loops.
Related
I'm trying to make a reversed play module in Action Script 3. I have a video, 200 frames long that I imported to Flash as a movie clip. I name the movie clip and inserted some key frames to make the video stop at specific frames, making it a 3 stage animation.
Whenever I swipe/pan to the right (detecting a positive x offset) it gives the command play();, the movie clip will play til it finds a stop.
What I want to achieve is to play it backwards from the current frame til the previous stop when I swipe to the left (detecting a negative offset).
I sorted out the swipe/touch programming and what I'm missing is the backwards bit. I've managed to make it work, going backwards 1 single frame, not the whole bunch that exist prior to hit the previous stop frame. My code for the swipe and play forward is this, with the single prev frame included, which gives me just one frame back instead of the whole set before the previous stop.
Multitouch.inputMode = MultitouchInputMode.GESTURE;
mymovieclip.stop();
mymovieclip.addEventListener(TransformGestureEvent.GESTURE_SWIPE , onSwipe);
function onSwipe (e:TransformGestureEvent):void{
if (e.offsetX == 1) {
//User swiped right
mymovieclip.play();
}
if (e.offsetX == -1) {
//User swiped left
mymovieclip.prevFrame();
}
}
You could try this:
import flash.events.Event;
import flash.display.MovieClip;
//note that this is not hoisted, it must appear before the call
MovieClip.prototype.playBackward = function():void {
if(this.currentFrame > 1) {
this.prevFrame();
this.addEventListener(Event.ENTER_FRAME, playBackwardHandler);
}
}
function playBackwardHandler(e:Event):void {
var mc:MovieClip = e.currentTarget as MovieClip;
if(mc.currentFrame > 1 && (!mc.currentFrameLabel || mc.currentFrameLabel.indexOf("stopFrame") == -1)) { //check whether the clip reached its beginning or the playhead is at a frame with a label that contains the string 'stopFrame'
mc.prevFrame();
}
else {
mc.removeEventListener(Event.ENTER_FRAME, playBackwardHandler);
}
}
var clip:MovieClip = backMc; //some clip on the stage
clip.gotoAndStop(100); //send it to frame 100
clip.playBackward(); //play it backwards
Now you can put 'stopFrame' label to the clip's timeline (stopFrame1, stopFrame2... stopFrameWhatever) and the clip should stop there until playBackward is called again. Note that you should remove the enter frame event listener if the clip hasn't reached a stopFrame or its beginning and you want to call play/stop from the MovieClip API, otherwise it may cause problems.
I have an animation that I want to loop three times and then finish the final frames and then stop. I have tried this code to start with:
var stopNum = 0;
function looper(loopLimit) {
if (stopNum>=loopLimit) {
stop();
} else {
gotoAndPlay(2);
}
this.stopNum++;
}
And this code to stop:
if (!loopCount) {
var loopCount:Number = 0;
}
loopCount++;
if (loopCount >= 3) {
this.stop();
}
I have remaining frames to play from this point and then the entire animation stops. The problem is the frames loop three times but include all the frames including the closing frames.
Try using some events available from Flash 10 like so:
Event.FRAME_CONSTRUCTED
and
Event.EXIT_FRAME
Throwing some idea though, e.g. If your animation ends, then use Event.EXIT_FRAME and keep counter which will tell you that how many times animation is played.
Off the top of my head, I'd use an event listener to check for when the playhead advances for the moiveclip (as mentioned by Rajneesh). Within the event listener, I'd check for what frame it is at, and if it is at the end of my 'end loop frame' and then I'd check if I need to loop it. If so, then I increment a counter to keep track of how many times I've looped, and tell the movieclip to go to the start frame and play again.
Once it's looped enough times, I'd just let it run until the last frame then, on which I'd stop the animation.
I'll take a guess and assume your movieclip has 100 frames, and you only want frame 1 to 90 to loop 2 times, then have it play 1 more time, but from frame 1 to 100. Plays a total of three times from 1 to 90, then once 91 to 100, before stopping.
import flash.display.MovieClip;
import flash.events.Event;
var clip:MovieClip = this.aCircle;
var timesPlayed:int = 0;
var timesToLoop:int = 3;
var frameToStartLoop:int = 1;
var frameToStopLoop:int = 90;
function enterFrameListener(inputEvent:Event):void {
if(clip.currentFrame == frameToStopLoop){
timesPlayed++;
if(timesPlayed < timesToLoop){
clip.gotoAndPlay(frameToStartLoop);
}
// if the currentFrame made it past the above condition, then
// it means there is no more looping needed so just play till the end and stop.
} else if(clip.currentFrame == clip.totalFrames){
clip.stop();
// can remove this listener now, as it is no longer needed
clip.removeEventListener(Event.ENTER_FRAME, enterFrameListener, false);
}
}
// use an event listener to listen for the ENTER_FRAME event, which is triggered everytime the movieclip advances a frame
// (as a side note, you'll also find that this event is triggerd even if there is only 1 frame, or even if the playhead is not actually moving, check the doc for details)
clip.addEventListener(Event.ENTER_FRAME, enterFrameListener, false, 0, true);
My flash game exists of a timeline with multiple frames (I know I should avoid the timeline)
The point of the game is a point and click adventure. The object that you are able to pick up get spawned and destroyed accordingly as you enter and leave the room. now my problem is when entering frame 14 (accessibel from frame 12) it creates a piece of paper which you are able to pick up if you have another item. Now my problem is when you can't or don't pick up the paper and go back to frame 12 (only exit is to frame 12), you can't click on any other object and you are basicly stuck on frame 12. When leaving and entering other rooms it works properly but for some reason it doesn't for on the paper on frame 14.
My code to remove objects works as following
In my Main.as Documentclass I have a function that called as soon as the game starts which does the following
if (lastframe == 14)
{
trace (prop.numChildren);
while (prop.numChildren )
{
prop.removeChildAt(0);
}
}
The lastframe variable is established when moving from frames
this function is found on the frame itself (each exit function on it's own respective frame)
function exitKantine(event:MouseEvent):void
{
Main.lastframe = 14;
gotoAndStop(12);
}
The function to remove the prop actually removes it but then causes all other clickable objects to be unusable.
Thanks for looking at my question and thanks in advance for your suggestions
I would say instead of removing children, add it once in the beginning, add all the listeners in the beginning, and toggle the visibility instead of trying to addChild and removeChild every time you want to hide it. Use an array so you can have a few happening at the same time.
something like this:
private function init():void
{
assignVars();
addListeners();
stage.addChild // make sure this is in document class or you are passing stage to the class using it
}
for (var i = 0; i < _thingsAry.length; i++)
{
if (_thingsAry[i] == 14)
{
_thingsAry[i].visible = false;
trace("the visibility of _thingsAry[" + i + "] is " + _thingsAry[i].visible
}
}
I need to have a swf load at the beginning, but I don't want to play about the last 3 seconds of the video.
Can someone help me out with a code that would basically have my swf play for "x" seconds?
Heres what I Have so far.. Currently it is set up to play the swf, but subtract "x" seconds from it but for some reason it doesn't seem to work
var mySwf:MovieClip;
var reducedTotalFrames:int;
var clipLoader:Loader = new Loader();
clipLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
clipLoader.load(new URLRequest("schoolintro.swf"));
function loadComplete(e:Event):void
{
mySwf = LoaderInfo(e.currentTarget).content as MovieClip;
var totalFrameCount:int = mySwf.currentScene.numFrames;
var secondsToSubtract:int = 3;
var threeSecondFrameCount:int = (stage.frameRate * secondsToSubtract);
reducedTotalFrames = totalFrameCount - threeSecondFrameCount;
stage.addEventListener(Event.ENTER_FRAME, onRender);
stage.addChild(mySwf);
}
function onRender(e:Event):void
{
if(mySwf != null && mySwf.currentFrame >= reducedTotalFrames){
//This is the end of the SWF with 3 seconds trimmed off. Here we can stop play
stage.removeEventListener(Event.ENTER_FRAME, onRender);
mySwf.stop();
//doSomethingElse();
}
}
Try some basic debugging, like placing trace statements in the code inside onRender to ensure it's being called, to ensure the mySwf reference is working correctly (for example, tracing out mySwf.currentScene.numFrames, and if its 0, you know you're not referencing your swf properly or the swf is not frame-based). If it the SWF is not frame-based, then you're going to have real issues controlling or even doing anything about this since all the animation/action going on inside the loaded SWF is code-based.
I think you just need to change this line from
var threeSecondFrameCount:int = (stage.frameRate * secondsToSubtract);
to
var threeSecondFrameCount:int = (stage.frameRate / secondsToSubtract);
not sure is this what you want or not.
i have a problem about action script 3. i have a flv video and its totaltime is 6 seconds. i want to start it from 2. seconds with seekSeconds(). if i write bigger than 6 values in seekSeconds it will only play the video from head to end.İf i write smaller than 6 ,it won't work.what can i write in seekSeconds() to start the video from 2 seconds?
function useParams()
{
var obj:Object = new Object();
var j;
for (j in this.myParams)
{
if (j == "url")
{
src = this.myParams[j];
}
else if (j=="bas")
{
startTime = int(this.myParams[j]);
}
else
{
stopTime = int(this.myParams[j]);
}
txt.text += j + " - " + this.myParams[j];
}
//fk.source = src;
txt.text = String(startTime);
}
fk.addEventListener(VideoEvent.READY, bitti);
function bitti(eventObject:VideoEvent):void
{
//fk.play();
trace(fk.totalTime);
fk.seek(2);
trace(fk.playheadTime);
//trace(fk.playheadTime);
}
According to the documentation for VideoPlayer, Event.READY is dispatched:
Event dispatched when an FLV file is loaded and ready to display. It starts the first time you enter a responsive state after you load a new FLV file with the play() or load() method. It starts only once for each FLV file that is loaded.
It is possible the video is ready but it hasn't buffered to an adequate amount for seeking. You can change the bufferTime to a value greater than 2 although I am not certain that will guarantee Event.READY will get fired at the time you need. Also note the property of seek for progressive downloads:
For a progressive download, you can seek only to a keyframe; therefore, a seek takes you to the time of the first keyframe after the specified time.
So make sure you set a bufferTime that is adequately advanced passed 2 seconds to ensure you are passed a keyframe.
Note: there is a bufferTime on both a VideoPlayer and the NetStream so you may have to adjust one or the other or both.