Countdown Timer in AS3 - actionscript-3

I'm testing the opposite script as a countdown timer, and there's a type error:
TypeError: Error #1034: Type Coercion failed: cannot convert flash.events::Event#33d6b881f29 to flash.events.TimerEvent.
var goalTimerScore: int = Math.floor(Math.random() * 101) + 20;
var Minutes:Number = Math.floor(Math.random() * 11);
var Seconds:Number = Math.floor(Math.random() * 60);
timerMin_txt.text = String(Seconds);
timerSec_txt.text = String(Minutes);
timerWatch.addEventListener(Event.ENTER_FRAME, countTimer);
timerWatch.play();
function countTimer(e:TimerEvent):void {
if (timerWatch.currentFrame == 61) {
Seconds--;
if (Seconds > 59) {
Seconds = 0;
timerSec_txt.text = "0" + Seconds;
Minutes--;
if (Minutes > 10) {
timerMin_txt.text = "" + Minutes;
} else {
timerMin_txt.text = "0" + Minutes;
}
if (Minutes == 0 && Seconds == 0) {
timerWatch.removeEventListener(Event.ENTER_FRAME, countTimer);
timer.stop();
gotoAndPlay("gameover_Hidden3");
return;
}
}
else {
if (Seconds >= 10) {
timerSec_txt.text = "" + Seconds;
} else {
timerSec_txt.text = "0" + Seconds;
}
}
}
}
Any ideas how to solve this?

You have the wrong function parameters, they should be:
function countTimer(e:Event):void {
As a suggestion, running a timer off the frame rate can be pretty inconsistent as it relies on a constant frame rate. Probably better to use a time based approach.
You can use the Timer class for a basic approach. There is an example in the asdocs of a count down.
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html

function countTimer(e: Event): void {
if (timerWatch.currentFrame == 61) {
Seconds--;
if (Seconds < 0) {
Minutes--;
Seconds = 59;
}
if (Minutes == 0 && Seconds == 0) {
timerWatch.removeEventListener(Event.ENTER_FRAME, countTimer);
timerWatch.stop();
gotoAndPlay("gameover_Hidden3");
return;
}
if (Minutes >= 1 && Seconds == 0) {
if (Minutes == 0) {
timerMin_txt.textColor = 0xFF0000;
timerSec_txt.textColor = 0xFF0000;
}
}
}
if (Seconds < 10) {
timerSec_txt.text = "0" + Seconds;
} else {
timerSec_txt.text = "" + Seconds;
}
if (Minutes < 10) {
timerMin_txt.text = "0" + Minutes;
} else {
timerMin_txt.text = "" + Minutes;
}
}

A crucial thing for timer accuracy is the stage.frameRate property. Without maxing it out, accuracy will be multiples of 60 Hz.
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.getTimer;
import flash.utils.Timer;
stage.frameRate = 1000;
const t:Timer = new Timer(0);
t.addEventListener(TimerEvent.TIMER, t_h);
t.delay = 10000; //10 seconds
timestamp = getTimer();
t.start();
public function t_h(e:TimerEvent):void {
trace("countdown complete")
trace(getTimer() - timestamp)
t.stop();
}

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.

Accessing the .name property in a click handler

I am trying to make a simple card matching game via flash + actionscript, and am having major trouble with assigning event listeners and name. I have got all the card generation statements in place, and they all draw onto my stage, but even though I assigning their instance name with newCard.name, the name I get when tracing the click is always "root1" on every single button, and I have no idea why.
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public dynamic class cardGameMain extends MovieClip {
public function cardGameMain() {
addCards();
}
public function addCards() {
var lastCard:int;
for (var i = 1; i < 17; i++) {
var newCard:MovieClip;
newCard = new cardBackSymbol();
newCard.name = "card" + i;
addChild(newCard);
newCard.addEventListener(MouseEvent.MOUSE_UP, decideCard);
if (i == 1 || i == 5 || i == 9 || i == 13) {
newCard.x = 20;
if (i == 1) {
newCard.y = 20;
}
else if (i == 5) {
newCard.y = 240;
}
else if (i == 9) {
newCard.y = 460;
}
else if (i == 13) {
newCard.y = 680;
}
lastCard = 20;
} else if (i > 1 && i < 5) {
newCard.x = lastCard + 145;
newCard.y = 20;
lastCard = lastCard + 145;
} else if (i > 5 && i < 9) {
newCard.x = lastCard + 145;
newCard.y = 240;
lastCard = lastCard + 145;
} else if (i > 9 && i < 13) {
newCard.x = lastCard + 145;
newCard.y = 460;
lastCard = lastCard + 145;
} else {
newCard.x = lastCard + 145;
newCard.y = 680;
lastCard = lastCard + 145;
}
trace(newCard.name + " position is " + newCard.x + ", " + newCard.y);
}
}
public function decideCard(e:MouseEvent):void {
trace(this.name)
}
}
}
Any help on the matter is MUCH appretiated!
You're using the this keyword which is referring to the containing class, not the object clicked.
Try this instead:
public function decideCard(e:MouseEvent):void {
trace(DisplayObject(e.currentTarget).name)
}

Convert seconds to minutes and seconds in Actionscript 3

I'm working with the youtube API and I'm getting the current time on the video as seconds.
What I want to do is to convert them into this: MM:SS
I've tried to google and try different things by myself but nothing seemed to work and be efficient.
I'll be glad to see how it can be done in a good and efficient way thanks in advance!
Something like:
var formattedTime =
(Math.floor(seconds/60)) + ":" + // minutes
(seconds % 60 >= 10 ? "": "0") + // padding for seconds if needed
(seconds % 60)); // seconds
here is a little class I use all the time just for what you need. I've also added a timecodes to seconds method. Simply use it like Timecodes.secondsToTimecode(634); which will output 00:10:34
package com.ronnieswietek.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 + "";
}
}
}
}
var timeStr:String;
//Video's length >= 1 hour
if( seconds >= 60*60 ){
//Format-> H:MM:SS
timeStr = (""+Math.floor(seconds/(60*60))) + //Hours
":"+
("0"+Math.floor((seconds%(60*60))/60)).substr(-2)+ //Minutes
":"+
("0"+(seconds%60)).substr(-2); //Seconds
}else{
//Format-> MM:SS
timeStr = ("0"+Math.floor(seconds/60)).substr(-2)+ //Minutes
":"+
("0"+(seconds%60)).substr(-2); //Seconds
}
Something a little easier to read to get your head around it:
var seconds:int = 200;
var minutes:int = 0;
while(seconds >= 60)
{
seconds -= 60;
minutes ++;
}
trace(minutes, seconds);
The leading zeros part can be done like so:
var secStr:String = String(seconds);
var minStr:String = String(minutes);
secStr = (secStr.length == 1) ? "0" + secStr : secStr;
minStr = (minStr.length == 1) ? "0" + minStr : minStr;
trace(minStr + ":" + secStr);

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;
}