View Full Version : I Hate Timers! Down anybody know the process??
brianemsu
06-16-2008, 07:09 PM
Hi,
I am having much trouble with the Timer. I add one to the object list and make it where the functions can all access it (I think!). Problem is, I can never seem to remove the listener, and all of my scene transitions get screwed.
In those mouse-down functions up top, when you press the button to call one of those, it keeps throwing an error "parameter child must be non-null"... and I seem to be having all kinds of trouble with removing the content function there as well...
Am I doing this right? Could you check out my code and see if I have all of the relationships in order and what-not. All I'm trying to do is transition from one function to the next and be able to use a back, forward and pause button. This is so confusing to me and my head is spinning!:o
package
{
import fl.motion.easing.Back;
import flash.display.*;
import flash.display.MovieClip;
import caurina.transitions.*;
import flash.events.*;
import flash.utils.Timer;
public class Main extends MovieClip
{
public var trinidad :Trinidad;
private var hattera :Hattera;
private var botanique :Botanique;
private var backButton :SimpleButton;
private var pauseButton :SimpleButton;
private var forwardButton :SimpleButton;
private var movieNumber :uint;
public var timer:Timer = new Timer(5000);
public function Main():void
{
init();
}
private function init():void
{
controlBar.back.addEventListener(MouseEvent.MOUSE_ DOWN, onMouseDownBack);
controlBar.forward.addEventListener(MouseEvent.MOU SE_DOWN, onMouseDownForward);
controlBar.pause.addEventListener(MouseEvent.MOUSE _DOWN, onMouseDownPause);
startTrinidad();
}
private function onMouseDownBack(e:MouseEvent):void
{
if (movieNumber == 1)
{
timer.removeEventListener(MouseEvent.MOUSE_DOWN, timerHandler1);
removeChild(trinidad);
//startBotanique();
}
else if (movieNumber == 2)
{
timer.removeEventListener(MouseEvent.MOUSE_DOWN, timerHandler2);
removeChild(hattera);
//startTrinidad();
}
else(movieNumber == 3)
{
timer.removeEventListener(MouseEvent.MOUSE_DOWN, timerHandler3);
removeChild(botanique);
//startHattera();
}
}
private function onMouseDownForward(e:MouseEvent):void
{
}
private function onMouseDownPause(e:MouseEvent):void
{
}
private function startTrinidad():void
{
movieNumber = 1;
trinidad = new Trinidad();
addChild(trinidad);
setChildIndex(trinidad, 0);
trace(movieNumber);
timer.addEventListener(TimerEvent.TIMER, timerHandler1);
timer.start();
}
function timerHandler1(e:TimerEvent):void
{
removeChild(trinidad);
startHattera();
timer.removeEventListener(TimerEvent.TIMER, timerHandler1);
}
private function startHattera():void
{
movieNumber = 2;
hattera = new Hattera();
addChild(hattera);
setChildIndex(hattera, 0);
trace(movieNumber);
timer.addEventListener(TimerEvent.TIMER, timerHandler2);
timer.start();
}
function timerHandler2(e:TimerEvent):void
{
removeChild(hattera);
startBotanique();
timer.removeEventListener(TimerEvent.TIMER, timerHandler2);
}
private function startBotanique():void
{
movieNumber = 3;
botanique = new Botanique();
addChild(botanique);
setChildIndex(botanique, 0);
trace(movieNumber);
timer.addEventListener(TimerEvent.TIMER, timerHandler3);
timer.start();
}
function timerHandler3(e:TimerEvent):void
{
removeChild(botanique);
startTrinidad();
timer.removeEventListener(TimerEvent.TIMER, timerHandler3);
}
}
}
Mazoonist
06-16-2008, 07:31 PM
Well, so far I can see that this line is incorrect:
timer.removeEventListener(MouseEvent.MOUSE_DOWN, timerHandler1); You are asking the timer instance to remove a mouse event from itself, a mouse event it wasn't listening for in the first place.
The matching addEventListener line was this:
timer.addEventListener(TimerEvent.TIMER, timerHandler1);
So the line that removes the listener should look like this:
timer.removeEventListener(TimerEvent.TIMER, timerHandler1);
There may be other problems too, so you should consider uploading your fla and AS files. Timer is not really very difficult to work with, so there is hope! I'm not really clear on exactly what you're trying to make it do, though. It would seem you want it to fire every five seconds. But then by removing the listener again it would seem you want it to only fire once. There is a second parameter that's a repeat count, so you could just do this:
timer = new Timer(5000, 1);
And you would get a timer that only fired once, after a five second delay.
Timer also has start() and stop() methods. You've used the start() method to get it going. You can also use stop() to stop it. You don't necessarily need to throw away the timer every time by using removeEventListener, unless you are sure that you're done with it completely. If only I were clear on what you were trying to achieve and had your files to test, it might be easier to help.
brianemsu
06-16-2008, 08:01 PM
I definitely see that problem now! Man, all of these lines of code start running together in my vision after long periods of time!
Ok, I want to upload my files but the .fla is 1.4 MB alone, I can't get it compressed enough to upload... (500 KB limit)
I will try an explain further what I am doing...
It is an advertisement for three different furniture products (Trinidad, Hattera, and Botanique). I have created a lot of the assets in the fla. The movie starts at Trinidad waits 5 seconds for some timeline animation to complete (what the Timer is for), then removes Trinidad and loads the next furniture product (Hattera). It continues in a loop.
The problem is when I want to add the buttons to skip backwards and forwards. I've done it on the timeline before but skipping around in code when a Timer object is involved has proved daunting! That's why I was trying to remove the listener.. does this also remove the Timer object? I was under the impression that I could add and remove listeners at will to one Timer object (which I created at the top so all the functions could see it) I will try the timer.stop() method you suggested now.
OK, the TimerEvent Listener is gone when I press the button but it still throws a "Parameter child must be non-null" at the removeChild() line...
I have a very rudimentary knowledge of scope when it comes to function to function... I really don't know why I used private on some items and public on others.. I guess just to see if they did something different.
Mazoonist
06-16-2008, 10:32 PM
Okay, if I understand this correctly, you want the timer to display the next product every five seconds. The "forward" button will display the next product and the "back" button will display the previous product. The pause button pauses the timer, but at that point you can still use the forward and back buttons to go to the previous and next products.
What I did is made a mock-up of your application, since it's too big to send with your graphics. So I made product movie clips for your three products, but mine are just simple graphics. I just used a circle, a square, and a triangle to represent the three products, and mine aren't animated. But the principle is the same as if they were. I also made my own version of your control bar and it contains my version of your three buttons. I didn't spend much time on design, as you'll see. :) One thing to note is that there is no need to declare variables for the three buttons or the control bar. Just make sure they all have instance names for the stage instances.
What I did, and what you should do, is create a class called "Product" that will serve as the base class for your three products:
package {
import flash.display.MovieClip;
public class Product extends MovieClip {
}
}
Nothing too earth-shattering about that code, eh? But what it does is gives you a type to use, so that all three products can share the same datatype. So after you make this class, you go back to the library in the fla, and type in "Product" in the base class field (do this for all three products). Notice that the Product.as file imports and extends MovieClip. So your three products will still inherit from MovieClip, but now they'll also share a "Product" type. This will enable you to also create a generic "currentProduct" variable in your main class, which will also be of the "Product" type. This way, all the types are compatible, and your three products can take turns being the "currentProduct." Get it?
So when a new product needs to be displayed, we can ask the application to removeChild(currentProduct) and it will remove whichever clip is being pointed to by that variable, then it will do an addChild on whatever movieNumber is the current one. I kept your movieNumber variable intact, so you had some things right. This is not to say that I am right or you are wrong, but when you program something like this, you need what you might call a "scheme" or a "system." When you realize what's possible to do, naturally you start thinking up better schemes and systems than you did before, and I'm still learning myself. There is some creativity involved, and different people are going to cook up different schemes, and there usually is no one right way to do it, but there are basic techniques.
I made a lot of other changes, but hopefully none that are so radical that you can't understand the flow of things. I added a variable called "isPaused" to indicate whether the timer is paused. There is now just one timerHandler. I used CLICK instead of MOUSE_DOWN, etc, etc.
A way that this whole thing could be better is if the products were in an array, that way you could add more products and you could modify the forward and back functions so that they check for the length of the array (or index 0) instead of a hard-coded number (like 3, as it is now). But for now, I didn't want to overwhelm you.
So check out the system, try it by substituting your own product clips and whatnot, let me know if you understand how it works. Then if you're up to it, I'll help you get those products into an array.
Main.as:
package
{
import fl.motion.easing.Back;
import flash.display.*;
import flash.display.MovieClip;
//had to comment this out for my purposes:
//import caurina.transitions.*;
import flash.events.*;
import flash.utils.Timer;
public class Main extends MovieClip
{
private var trinidad :Product;
private var hattera :Product;
private var botanique :Product;
private var currentProduct:Product;
private var movieNumber :uint;
private var timer:Timer = new Timer(5000);
private var isPaused:Boolean = false;
public function Main():void
{
init();
}
private function init():void
{
controlBar.back.addEventListener(MouseEvent.CLICK, backHandler);
controlBar.forward.addEventListener(MouseEvent.CLI CK, forwardHandler);
controlBar.pause.addEventListener(MouseEvent.CLICK , pauseHandler);
trinidad = new Trinidad();
hattera = new Hattera();
botanique = new Botanique();
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
movieNumber = 1;
currentProduct = trinidad;
addChild(currentProduct);
displayProduct();
}
private function displayProduct() {
removeChild(currentProduct);
if(movieNumber == 1) {
addChild(trinidad);
currentProduct = trinidad;
} else if(movieNumber == 2) {
addChild(hattera);
currentProduct = hattera;
} else if(movieNumber == 3) {
addChild(botanique);
currentProduct = botanique;
}
}
private function backHandler(event:MouseEvent):void {
movieNumber -= 1;
if(movieNumber < 1) {
movieNumber = 3;
}
displayProduct();
}
private function forwardHandler(event:MouseEvent):void {
movieNumber += 1;
if(movieNumber > 3) {
movieNumber = 1;
}
displayProduct();
}
private function pauseHandler(event:MouseEvent):void {
isPaused = !isPaused; //reverse the status of isPaused from true to false or vice versa
if(isPaused == true) {
controlBar.pause.alpha = 0.5; //this is just to give a visual clue that it's paused
timer.stop()
} else {
controlBar.pause.alpha = 1;
timer.start();
}
}
private function timerHandler(event:TimerEvent):void {
//note:same code as the forward button:
movieNumber += 1;
if(movieNumber > 3) {
movieNumber = 1;
}
displayProduct();
}
}
}
brianemsu
06-17-2008, 02:39 PM
Man, I really appreciate your taking the time to help me out! This has been an enormous help! Being the only one that knows Flash at my job really sucks. I'm glad I've got friends here that are willing to help out. I'm planning on going to my first Flash conference this year, are there any group meet-ups where all of us can hang out?
Ok, so I get what you are doing in the code that you wrote. It looks like a good way to set things up. I've transferred the code to my movie and have the buttons working like they should. There is a slight problem though. I set up the animations on the timeline because my lack of time prohibited learning how the buttons work, setting up the animations with Tweener, then trying to get all of that to work together. The animations still work but they all fire at the start of the movie so when one child is removed and the next is added, the new child's animations are done.
Is there an easy way to start the animations over each time a child is added? Or, I was also wondering about the Product class you set up. Could that file be where I place all of the animations for the products (using Tween class). What should go in the Product class, I guess is what I'm wondering. You see, I hate to complicate things further, but it would be great if one product's animations would go through a "complete" or "end" cycle whenever a forward or back button is pressed. The purpose of that is so there isn't an abrupt cut-off of the animation from one clip to the next, but a smooth transition. Does that make sense?
Right now, I have it set up on the timeline so that the animation starts, stops at a stop() frame, then there is a "end" cycle that follows those frames that it could possibly go through, if that could work through code somehow.
Thanks again for your help!
-b
edit: My problem seems to be in the area of importing Library assets to the stage and being able to work with those.
If those product clips (trinidad, hattera, and botanique) have MovieClips inside that play, should I export them for actionscript too.. also with a base class of Product? How do I tell one of those MovieClips to play?
edit2: I see that the clips inside of the Product clips (trinidad, hattera, and botanique) need Properties panel names to work. (I had thought those names get erased upon deletion from the stage)
|
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.