AS3 Simple timer with alarm? - actionscript-3

I have been looking for an example code to create a simple countdown timer .
It would display the time in "Hours : Minutes : Seconds" and I would have the ability to set the time to 10 min, 30 min, 1 hour, 2 hour , etc.
When the timer hits zero, it would do a function. Your help is greatly appreciated. The only stuff I could find online was for counting down to a specific date.

Making a timer is very simple. You can read more on the AS3 Timer Class. Displaying the time as HH:MM:SS is a little bit of work. I use this class when I need to do that:
package com.dop.utils
{
public class Timecodes
{
public function Timecodes()
{
}
public static function timecodeToSeconds(tcStr:String):Number
{
var t:Array = tcStr.split(":");
return (t[0] * 3600 + t[1] * 60 + t[2] * 1);
}
public static function secondsToTimecode(seconds:Number):String
{
var minutes:Number = Math.floor(seconds/60);
var remainingSec:Number = seconds % 60;
var remainingMinutes:Number = minutes % 60;
var hours:Number = Math.floor(minutes/60);
var floatSeconds:Number = Math.floor((remainingSec - Math.floor(remainingSec))*100);
remainingSec = Math.floor(remainingSec);
return getTwoDigits(hours) + ":" + getTwoDigits(remainingMinutes) + ":" + getTwoDigits(remainingSec);
}
private static function getTwoDigits(number:Number):String
{
if (number < 10)
{
return "0" + number;
}
else
{
return number + "";
}
}
}
}
I made a little example that you can see here using this class: http://ronnieswietek.com/cc/alarm/alarm.swf
(and source here: http://ronnieswietek.com/cc/alarm/alarm.fla)
The code I used that utilizes the Timer class is here:
import com.dop.utils.Timecodes;
import flash.events.*;
import fl.controls.*;
import fl.data.*;
import flash.utils.Timer;
var timer:Timer = new Timer(1000); //-- run once a second
timer.addEventListener(TimerEvent.TIMER, onTimer);
var countdown:Number = 0;
var durations:Array = [
{label:'1 minute',time:1},
{label:'5 minutes',time:5},
{label:'10 minutes',time:10},
{label:'30 minutes',time:30},
{label:'1 hour',time:60},
{label:'2 hours',time:120},
{label:'3 hours',time:180}
];
durationBox.dataProvider = new DataProvider(durations);
timerButton.addEventListener(MouseEvent.CLICK, timerHandler);
function timerHandler(e:MouseEvent):void
{
if (!timer.running)
{
var selectedTime:Number = durationBox.selectedItem.time * 60;
countdown = selectedTime;
timeText.text = Timecodes.secondsToTimecode(countdown);
timer.start();
timerButton.label = "Stop";
}
else
{
countdown = 0;
timeText.text = Timecodes.secondsToTimecode(countdown);
timer.stop();
timer.reset();
timerButton.label = "Start";
}
}
function onTimer(e:TimerEvent):void
{
timeText.text = Timecodes.secondsToTimecode(countdown);
countdown--;
if (countdown == 0)
{
timer.stop();
timer.reset();
timeText.text = "ALARM!!!";
}
}

Where accuracy is required you can't rely on the Timer class alone to give you a precise passage of time. Especially if the Flash Player is doing a lot of other work. This is because the Timer classes interval is actually a request and not a guarantee. Let's take a look, start with a trivial implementation of a timer ticking once a second (1000 milliseconds):
private var startTime:uint;
private var ticks:int;
protected function start():void
{
var t:Timer = new Timer( 1000 );
t.addEventListener( TimerEvent.TIMER, timerTick );
t.start();
startTime = getTimer();
}
protected function timerTick( event:TimerEvent ):void
{
trace( 'Ideal: ' + (++ticks) + ' Actual: ' + (getTimer()-startTime)/1000 );
}
Using getTimer (get familiar with getTimer) to measure the actual time we can see within 20 seconds the Timer class is a half a second behind. This drift will vary each time this is run:
Expected: 1 Actual: 1.043
Expected: 2 Actual: 2.083
Expected: 3 Actual: 3.082
…
Expected: 18 Actual: 18.417
Expected: 19 Actual: 19.457
Expected: 20 Actual: 20.5
That's where implementing a Stopwatch comes in handy for measuring time more precisely:
import flash.utils.getTimer;
public class Stopwatch
{
private var startStamp:Number;
private var stopStamp:Number;
private var runTime:Number;
private var _countdownDuration:Number;
private var started:Boolean;
private var stopped:Boolean;
private var paused:Boolean;
function Stopwatch( startNow:Boolean = true ):void
{
if ( startNow )
start();
}
public function start():void
{
runTime = 0;
startStamp = getTimer();
_countdownDuration = 0;
started = true;
stopped = false;
paused = false;
}
public function startCountdown( milliseconds:Number ):void
{
start();
_countdownDuration = milliseconds;
}
public function pause():void
{
if ( started && ! stopped )
{
runTime += getTimer() - startStamp;
paused = true;
}
}
public function resume():void
{
if ( started && paused )
{
startStamp = getTimer();
paused = false;
}
}
public function stop():void
{
if ( started && ! stopped )
{
if ( ! paused )
runTime += getTimer() - startStamp;
stopped = true;
paused = false;
}
}
public function set elapsed( value:uint ):void
{
runTime = value;
if ( running )
startStamp = getTimer();
}
public function get elapsed():uint
{
if ( running )
return ( getTimer() - startStamp ) + runTime;
return runTime;
}
public function get running():Boolean
{
return ( started && ! paused && ! stopped );
}
public function get countdownDuration():Number
{
return _countdownDuration;
}
public function set countdownDuration( value:Number ):void
{
_countdownDuration = value;
}
public function get remaining():int
{
if ( ! _countdownDuration )
return 0;
else if ( _countdownDuration - elapsed < 0 )
return 0;
return _countdownDuration - elapsed;
}
}
Extending the first example with Stopwatch you can effectively measure the passage of time very simply (just remember stopwatch.elapsed is in milliseconds so we'll divide by 1000 for seconds):
private var stopwatch:Stopwatch;
protected function start():void
{
var t:Timer = new Timer( 1000 );
t.addEventListener( TimerEvent.TIMER, timerTick );
t.start();
stopwatch = new Stopwatch;
stopwatch.start();
}
protected function timerTick( event:TimerEvent ):void
{
trace( stopwatch.elapsed/1000 + ' seconds have elapsed',
(60 * 10) - stopwatch.elapsed/1000 + ' seconds remain' );
}
Since stopwatch.elapsed is in milliseconds, you'll want to convert that quantity to different time increments. Following the Single Responsibility Principle we'll make a reusable general use class called StopwatchFormatter to help us consolidate these calculations and expose a readable API:
public class StopwatchFormatter
{
private var elapsed:Number;
public var paddedSize:int;
public var cappedDecimalLength:int;
function StopwatchFormatter( paddedSize:Number = 2, cappedDecimalLength:Number = 1, elapsed:Number = 0 )
{
this.elapsed = elapsed;
this.paddedSize = paddedSize;
this.cappedDecimalLength = cappedDecimalLength;
}
// INPUTS
public function setTimeAsGroup( hours:Number, minutes:Number = 0, seconds:Number = 0, milliseconds:Number = 0 ):StopwatchFormatter
{
elapsed = ( hours * 60 * 60 * 1000 ) + ( minutes * 60 * 1000 ) + ( seconds * 1000 ) + milliseconds;
return this;
}
public function set totalMilliseconds( value:Number ):void
{
elapsed = value;
}
public function set totalSeconds( value:Number ):void
{
elapsed = value * 1000;
}
public function set totalMinutes( value:Number ):void
{
elapsed = value * 1000 * 60;
}
public function set totalHours( value:Number ):void
{
elapsed = value * 1000 * 60 * 60;
}
// CLOCK LIKE
// (converting to int will drop the decimal place)
public function get milliseconds():int
{
return elapsed % 1000;
}
public function get seconds():int
{
return ( elapsed / 1000 ) % 60;
}
public function get minutes():int
{
return ( elapsed / 1000 / 60 ) % 60;
}
public function get hours():int
{
return ( elapsed / 1000 / 60 / 60 ) % 24;
}
// CLOCK PADDED (zeroes in the front)
// 5 becomes "05" , 10 becomes "10" where _paddedSize is 2
public function get millisecondsPadded():String
{
return frontPad( milliseconds );
}
public function get secondsPadded():String
{
return frontPad( seconds );
}
public function get minutesPadded():String
{
return frontPad( minutes );
}
public function get hoursPadded():String
{
return frontPad( hours );
}
// TOTAL
public function get totalMilliseconds():Number
{
return elapsed;
}
public function get totalSeconds():Number
{
return elapsed / 1000;
}
public function get totalMinutes():Number
{
return elapsed / 1000 / 60;
}
public function get totalHours():Number
{
return elapsed / 1000 / 60 / 60;
}
// TOTAL CAPPED
// 3.134 becomes 3.1 where _cappedDecimalLength is 1
public function get totalMillisecondsCapped():Number
{
return capped( totalMilliseconds );
}
public function get totalSecondsCapped():Number
{
return capped( totalSeconds );
}
public function get totalMinutesCapped():Number
{
return capped( totalMinutes );
}
public function get totalHoursCapped():Number
{
return capped( totalHours );
}
// TOTAL CAPPED + PADDED (zeroes in the back and one zero in the front for values less than 0)
// 3.101 becomes "3.10" where _cappedDecimalLength is 2
public function get totalSecondsCappedPadded():String
{
return capped( totalSeconds ).toFixed( cappedDecimalLength );
}
public function get totalMinutesCappedPadded():String
{
return capped( totalMinutes ).toFixed( cappedDecimalLength );
}
public function get totalHoursCappedPadded():String
{
return capped( totalHours ).toFixed( cappedDecimalLength );
}
// UTILITY FUNCTIONS
private function frontPad( n:int ):String
{
var s:String = n.toString();
if ( s.length < paddedSize )
{
var i:int = 0;
var len:int = paddedSize - s.length;
for ( ; i < len; i++ )
{
s = "0" + s;
}
}
return s;
}
private function capped( input:Number ):Number
{
if ( cappedDecimalLength == 0 )
return Math.floor( input );
var decimalFactor:Number = Math.pow( 10, cappedDecimalLength );
return Math.floor( input * decimalFactor ) / decimalFactor;
}
}
Pulling it all together with these two classes and a Timer we have a trivial way to countdown:
private var stopwatch:Stopwatch;
private var time:StopwatchFormatter;
protected function start():void
{
var t:Timer = new Timer( 1000 );
t.addEventListener( TimerEvent.TIMER, timerTick );
t.start();
stopwatch = new Stopwatch;
stopwatch.startCountdown( new StopwatchFormatter().setTimeAsGroup( 1, 10, 30 ).totalMilliseconds );
time = new StopwatchFormatter;
}
protected function timerTick( event:TimerEvent ):void
{
time.totalMilliseconds = stopwatch.elapsed;
var elapsed:String = time.hoursPadded + ':' + time.minutesPadded + ':' + time.secondsPadded + ':' + time.millisecondsPadded;
time.totalMilliseconds = stopwatch.remaining;
var remainig:String = time.hoursPadded + ':' + time.minutesPadded + ':' + time.secondsPadded + ':' + time.millisecondsPadded;
trace( 'Elapsed:', elapsed, "Remaining:", remainig );
}

Related

Restarting timer in action script 3 function resetClock

I'm new to action script 3 so i will be picking your brains I lot.
I'm making a simple 5 min scoreboard for my workplace to use and now im stuck on making the reset button work.
I have made 3 buttons with instance of (start-btn, stop_btn and reset_btn) but I can't figure out the function code for the reset_btn. I need it to go back to 5:00 and stop so you can press start and begin counting from (5:00 or in my case 300) again.
This is my code so far:
import flash.events.TimerEvent;
import flash.utils.Timer;
var timeRemaining:int = 300;
showTime.text = formatTimeRemaining();
var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.stop();
start_btn.addEventListener(MouseEvent.CLICK, startClock);
function startClock(event:MouseEvent):void
{
timer.start();
}
stop_btn.addEventListener(MouseEvent.CLICK, stopClock);
function stopClock(event:MouseEvent):void
{
timer.stop();
}
reset_btn.addEventListener(MouseEvent.CLICK, resetClock);
function resetClock(event:MouseEvent):void
{
timer.reset();
showTime.text = "300";
}
function onTimer( ev:TimerEvent ):void
{
timeRemaining--;
if (timeRemaining < 0)
{
timeRemaining = 0;
loseGame();
}
else
{
showTime.text = formatTimeRemaining();
}
}
function formatTimeRemaining():String
{
var mins : int = int (timeRemaining / 60);
var minstr:String = mins < 10 ? "0" + mins:"" + mins;
var secs:int = timeRemaining % 60;
var secstr:String = secs < 10 ? "0" + secs:"" + secs;
return minstr+":"+secstr;
}
function loseGame():void
{
timer.stop();
trace("Countdown is finished.");
showTime.text = formatTimeRemaining() + (" Time's Up!");
}
function resetClock(event:MouseEvent):void
{
timer.stop();
timeRemaining = 300;
showTime.text = formatTimeRemaining();
}
Simply stop the timer, reset the timeRemaining variable then display it.

User interaction with Leapmotion AS3 library

I can connect the device and attach a custom cursor to one finger, but I can´t use any of the gestures to over/click a button or drag a sprite around, etc.
I´m using Starling in the project. To run this sample just create a Main.as, setup it with Starling and call this class.
My basic code:
package
{
import com.leapmotion.leap.Controller;
import com.leapmotion.leap.events.LeapEvent;
import com.leapmotion.leap.Finger;
import com.leapmotion.leap.Frame;
import com.leapmotion.leap.Gesture;
import com.leapmotion.leap.Hand;
import com.leapmotion.leap.InteractionBox;
import com.leapmotion.leap.Pointable;
import com.leapmotion.leap.ScreenTapGesture;
import com.leapmotion.leap.Vector3;
import starling.display.Shape;
import starling.display.Sprite;
import starling.events.Event;
import starling.events.TouchEvent;
/**
* ...
* #author miau
*/
public class LeapController extends Sprite
{
private var _controller:Controller;
private var _cursor:Shape;
private var _screenTap:ScreenTapGesture;
private var _displayWidth:uint = 800;
private var _displayHeight:uint = 600;
public function LeapController()
{
addEventListener(Event.ADDED_TO_STAGE, _startController);
}
private function _startController(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, _startController);
//adding controller
_controller = new Controller();
_controller.addEventListener( LeapEvent.LEAPMOTION_INIT, onInit );
_controller.addEventListener( LeapEvent.LEAPMOTION_CONNECTED, onConnect );
_controller.addEventListener( LeapEvent.LEAPMOTION_DISCONNECTED, onDisconnect );
_controller.addEventListener( LeapEvent.LEAPMOTION_EXIT, onExit );
_controller.addEventListener( LeapEvent.LEAPMOTION_FRAME, onFrame );
//add test button
_testButton.x = stage.stageWidth / 2 - _testButton.width / 2;
_testButton.y = stage.stageHeight / 2 - _testButton.height / 2;
addChild(_testButton);
_testButton.touchable = true;
_testButton.addEventListener(TouchEvent.TOUCH, doSomething);
//draw ellipse as a cursor
_cursor = new Shape();
_cursor.graphics.lineStyle(6, 0xFFE24F);
_cursor.graphics.drawEllipse(0, 0, 80, 80);
addChild(_cursor);
}
private function onFrame(e:LeapEvent):void
{
trace("ON FRAME STARTED");
var frame:Frame = e.frame;
var interactionBox:InteractionBox = frame.interactionBox;
// Get the first hand
if(frame.hands.length > 0){
var hand:Hand = frame.hands[0];
var numpointables:int = e.frame.pointables.length;
var pointablesArray:Array = new Array();
if(frame.pointables.length > 0 && frame.pointables.length < 2){
//trace("number of pointables: "+frame.pointables[0]);
for(var j:int = 0; j < frame.pointables.length; j++){
//var pointer:DisplayObject = pointablesArray[j];
if(j < numpointables){
var pointable:Pointable = frame.pointables[j];
var normal:Vector3 = pointable.tipPosition;
var normalized:Vector3 = interactionBox.normalizePoint(normal);
//pointable.isFinger = true;
_cursor.x = normalized.x * _displayWidth;
_cursor.y = _displayHeight - (normalized.y * _displayHeight);
_cursor.visible = true;
}else if (j == 0) {
_cursor.visible = false;
}
}
}
}
}
private function onExit(e:LeapEvent):void
{
trace("ON EXIT STARTED");
}
private function onDisconnect(e:LeapEvent):void
{
trace("ON DISCONNECT STARTED");
}
private function onConnect(e:LeapEvent):void
{
trace("ON CONNECT STARTED");
_controller.enableGesture( Gesture.TYPE_SWIPE );
_controller.enableGesture( Gesture.TYPE_CIRCLE );
_controller.enableGesture( Gesture.TYPE_SCREEN_TAP );
_controller.enableGesture( Gesture.TYPE_KEY_TAP );
}
private function onInit(e:LeapEvent):void
{
trace("ON INIT STARTED");
}
private function doSomething(e:TouchEvent):void
{
trace("I WAS TOUCHED!!!");
}
}
}
If a good code Samaritan can update this code to perform a screen tap gesture (or any interacion with any object), I will really appreciate this a lot.
Regards!
controller.enableGesture(Gesture.TYPE_SWIPE);
controller.enableGesture(Gesture.TYPE_SCREEN_TAP);
if(controller.config().setFloat("Gesture.Swipe.MinLength", 200.0) && controller.config().setFloat("Gesture.Swipe.MinVelocity", 500)) controller.config().save();
if(controller.config().setFloat("Gesture.ScreenTap.MinForwardVelocity", 30.0) && controller.config().setFloat("Gesture.ScreenTap.HistorySeconds", .5) && controller.config().setFloat("Gesture.ScreenTap.MinDistance", 1.0)) controller.config().save();
//etc...
Then catch it in the frame event listener:
private function onFrame( event:LeapEvent ):void
{
var frame:Frame = event.frame;
var gestures:Vector.<Gesture> = frame.gestures();
for ( var i:int = 0; i < gestures.length; i++ )
{
var gesture:Gesture = gestures[ i ];
switch ( gesture.type )
{
case Gesture.TYPE_SCREEN_TAP:
var screentap:ScreenTapGesture = ScreenTapGesture ( gesture);
trace ("ScreenTapGesture-> x: " + Math.round(screentap.position.x ) + ", y: "+ Math.round( screentap.position.y));
break;
case Gesture.TYPE_SWIPE:
var screenSwipe:SwipeGesture = SwipeGesture(gesture);
if(gesture.state == Gesture.STATE_START) {
//
}
else if(gesture.state == Gesture.STATE_STOP) {
//
trace("SwipeGesture-> direction: "+screenSwipe.direction + ", duration: " + screenSwipe.duration);
}
break;
default:
trace( "Unknown gesture type." )
}
}
}
When the event occurs, check the coordinates translated to the stage/screen and whether a hit test returns true.
EDIT: Considering I have no idea how to reliable get the touch point x/y (or better: how to translate them to the correct screen coordinates), I would probably do something like this in my onFrame event:
private function onFrame(event:LeapEvent):void {
var frame:Frame = event.frame;
var gestures:Vector.<Gesture> = frame.gestures();
var posX:Number;
var posY:Number;
var s:Shape;
if(frame.pointables.length > 0) {
var currentVector:Vector3 = screen.intersectPointable(frame.pointables[0], true); //get normalized vector
posX = 1920 * currentVector.x - stage.x; //NOTE: I hardcoded the screen res value, you can get it like var w:int = leap.locatedScreens()[0].widthPixels();
posY = 1080 * ( 1 - currentVector.y ) - stage.y; //NOTE: I hardcoded the screen res value, you can get it like var h:int = leap.locatedScreens()[0].heightPixels();
}
for(var i:int = 0; i < gestures.length; i++) {
var gesture:Gesture = gestures[i];
if(gesture.type == Gesture.TYPE_SCREEN_TAP) {
if(posX >= _button1.x &&
posX <= _button1.x + _button1.width &&
posY >= _button1.y &&
posY <= _button1.y + _button1.height) {
s = new Shape();
s.graphics.beginFill(0x00FF00);
s.graphics.drawCircle(0, 0, 10);
s.graphics.endFill();
s.x = posX;
s.y = posY;
stage.addChild(s);
trace("Lisa tocada!");
}
else {
s = new Shape();
s.graphics.beginFill(0xFF0000);
s.graphics.drawCircle(0, 0, 10);
s.graphics.endFill();
s.x = posX;
s.y = posY;
stage.addChild(s);
trace("Fallaste! Intentalo otra vez, tiempo: "+new Date().getTime());
}
}
}
}

gotoandstop problems actionscript 3

I have a memory game program and when the timer runs out, I want it to go to frame 3 where it displays the "game failed" page.
I have it all set up, except when the game runs out of time, the frame just appears to overlap the original frame, instead of going to a completely separate page.
Can anyone help me?
Here is my code:
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.display.MovieClip;
import flash.text.TextField;
public class MemoryGame extends MovieClip{
private var firstTile:cards;
private var secondTile:cards;
private var pauseTimer:Timer;
private var score:int;
private var cardCount:int;
var seconds:Number;
var minutes:Number;
var numberDeck:Array = new Array(1,1,2,2,3,3,4,4,5,5,6,6);
public function MemoryGame(){
//TIMER FUNCTION
var levelTimer:Timer = new Timer(1000, 180);
levelTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler);
levelTimer.addEventListener(TimerEvent.TIMER, timerHandler);
// LEVEL FUNCTION
easyBtn.addEventListener(MouseEvent.CLICK, easyButtonClicked);
medBtn.addEventListener(MouseEvent.CLICK, medButtonClicked);
hardBtn.addEventListener(MouseEvent.CLICK, hardButtonClicked);
score = 0;
txtScore.text=""+score;
//Level button events
function easyButtonClicked(e:MouseEvent):void{
removeChild(levelText);
trace("easy button clicked!");
seconds = 0;
minutes = 1;
txtTime.text = "1:00";
levelTimer.start();
setupTiles();
}
function medButtonClicked(e:MouseEvent):void{
removeChild(levelText);
trace("medium button clicked!");
seconds = 30;
minutes = 0;
txtTime.text = "0:30";
levelTimer.start();
setupTiles();
}
function hardButtonClicked(e:MouseEvent):void{
removeChild(levelText);
trace("hard button clicked!");
seconds = 15;
minutes = 0;
txtTime.text = "0:15";
levelTimer.start();
setupTiles();
}
//Timer handlers
function timerHandler(e:TimerEvent):void {
if (seconds > 00) {
seconds -=1;
}
else {
if (minutes > 0) {minutes -=1;seconds = 59;}
}
txtTime.text = minutes+":"+(seconds >= 10 ? seconds : "0"+seconds);
}
function timerCompleteHandler(e:TimerEvent):void {
e.target.reset();
e.target.stop();
trace("game over!");
}
//Tiles set up
function setupTiles(){
for(x=1; x<=4; x++) {
for (y=1; y<=3; y++){
var randomCard = Math.floor(Math.random()*numberDeck.length);
var tile:cards = new cards();
tile.card = numberDeck[randomCard];
numberDeck.splice(randomCard,1);
tile.gotoAndStop(9);
tile.x = (x-1) * 150;
tile.y = (y-1) * 200;
tile.addEventListener(MouseEvent.CLICK,tileClicked);
addChild(tile);
cardCount = cardCount + 1
}
}
}
}
public function tileClicked(event:MouseEvent) {
var clicked:cards = (event.currentTarget as cards);
if (firstTile == null){
firstTile = clicked;
firstTile.gotoAndStop(clicked.card);
}
else if (secondTile == null && firstTile != clicked){
secondTile = clicked;
secondTile.gotoAndStop(clicked.card);
if (firstTile.card == secondTile.card){
pauseTimer = new Timer(1000, 1);
pauseTimer.addEventListener(TimerEvent.TIMER_COMPLETE,removeCards);
pauseTimer.start();
}
else {
pauseTimer = new Timer(1000, 1);
pauseTimer.addEventListener(TimerEvent.TIMER_COMPLETE,resetCards);
pauseTimer.start();
}
}
if (seconds == 0){
this.gotoAndStop(2);
pauseTimer.stop();
//levelTimer.stop();
}
}
public function resetCards(event:TimerEvent) {
firstTile.gotoAndStop(9);
secondTile.gotoAndStop(9);
firstTile = null;
secondTile = null;
pauseTimer.removeEventListener(TimerEvent.TIMER_COMPLETE,resetCards);
score = score - 2;
txtScore.text=""+score;
}
public function removeCards(event:TimerEvent){
removeChild(firstTile);
removeChild(secondTile);
firstTile = null;
secondTile = null;
pauseTimer.removeEventListener(TimerEvent.TIMER_COMPLETE,removeCards);
score = score + 10;
txtScore.text=""+score;
cardCount = cardCount - 2;
trace("Cardcount: " + cardCount);
if (cardCount == 0){
this.gotoAndStop(2);
txtFinalScore.text=" "+score;
pauseTimer.stop();
}
}
}
}
Thank you so much!
When you add an object using addChild(object) it isn't associated with keyframes along the timeline.
So what you need to do is rather than jumping to frame 2, removeChild(object) or object.visible = false all children you don't want and addChild(object) your 'out of time' assets.
A good work ethic is to create destroy() functions that remove and null any unwanted assets. This way you can easily remove unwanted items and free up memory.

Add or remove time from a countdown

I have a timer script:
import flash.utils.Timer;
import flash.events.TimerEvent;
var secs:Number = 30;//second
var mins:Number = 2;//minute
var sec_t:String;
var min_t:String;
var my_timer:Timer = new Timer(1000);
my_timer.addEventListener(TimerEvent.TIMER, timerHandler);
my_timer.start();
showTimer.text = "02:30";
function timerHandler(event:TimerEvent):void
{
if (secs == 0)
{
if (mins == 0)
{
my_timer.stop();
trace("Countdown is finished.");
showTimer.text =String(min_t+sec_t)+" Times Up";
return;
}
else
{
--mins;
secs = 59;
}
}
else
{
--secs;
}
sec_t = (secs < 10) ? "0" + String(secs):String(secs);
min_t = (mins < 10) ? "0" + String(mins) + ":":String(mins) + ":";
trace(min_t+sec_t);
showTimer.text =String(min_t+sec_t);
}
wrongBtn.addEventListener(MouseEvent.CLICK, wrongClick);
function wrongClick(event:MouseEvent):void
{
secs = secs - 10;
}
correctBtn.addEventListener(MouseEvent.CLICK, correctClick);
function correctClick(event:MouseEvent):void
{
secs = secs + 10;
}
There are two buttons, wrongBtn and correctBtn.
wrongBtn will decrease time by 10 seconds, correctBtn will increase time by adding 10 seconds.
But when the timer second is around 2:05 and I press wrongBtn, the time is displayed incorrectly, like this: "2:0-5". Likewise, when the time is around 2:55 and I press the correctBtn, the time will be displayed as "2:65"...
How can I get this working, so that the output is displayed correctly?
Keep one timer count instead of separate minutes and seconds. You can safely increase and decrease it, and always keep the correct time. To make it readable, just format the output:
import flash.events.TimerEvent;
import flash.utils.Timer;
var timeRemaining:int = 150; // 150 seconds => 2:30 mins
showTime.text = formatTimeRemaining();
var timer : Timer = new Timer (1000);
timer.addEventListener (TimerEvent.TIMER, onTimer);
timer.start();
function onTimer ( ev:TimerEvent ) : void {
timeRemaining--;
if (timeRemaining < 0) {
timeRemaining = 0;
loseGame();
}
else
showTime.text = formatTimeRemaining ();
}
function formatTimeRemaining () : String {
var mins : int = int (timeRemaining / 60);
var minstr : String = mins < 10 ? "0"+mins : ""+mins;
var secs : int = timeRemaining % 60;
var secstr : String = secs < 10 ? "0"+secs : ""+secs;
return minstr+":"+secstr;
}
function loseGame () : void {
timer.stop();
trace("Countdown is finished.");
showTime.text = formatTimeRemaining() + (" Time's Up!");
}
wrongBtn.addEventListener(MouseEvent.CLICK, wrongClick);
function wrongClick(event:MouseEvent):void
{
timeRemaining -= 10;
}
correctBtn.addEventListener(MouseEvent.CLICK, correctClick);
function correctClick(event:MouseEvent):void
{
timeRemaining += 10;
}

AS3.0 Two For-loops with a delay

I've got the following code and i would like to add an delay of 200 ms after each trace statement
for (var x_pos:uint = 0; x_pos <= 12; x_pos++){
for (var y_pos:uint = 0; y_pos <=12; y_pos++){
trace("hello world " +"("x_pos+","+y_pos+")");
//CODE FOR DELAY OF 200ms
}
}
The real situation is a bit more complex but kind of the same:
//For each Row
for (var x_pos:uint = 0; x_pos <= tile_amount-1; x_pos++){
//For each column
for (var y_pos:uint = 0; y_pos <= tile_amount-1; y_pos++){
//New tile;
var newtile:Tile = new Tile;
//Set position
newtile.x = ((40*y_pos)-(40*x_pos));
newtile.y = ((20*y_pos)+(20*x_pos));
//Add to stage
addChild(newtile);
}
}
Anyone any suggestions ?
private var x_pos:uint;
private var y_pos:uint;
private var timer:Timer;
public function startLoop():void
{
x_pos = 0;
y_pos = 0;
timer = new Timer(200);
timer.addEventListener(TimerEvent.TIMER, onTick);
timer.start();
}
private function onTick(event:TimerEvent):void
{
trace("hello world " +"("x_pos+","+y_pos+")");
if (++y_pos <= 12)
return;
y_pos = 0;
if (++x_pos <= 12)
return;
timer.stop();
timer.removeEventListener(TimerEvent.TIMER, onTick);
timer = null;
}
You can't stop the execution of code in the middle of a statement like that, your best bet is to use a timer:
package
{
import flash.events.TimerEvent;
public class Foo
{
private var x_pos:uint = 0;
private var y_pos:uint = 0;
private var timer:Timer;
public function Foo()
{
timer = new Timer(200, 0);
timer.addEventListener(TimerEvent.TIMER, handleTick);
timer.start();
}
public function handleTick(e:TimerEvent):void {
trace("hello world " +"("x_pos+","+y_pos+")");
y_pos++;
if(y_pos > 12){
x_pos++;
y_pos = 0;
}
if(x_pos > 12) timer.stop();
}
}
}
Actionscript does not have a blocking timeout system -- you need to do a recursive function of your own. This following perfect, but it is a start.
import flash.utils.setTimeout;
// call the final function.
delayedRecursion(12,12,200,
function(curX:Number, curY:Number):void
{
trace("hello world " +"("+curX+","+curY+")");
});
//This is really a wrapper around delayedRecursionHelper
function delayedRecursion(maxX:Number, maxY:Number,
delay:Number, callback:Function):void
{
delayedRecursionHelper(0,-1,maxX,maxY,delay,callback);
}
// each time you call this, it creates a function which holds the variables
// passed in, but incremented by 1.
function delayedRecursionHelper(
curX:Number, cury:Number,
maxX:Number, maxY:Number,
delay:Number, called:Function ):Function
{
return function():void
{
called(curX, curY);
// Exit condition: nothing to do here!
if( curX == maxX && curY == maxY ) return;
if( curY == maxY )
{
curY = -1;
curX++;
}
curY++;
setTimeout(delayedRecursionHelper(curX, curY, maxX, maxY, delay), delay);
}
}
You can not delay the loops in as3.
For this purpose you need to use timers. Some help for your solution you can find here: How to show the current progressBar value of process within a loop in flex-as3?
At the end you just need to modify the function logic.