Creating a countdown timer that brings me to a different frame when it finishes AS3 - actionscript-3

So I am doing a little test with countdown timers to test my limits on AS3 and I've encountered this problem that keeps appearing, the basics of this countdown timer is: if you answer a question right you will get extra time and if you get the question wrong you lose time, when the countdown timer reaches 0 you will be brought to a different frame in which it will say game over.
here is the code I have:
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
var mytimer:Timer=new Timer (1000,count);
var counter:Number=-1;
var RightAnswer:Number=2;
var count:Number=0;
var time:Number=10
var WrongAnswer:Number=-5;
mytimer.addEventListener(TimerEvent.TIMER, timerHandler);
function timerHandler(event:TimerEvent):void{
myText.text= time -counter+"";
counter++;
}
mytimer.start();
function checkAnswer(event:MouseEvent):void{
userAnswer=(txtUserAnswer.text);
userAnswerInt=Number(userAnswer);
if(userAnswerInt==correctAnswer){
time = time + RightAnswer;
}else{
time = time + WrongAnswer;
}
}
mytimer.addEventListener(TimerEvent.TIMER, testing);
function testing (event:Event):void{
if (time <= 0){
gotoAndStop(18);
}
}
I also know it is a problem with the last piece of code as the timer will keep going because the actual time variable is always at 10 and it the timer itself keeps on going down ignoring this piece of code because the time variable is a number variable, but I'm not sure how to change this code.

Related

Animate CC advances to the next frame with gotoAndStop commented out?

I'm writing this code that tests your reaction time and then advances to the next frame. It shows a box and then time the difference between when the box appeared and when the use presses [A]. Heer is my code
import flash.utils.Timer;
import flash.events.Event;
import flash.utils.getTimer;
stop();
var canPress = false;
var startClock:Timer = new Timer(4000+Math.random()*6000, 1);
grbox.y = -500;
startClock.start();
var startTime:int = 0;
function displayBox(evt:Event):void{
canPress = true;
grbox.y = 143;
var startTime:int = getTimer();
}
function Tpressed(e:KeyboardEvent):void
{
if(e.keyCode==Keyboard.A){
if(canPress==true){
var endTime:int = getTimer();
score1 = endTime-startTime;
if(score2<0){
//gotoAndStop(3);
}
else{
//gotoAndStop(4);
}
}
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, Tpressed);
startClock.addEventListener(TimerEvent.TIMER, displayBox);
For some reason if I just spam the [A] button it will advance to the next frame. Why is this happening?!?! My 'gotoAndStop(4);' command is commented out so it should do anything, yet it is.
EDIT: Here is my .fla file: https://drive.google.com/open?id=0BxtLreFIVnSWR2VPSGdSaHZGaVk
RAW CODE: https://docs.google.com/document/d/1GRZIaKAdRNu3z3aPjjXNcgqMl2BhR-ZBT6gU7OeSbWQ/edit?usp=sharing
On one of your frames you added an event listener for key presses to the stage. That's probably where your problem is at. So when you press any key, it calls the pressed function as well as the Tpressed function. And since the key that is being checked for in each function is "A", both functions execute their if blocks. And both if blocks call a gotoAndStop method.
Without knowing exactly what you are trying to accomplish in the big picture, this problem could be fixed by removing the event listener for the pressed function when you leave that frame.
Could look like:
function pressed(e:KeyboardEvent):void
{
if(e.keyCode==Keyboard.A){
gotoAndStop(Math.round(Math.random()+2));
// remove the event listener since we are leaving this frame and you apparently only want this function to work on this frame
stage.removeEventListener(KeyboardEvent.KEY_DOWN, pressed);
}
}

Adding additional time to main timer from movieclip?

Hi so yeah in the main timeline I have the timer
var count:Number = 300;//Count down from 300
var myTimer:Timer = new Timer(1000,count);
myTimer.addEventListener(TimerEvent.TIMER, sayHello);
function sayHello(e:TimerEvent):void
{
trace("Current Count: " + myTimer.currentCount);
}
And when you go into the movieclip reimoi_mcand click the useplush button I want to be able to add additional seconds onto the timer. The following is the code in the reimoi_mc clip but yeah I really have no idea how to make this work, please help ;0; (I have to use MovieClip(root) to access the running timer from the main timeline within the movieclip)
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.utils.getTimer;
stop();
useplush.addEventListener(MouseEvent.CLICK, addtime);
function addtime(e:MouseEvent):void
{
MovieClip(root).count += 2;
MovieClip(root).myTimer.repeatCount += MovieClip(root).count; //add time to the timer
trace("new time " + myTimer.currentCount);
}
I think what you are trying to do is add 2 seconds to the timer in the click handler, and then show how much time is left? If so, just a couple tweaks will do:
function sayHello(e:TimerEvent):void {
trace("Time Left: " + myTimer.repeatCount - myTimer.currentCount); //time left is the repeat count - the current count
}
function addtime(e:MouseEvent):void {
MovieClip(root).myTimer.repeatCount += 2 //add 2 more ticks to the timer (currentCount will always remain the same unless the timer is reset)
trace("new time remaining: " + MovieClip(root).myTimer.repeatCount - MovieClip(root).myTimer.currentCount);
}
BONUS CODE!
If you wanted to make it agnostic of the timer delay (let's say you want it to update quicker than 1 second for instance), you could do this:
var startingTime:Number = 20; //the initial time in seconds
var myTimer:Timer = new Timer(200); //your timer and how often to have it tick (let's say 5 times a second)
myTimer.repeatCount = startingTime * Math.ceil(1000 / myTimer.delay); //set the initial repeat count
myTimer.addEventListener(TimerEvent.TIMER, sayHello);
myTimer.start();
function sayHello(e:Event):void {
trace("Time Left: " + ((((myTimer.repeatCount - myTimer.currentCount) * myTimer.delay) / 1000)) + "seconds");
}
And in your other object:
stage.addEventListener(MouseEvent.CLICK, function(e:Event){
myTimer.repeatCount += Math.ceil(2000 / myTimer.delay); //add 2000 milliseconds to the timer
});
You'd better use an external counter to count the time, instead of stuffing it into a Timer object. You would then need timers to measure delays, and listeners to count them.
var myTimer:Timer=new Timer(1000); // no second parameter
public var secondsLeft:int=300; // former "count"
myTimer.addEventListener(TimerEvent.TIMER, sayHello);
function sayHello(e:TimerEvent):void {
secondsLeft--;
trace("Seconds left:", secondsLeft);
if (secondsLeft<=0) {
myTimer.stop();
myTimer.reset();
// whatever else to trigger when time runs out
}
}
And then you just add to secondsLeft and update the scoreboard.

How to Increase a timer AS3

Hey everyone cant really figure out the easiest approach to this problem.
Basically I have a timer that starts in the beginning of the game like so:
//Create new timer object
tEggTimer = new Timer (nTimerSpeed);
//Listen for timer intervals
tEggTimer.addEventListener(TimerEvent.TIMER, addEggs, false, 0, true);
//start timer
tEggTimer.start();
The nTimerSpeed is equal to (800);
Then I add the eggs like so:
private function addEggs(e:TimerEvent):void
{
//var eggGlobalPosition:Point = _Egg.localToGlobal(new Point(_Bunny.x, _Bunny.y));
_Egg = new mcEgg();
stage.addChild(_Egg);
_Egg.x = _Bunny.x;
_Egg.y = _Bunny.y + 30;
aEggArray.push(_Egg);
trace(aEggArray.length);
}
So in another enter frame function I want to change the value of the timer to (500), but whenever I try like so:
tEggTimer = new Timer (500);
tEggTimer.start();
like So:
private function updateDifficulty():void
{
if (difficultyUpdate) return;
if (nScore >= 2)
{
tEggTimer.removeEventListener(TimerEvent.TIMER, addEggs);
tEggTimer.stop();
tEggTimer = new Timer(200);
tEggTimer.addEventListener(TimerEvent.TIMER, addEggs);
tEggTimer.start();
But this doesnt do anything but stop the timer entirely.
What can I do in order to decrease the timer correctly?
Thanks guys.
If you just want to change the timer speed, while keeping everything else the same, you could just change the delay property in the timer object.
Sample here:
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
var speeds:Vector.<int> = new <int>[1000, 2000, 5000];
var currentSpeed:int = 0;
var timer:Timer = new Timer(speeds[currentSpeed]);
function timerTick(inputEvent:TimerEvent):void {
trace("Timer ticking: "+ getTimer());
}
timer.addEventListener(TimerEvent.TIMER, timerTick, false, 0, true);
timer.start();
function clickedStage(inputEvent:MouseEvent):void {
currentSpeed = ++currentSpeed % speeds.length;
timer.delay = speeds[currentSpeed];
trace("Timer delay set to "+ timer.delay);
}
this.stage.addEventListener(MouseEvent.CLICK, clickedStage, false, 0, true);
Clicking on the stage will change the timer delay from 1 second, 2 seconds, 5 seconds and cycle. I'm just using getTimer() to show the rate of which the timer is ticking.
Note that it seems from the output, every time the value is changed, the timer will automatically restart.
timer.reset();
timer.delay = 2000;
timer.start();
May no be the best way but, instead using nTimerSpeed, make it run through every millisecond:
tEggTimer = new Timer (1);
Then in your AddEggs function use nTimerSpeed and a counter variable. counter is initialize to 0. Incase all your logic in an if statement, increment counter every time through function. if counter equals nTimerSpeed, allow for them inside the if statement and reset counter.
function AddEggs()
{
if(counter == nTimerSpeed)
{
//adding eggs logic
counter = 0;
}
counter++;
}
Did you try saying: tEggTimer.stop() just before re-instantiating with the 500 ms version? I'm guessing that your first Timer instance will just keep firing as your new one starts, unless you deliberately stop it.

Multiple timers help! FLASH as3

I'm making a quiz game, there's 5 questions involved. I made a timer for the 1st question so when the user hasnt answered the question within 10secs they'll go to question 2 (another frame).
Question 1 timer works fine, how do i get question 2 to do the exactly the same as question 1? I tried adding the same code into question 2 however it gives me an error.
Thanks
My code:
stop();
var count:Number = 10;
var myTimer:Timer=new Timer(1000,2);
myTimer.addEventListener(TimerEvent.TIMER, countdown);
myTimer.start();
function countdown(event:TimerEvent):void {
count00.text=String((count)-myTimer.currentCount);
if(count00.text == "0"){
gotoAndStop(85);
}
}
myTimer.stop();
myTimer.removeEventListener(TimerEvent.TIMER, countdown);
First off, you shouldnt be doing this over multible frames. But thats a different discussion.
You should stop your timer, remove the listener and move to next a frame in an onComplete event.
stop();
var count:Number = 10;
var myTimer:Timer=new Timer(1000,count);// this should be the total count
myTimer.addEventListener(TimerEvent.TIMER, countdown);
myTimer.addEventListener(TimeEvent.TIMER_COMPLETE, timerDone);
myTimer.start();
function countdown(event:TimerEvent):void {
count00.text=String((count)-event.currentTarget.currentCount);//get currentCount from event
}
function timerDone(e:TimerEvent):void{
trace("Timer finishing!");
myTimer.stop();
myTimer.removeEventListener(TimerEvent.TIMER, countdown);
gotoAndStop(85);
}
Btw. you are setting the repeatCount of the timer to 2, new Timer(1000,2); this will give you 2 seconds countdown, not much time for a question ;) it should be count
Also there musst be a dynamic textField with the instance name count00 in the same frame (not layer) as the code!!
Please always include relevant error messages in the question!

Sounds play delay wrong

I am writing simple metronome component using Flex + AS3. I want it playing 'tick1' sound after, for example, each 500 millisecond and each 4th time plays another sound 'tick2'. But actually delay between sound is not equivalent - sometimes lesser, sometimes greater a bit. I testing it on latest Chrome.
Here my code:
//Somewhere here button bound to the 'toggle' function
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.media.SoundTransform;
import flash.media.SoundChannel;
private var bpm:Number = 120; //2 bit per second, delay=500ms
private var period:Number = 4;
private var timer:Timer = new Timer(bpm, period);
[Embed(source='sounds/1.mp3')]
private var tickSound1Class:Class;
private var tickSound1:Sound;
[Embed(source='sounds/2.mp3')]
private var tickSound2Class:Class;
private var tickSound2:Sound;
private var trans:SoundTransform = new SoundTransform(1);
private function init():void {
....
tickSound1 = new tickSound1Class() as Sound;
tickSound2 = new tickSound2Class() as Sound;
update();
timer.addEventListener(TimerEvent.TIMER, onTimerEvent);
....
}
private function update():void {
timer.delay = 1000 * 60/bpm;
timer.repeatCount = 0;
}
private function toggle():void {
if (timer.running) {
timer.reset();
startStopButton.label = "Start";
} else {
update();
timer.start();
startStopButton.label = "Stop";
}
}
private function onTimerEvent(event:TimerEvent):void {
var t:Timer = event.currentTarget as Timer;
if (t.currentCount % period == 0)
tickSound1.play(0, 0, trans);
else
tickSound2.play(0, 0, trans);
}
I think there are two main reasons:
It is known that Timer object in Flash Player is inaccurate, delay between it's fires fluctuates.
Sound.play() method also introduces some delay before the sound actually starts to play, and theoretically this delay can fluctuate. The delay is especially noticeable in PPAPI version of Flash Player being used in Chrome.
There are several solutions. I would suggest one of these:
Use pre-composed sound of the whole metronome cycle (tick1-pause1-tick2-pause2) and just loop it using the second argument of Sound.play() method;
use dynamic sound generation.
The second option is more flexible but is more difficult to implement. Basicaly, you'll need to create a new instance of Sound object, subscribe to it's SAMPLE_DATA event and call it's play() method. In the handler you'll check event.position / 44.1, which will give you current position of sound generation in ms. Then, if you decide that it's time to play tick1 or tick2 sound, you'll call tickN.extract(event.data, ...), where tickN is tick1 or tick2 Sound object, or write the silence otherwise.
You can read more about dynamic sound generation here.
Also, notice that when you call Sound.play() it returns a SoundChannel object, which has the position property. Is it a position in ms of a sound that is being played (not generated) at the moment, and it is accurate. So, using this property, you can come up with the third approach: create a Sound object and setup a SAMPLE_DATA handler like in the dynamic sound generation solution, but write the silence (zeros) to the event.data object inside the handler all the time. This is needed to obtain a sound channel without actually playing a sound. Then, use high frame rate (60 FPS) and a Timer with the smallest possible delay (1 ms). Each time the Timer fires, check soundChannel.position to determine whether it is time to play the tick sound, and, if it so, just play it like you're doing in your example. This approach is likely to solve the problem of the Timer inaccuracy, but it cannot deal with the delay caused by tickSound.play() method.