Cant work out why my fading script won't work - actionscript-3

I've run across a piece of code that I'm really struggling to get working... It's meant to wait three seconds before fading an object (swslogo), however when I test it, it doesn't seem to work.. anyone know why this might be
var GameMode:Number = 0;
swslogo.alpha = .0;
var IntroTimer = new Timer(4000,1); //add a 4 second timer
IntroTimer.addEventListener(TimerEvent.TIMER_COMPLETE,swsfadein);
intro();
function intro(e:Event=null):void
{
IntroTimer.reset()
IntroTimer.start();
}
function swsfadein(e:Event=null):void
{
IntroTimer.stop();
swslogo.addEventListener(Event.ENTER_FRAME, fadein)
}
function fadein(e:Event=null){
if(swslogo.alpha <=0){
this.alpha +=0.1;
if(swslogo.alpha >=1){
this.removeEventListener(Event.ENTER_FRAME, fadein);
}
}
}
Edit: Removed accidental line that wasn't meant to be there

From your last few questions I can tell you totally need to learn what a program is, in general, unrelated to AS3 of any other given language, instead of struggling with random pieces of code while treating them like magic spells.
// This part is fine.
var IntroTimer = new Timer(4000,1); //add a 4 second timer
IntroTimer.addEventListener(TimerEvent.TIMER_COMPLETE,swsfadein);
// A method is called. It resets and restarts timer.
intro();
// Another method is called. It stops the times and starts the fading thing.
swsfadein ();
So basically that code in a single go:
Creates timer.
Starts timer.
Stops timer.
Starts fading.
Which obviously suppresses the intended use of the timer.

Related

AS3: how do i stop two of the same function from playing at once?

i am using AS3 to create a function that will automatically play a movieclip all the way through and then remove it. my project is going to have a lot of animated cutscenes, so id like to be able to call this function, use the cutscene id like as a parameter, and then move on to the next. the problem is, im trying to use the function multiple times in a row to play clips sequentially, but they're all playing at the same time. is there a fix, or a better way to do this altogether?
playClip(new a_walk); //find a way to make these stop playing at the same time
playClip(new a_door);
//a_walk and a_door are the AS linkage class names for the movieclips im referring to
function playClip (clip:MovieClip):void {
addChildAt(clip, 0);
clip.mask = myMask;
clip.x=412.4;
clip.y=244.5;
clip.addEventListener(Event.ENTER_FRAME, checkframes);
function checkframes(event:Event) {
if (clip.currentFrame == clip.totalFrames) {
//trace("wow! youre an idiot!");
if (clip.parent) {
clip.parent.removeChild(clip);
trace (100);
return;
}
}
}
}
Sounds like you want a mechanism to play a queue of MovieClips? If so, here is a way you can accomplish this:
//create an array with the clips you want to play (in order), in my example here, the items can be a MovieClip derived Class, or a MovieClip instance
var playQueue:Array = [a_walk, a_door];
//create a var to store the currently playing clip
var currentClip:MovieClip;
playNext(); //call this when you want the queue of clips to start playing
function playNext():void {
//if there was an item previously playing (currentClip has a value), stop it and remove it/dispose of it
if(currentClip){
currentClip.stop(); //stop it from playing
currentClip.addFrameScript(currentClip.totalFrames-1, null); //remove the frame script that was added
currentClip.parent.removeChild(currentClip); //remove it from the display
currentClip = null;
}
//check if there's anything left to play
if(playQueue.length < 1) return;
var nextItem:* = playQueue.shift(); //shift retrieves and removes the first item in the array;
if(nextItem is Class){
//if it's a class, instantiate it
currentClip = new nextItem();
}else{
currentClip = MovieClip(nextItem);
}
//initialize the movie clip
addChildAt(currentClip, 0);
currentClip.gotoAndPlay(1);
//this is just what you were doing before:
currentClip.mask = myMask;
currentClip.x=412.4;
currentClip.y=244.5;
//add a command on the last frame of the movie clip to play the next item in the queue
currentClip.addFrameScript(currentClip.totalFrames-1, playNext);
//addFrameScript is 0 based, so 0 would refer to the first frame. This is why we subtract 1 to get the last frame
}
I should note, that addFrameScript is an undocumented function. It serves as a nice shortcut so you don't have to have an ENTER_FRAME listener checking currentFrame vs. totalFrames. Being undocumented however, one can not count on it's continued existence in future versions of the Flash/AIR runtimes (though it's been around for a long long time)
note
This answer is a work in progress. I'm waiting on a response from the OP.
// playClip(new a_door); don't call this yet, or they will just both play.
var clipData:CustomClass = new CustomClass(); // add an instance of a custom class to hold the value of the movie
//clip being played (so that you can use this value later in the event handler.)
// it will also hold a value of the next clip
clipData._currentClip = a_walk;
clipData._nextClip = a_door;
playClip(new a_walk);
function playClip (clip:MovieClip):void {
addChildAt(clip, 0);
clip.mask = myMask;
clip.x=412.4;
clip.y=244.5;
clip.addEventListener(Event.ENTER_FRAME, checkframes);
}
function checkframes(event:Event) {
if (clipData._currentClip.currentFrame == clipData._currentClip.totalFrames) {
//trace("wow! youre an idiot!");
if (clipData._currentClip.parent) {
playClip(clipData._nextClip);
clipData._currentClip.parent.removeChild(clipData._currentClip);
clipData._currentClip = clipData._nextClip; // moves the clips down
//clipData._nextClip = here we have
//a problem. Do these clips play in a set
//order, first to last? Or do the play out of
//order jumping back and forth? If so, how
//are you planning on controlling which clip
//plays next?
trace (100);
return;
}
}
}
I haven't checked this in Flash yet to see if it works, but I noticed that you are defining a function inside another function, which I don't think is good practice, so this might clean things up for you. Give it a try and let us know.
I'll try to fix my code above when I get a chance. In the meantime, you answered my question about playing the clips in order, so a simple solution would be to put all the clips in an array and then play them by playClip(clipArray[i]) and then when the clip ends and gets removed, do i++ and call the same function playClip(clipArray[i]) which will play the next clip in the array.

AS3: Fast hovering doesn't execute rollOut

I'm having a serious problem that is getting me nervous:
I've made a button _btn that includes ROLLOVER and ROLLOUT animations with coding (an nested movieclip instance called barra that increases to half alpha when you hover over and decreases when you hover out).
[Here it should go a descriptive image but I'm new and I need 10 reputation. I'll appreciate your help]
This works perfectly but the problem occurs when I move my cursor very quickly from one point to another, with the button in between. It seems that the ROLLOUT function is not detected, so the ROLLOVER animation keeps working (and if you look carefully, the animation stops for a few seconds and then continues).
[Here it should go another descriptive image too]
This is the code in the Actions layer:
//Funciones ROLL OVER
function _btnOver(event:MouseEvent):void {
_btn.buttonMode = true;
_btn.addEventListener(Event.ENTER_FRAME,_btnFadeIn);
}
function _btnFadeIn(event:Event):void {
_btn.barra.alpha += 0.1;
if (_btn.barra.alpha >= 0.5)
{
_btn.removeEventListener(Event.ENTER_FRAME,_btnFadeIn);
}
}
_btn.addEventListener(MouseEvent.ROLL_OVER,_btnOver);
//Funciones ROLL OUT
function _btnOut(event:MouseEvent):void {
_btn.addEventListener(Event.ENTER_FRAME,_btnFadeOut);
}
function _btnFadeOut(event:Event):void {
_btn.barra.alpha -= 0.1;
if (_btn.barra.alpha <= 0.2)
{
_btn.removeEventListener(Event.ENTER_FRAME,_btnFadeOut);
}
}
_btn.addEventListener(MouseEvent.ROLL_OUT,_btnOut);
Click here if you want to download the FLA and SWF files, so you can see the problem clearly.
I barely know how to use ActionScript 3 (my only programming knowledge is Processing) and I don't have time now to learn it from head to toe, but I've researched about the problem and it's still not clear.
With tutorials and guides, I managed to learn how to create and understand this code, and I think the problem might be in the functions of the events ROLL_OVER and ROLL_OUT, which contain the addEventListener of the ENTER_FRAME events (where the animations actually are), respectively. But I don't know exactly what I have to do to fix it, what should I add or change.
I would be really glad if someone could help with this, I'm frustrated! What do you recommend me to do?
Thanks in advance
(PD: I don't understand most of the programming language. If you can be as clear and direct as possible, I'll really appreciate it)
Apparently your troubles lay in incoherent animation sequence by using enter frame listeners. You are running two independent listeners, both altering alpha of a single object, this creates a conflict, only one will work (you can determine which if you add both at once and trigger events, the resultant alpha value will indicate which listener changes it last) and you apparently expect one to do a fade in while the other to do a fade out. Instead, you should use one listener (probably even persistent) and give your object "target alpha" property as well as delta to change alpha per frame. An example:
var bbta:Number=0.2; // btn.barra's target alpha
_btn.addEventListener(Event.ENTER_FRAME,_btnFade);
function _btnFade(e:Event):void {
var a:Number=_btn.barra.alpha;
if (Math.abs(a-bbta)<1e-8) return;
// no sense of setting alpha with minuscule difference
const delta:Number=0.1; // how fast to change per frame
if (a>bbta) {
a-=delta;
if (a<=bbta) a=bbta;
} else {
a+=delta;
if (a>=bbta) a=bbta;
}
_btn.barra.alpha=a;
}
function _btnOver(event:MouseEvent):void {
_btn.buttonMode = true; // move this elsewhere, if you don't cancel buttonMode
bbta=0.5; // set target alpha, the listener will do a fade-in
}
function _btnOut(event:MouseEvent):void {
bbta=0.2; // set target alpha, the listener will do a fade-out
}
I edited some code in here, basically i am checking hover state onLoop function, so you can change your settings on here
import flash.events.Event;
var isRolledOver:Boolean = false;
//Funciones ROLL OVER
function _btnOver(event:MouseEvent):void {
isRolledOver = true;
}
function _btnOut(event:MouseEvent):void {
isRolledOver = false;
}
_btn.addEventListener(MouseEvent.ROLL_OVER,_btnOver);
_btn.addEventListener(MouseEvent.ROLL_OUT,_btnOut);
this.addEventListener(Event.ENTER_FRAME,onLoop);
function onLoop(e){
if(this.isRolledOver){
if(_btn.barra.alpha < 0.5) _btn.barra.alpha += 0.1;
}
else{
if(_btn.barra.alpha > 0.5 || _btn.barra.alpha > 0) _btn.barra.alpha -= 0.1;
}
}
I added the sample fla in case

as3 timer turn external device on and off

I am trying to program a Phidgets device to repeatedly turn an external light on for .5 sec and off for .5 sec.
(these times correspond to Frames 1 and 11 of a 20 frame movie clip.
I've tried to insert the on- and off- commands into the movie clip, but they don't transfer to the main stage, so now I'm just trying to program the light to go on and off from the main program
The code below turns the light on and off at the SAME TIME- which means NOTHING HAPPENS.
Does anyone know how to delay the timer so that the off command comes 500 msec AFTER the on command ?
THanks
phid.addEventListener(PhidgetEvent.ATTACH,onAttach);
//connects Phidget to software
function onAttach(evt:PhidgetEvent):void{
trace(evt);
}
var phidControl:Timer = new Timer (500);
phidControl.addEventListener(TimerEvent.TIMER, lightOn);
function lightOn (evt:TimerEvent):void {
phid.setOutputState(0, true);} //this turns the light on
enter code here
var phidOff:Timer = new Timer(500);
phidControl.addEventListener(TimerEvent.TIMER, lightOff);
function lightOff(evt:TimerEvent):void {
phid.setOutputState(0, false);//this turns light off
}
it looks like you're creating two Timers which both run at a 500ms interval simultaneously.
It might be easier to put one function on a 500ms timer, which will call either function intermittently, something like
var lightIsOn = false;
function lightToggle(evt:TimerEvent):void{
if(lightIsOn){
lightOff();
}else{
lightOn();
}
lightIsOn = !lightIsOn;
}
---- UPDATE ----
I'm not very familiar with Phidgets, however that shouldn't make a difference in this case. Try this:
val = true;
var phidControl:Timer = new Timer(500); //If you don't set the repeat count it goes on forever
phidControl.addEventListener(TimerEvent.TIMER, lightToggle);
function lightToggle(evt:TimerEvent):void {
val = !val;
phid.setOutputState(0,val);
}
phidControl.start(); //Make sure you start the timer.
If you only want to switch it once every .5 seconds then you don't have to worry about reading the state of the light, just tell it when to change. So from what I can tell, you don't need the inputChange function.

AS3 - Make the screen flash for half a second

What I want to do is:
After colliding with an [object], I want the screen to flash for about half of a second. I have tried for loops and while loops but they seem to not work. I have no idea how I should program this.
I've been trying to figure out how to do this since I'v been making the game so it would be helpful if someone could help me.
Thank you for reading.
You need to use something that involves time. loops all run in a thread which doesn't pause for time - which is why they don't work.
Here is how you could do this with an AS3 Timer (let's say this code runs right after you've determined there's been a collision)
function flashScreen():void {
var timer:Timer = new Timer(50, 10); //run the timer every 50 milliseconds, 10 times (eg the whole timer will run for half a second giving you a tick 10 times)
var flash:Shape = new Shape(); //a white rectangle to cover the whole screen.
flash.graphics.beginFill(0xFFFFFF);
flash.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
flash.visible = false;
stage.addChild(flash);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
//we've told AS3 to run this every 50 milliseconds
flash.visible = !flash.visible; //toggle visibility
//if(Timer(e.currentTarget).currentCount % 2 == 0){ } //or you could use this as a fancy way to do something every other tick
});
timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(e:TimerEvent):void {
//the timer has run 10 times, let's stop this flashing madness.
stage.removeChild(flash);
});
timer.start();
}
Other ways you can do this are with setInterval, setTimeout, a Tweening library,and an ENTER_FRAME event handler.

Having difficulty in understanding ActionScript 3 Timer class

I'm trying to make a dice game in Flash/ActioScript 3. I did all the essentials and it works smoothly. Now I want to improve the user experience. For instance, when it's computer's turn (to roll and do things according to die value) I want to animate the die. The die has 6 keyframes. So, for, say, 2 seconds the die will loop those 6 frames then it will stop on a value (depending on random generator). Somehow I can't do it as I want. How can I write a function(s) so that when I say,
animateDice()
it will do nothing but just animate the dice for a specified interval?
Update:
var timer:Timer = new Timer(10, 50);
myButton.addEventListener(MouseEvent.CLICK, onClick);
timer.addEventListener(TimerEvent.TIMER, animateDice);
function onClick(event: Event):void {
timer.start();
}
function animateDice(event: Event):void {
dice.play();
}
For instance, I don't understand why the above code doesn't work properly. It does work properly on first click, but not there after.
Update 2: I guess I'm still having problems. How do I suspend the running code until the timer stops? (Yes there is a work around---putting timer handlers inside other timers, etc. Is there an easy way?
Maybe, this will help:
First we see the die rolling (and a message box informs the user that the game will decide whom starts). Then it's either Human's or Computer's turn. When it's computer's turn, first we see the rolling die again for, say, 1 second. Then it stops and and we see the outcome. I'm a beginner and I nay be missing something, but from what I see it seems that all these simple steps (just showing the die rolling for some time) means lots and lots of lines.
If I use a simple timer for die animation, the script continues and the whole show goes away.
The timer object has three properties:
delay, or how often the event should fire
repeatCount, or how many times the event should fire
currentCount, or how many times the timer's event has fired thus far
You are creating the timer with new Timer(10, 50), which sets delay to 10 and repeatCount to 50. This means that, once you call timer.start(), timer will fire TimerEvent.TIMER every 10 milliseconds. Each time it is fired, it adds 1 to currentCount. When currentCount is greater than or equal to repeatCount (50), it stops looping the timer.
Once your timer has stopped, if you call timer.start() again, it will only fire the event once, because currentCount has not been reset to zero, and is still >= repeatCount.
If you call timer.reset() before calling timer.start(), it will set this value to zero and things should behave as expected.
var timer:Timer = new Timer(2000, 1);
myButton.addEventListener(MouseEvent.CLICK, onClick);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
function onClick(event: Event):void {
timer.reset();
timer.start();
dice.play();
}
function onTimerComplete(event:TimerEvent):void {
var roll:int = int(Math.floor(Math.rand()*6))+1;
dice.gotoAndStop(roll);
}
The timer is set to run only once, for 2000 milliseconds (which are 2 seconds). When Click occurs, the timer is reset (so that if it's not the first time it was clicked, it will run as if it was the first time) and started, and the animation starts a well. After 2 seconds, TIMER_COMPLETE will be fired by the timer, and we catch it and determine a final number for the die, then gotoAndStop to that frame.
I didn't try to compile the code, but the gist of it should work for you.
P.S, dice is the plural of 'die' :) you're skipping a great opportunity for the type of variable names we all want to use but can't!
You could try something a little more like this:
var t:Timer = new Timer(10, 50);
t.addEventListener(TimerEvent.TIMER, timerHandler);
t.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler);
t.start();
function timerHandler(e:TimerEvent):void {
gotoRandomFrame();
}
private function timerCompleteHandler(e:TimerEvent):void {
var finalNum:int = gotoRandomFrame();
// Using finalNum
}
private function gotoRandomFrame():int {
var num:int = Math.floor(Math.random() * 6) +1;
dice.gotoAndStop(num);
return num;
}
So use gotoAndStop to set your frame rather than using play