I have created a drag and drop mini-game and, once finished, I wish for the user to be able to click a "try again" button and have the whole thing start over.
I have read in to this and see that there are a couple of options but am stuck as to which would be best for me.
I have created an FLA with all of my library items, an AS file (MainGame.as) with the main game and all of it's functions in one class and a second AS file (MyGame.as) which calls the class file to play the game.
Which would work best for me?
I have nothing on the layers and just cannot figure out how to remove the swf and load it again with the click of a button.
Am I right in thinking that I would add the button to the MyGame file in the timerDone function?
If so, how would I use that to reload the SWF from the start?
Here is my timerDone function ...
function timerDone(e:TimerEvent=null):void
{
if (countDown == 0)
{
count = 0;
finalScore = score;
}
else
{
count = (30) - (myTimer.currentCount);
finalScore = (count * 10) + (score);
}
myText.text = "GAME OVER!";
myText.x = 195;
displayText();
myText2.text = "Your score = " + (finalScore);
displayText2();
}
I am thinking that I add the button after the last line and somehow refresh the SWF, is that right?
Or am I way off?
You should do something like that: you call the function toReplay at the end of your function timerDone:
Function timerDone, after "displayText2();"
tryAgain.addEventListener(MouseEvent.CLICK, toReplay);
Outside the function timerDone
/**
* The function toReplay calls the function init which
* initializes the Timer and all your variables.
**/
function toReplay(e:MouseEvent):void {
e.target.removeEventListener(MouseEvent.CLICK, toReplay);
init();
}
function init():void {
// Timer
count = 0;
finalScore = 0;
myText.text = "";
// etc.
}
And the function init can directly be invoked to initialize all your variables at the begining of the game:
init();
Related
I am building an Adobe Air AS3 IOS and Android App, in which i have a movie clip in the center of the stage. When you start touching this movie clip, you can move it all around the stage.
This is how i'm doing so :
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
MC_M1.alpha = 1;
MC_M1.addEventListener(Event.ENTER_FRAME, ifHitAct);
MC_M1.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
MC_M1.x = 0.516 * gameIntro.stageWidthToUse;
MC_M1.y = 0.75 * gameIntro.stageHeightToUse;
MC_M1.height = 0.2 * gameIntro.stageHeightToUse;
MC_M1.width = MC_M1.height / 1.4;
gameIntro.STAGE.stage.addChildAt(MC_M1,1);
function onTouchBegin(event:TouchEvent)
{
trace("TouchBegin");
if (touchMoveID != 0)
{
trace("It Did Not");
return;
}
touchMoveID = event.touchPointID;
gameIntro.STAGE.stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
gameIntro.STAGE.stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
}
function onTouchMove(event:TouchEvent)
{
if (event.touchPointID != touchMoveID)
{
return;
}
//trace("Moving")
MC_M1.x = event.stageX;
MC_M1.y = event.stageY;
}
function onTouchEnd(event:TouchEvent)
{
if (event.touchPointID != touchMoveID)
{
return;
}
//trace("Ending");
touchMoveID = 0;
gameIntro.STAGE.stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
gameIntro.STAGE.stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
}
When the player actually looses the game, what i am actually doing is the following :
MC_M1.removeEventListener(Event.ENTER_FRAME , ifHitAct);
MC_M1.removeEventListener(TouchEvent.TOUCH_BEGIN , onTouchBegin);
gameIntro.STAGE.stage.removeChild(MC_M1);
MC_M1.alpha = 0;
isDead = 1;
replayButToUse.x = 0.127 * gameIntro.stageWidthToUse;
replayButToUse.y = 0.91 * gameIntro.stageHeightToUse;
replayButToUse.addEventListener(MouseEvent.CLICK, gotoIntro);
This is all happening in a class called : introClassToUse.
So when the users looses, he will get a replay button, and when he clicks it, he will go back to the same class and reload everything, using the following code :
function gotoIntro(event:MouseEvent):void
{
replayButToUse.removeEventListener(MouseEvent.CLICK, gotoIntro);
replayButToUse.alpha = 0;
replayButToUse.removeEventListener(MouseEvent.CLICK, gotoIntro);
stop();
var reload:introClassToUse = new introClassToUse();
}
And so everything loads back up and the game restarts. My problem is, i'm facing a very weird behavior when i tend to replay the game more than 2-3 times. The MC_M1 just stops listening to any touch event, but keeps on listening to ENTER_FRAME events, in which i keep touching the MC_M1 but it seems to not respond to it. I even debugged it remotely from my iPhone, for the first couple of replays, i can see the trace("TouchBegin"); with it's outcome, it was showing me TouchBegin, but after a few replays, the touch events just froze. What am i missing?
Any help is really appreciated, i'm new in AS3, i need to learn so i could manage more
Edit 1 :
I have no code on any frame, i just have lots of AS Classes.
The fla file is linked to an AS Class called gameIntro. In this class, i have linked the following :
- STAGE is an object of type Stage.
- gameIntro.STAGE = stage
Later on, when the user clicks a play button, i call the class introClassToUse. This class has all the game functionalities. All the code present above is in introClassToUse. When the user looses and clicks the replay button, he will go to "goToIntro" function, im which i recall the introClassToUse.
It's all working fine, with several other timers implemented and all, the only problem is that after several replays, the MC_M1 just freezes over
I am removing the MC_M1 each time the user looses and re-add them when i call back the introClassToUse, because i tried to use the .visible property, it didn't work at all ( this is why i am using the gameIntro.STAGE.stage.removeChild(MC_M1)
I know the question is old but maybe someone is still wondering what is going on here (like me).
There are lot of problems in you code but I thing the root of your problem starts here:
function gotoIntro(event:MouseEvent):void{
//...
var reload:introClassToUse = new introClassToUse();
}
It is usually unwanted behavior if simply creating an instance does more than nothing to your program and you don't even need to assign it to variable in this case.
You mentioned this code is located in your introClassToUse class. This basically means that you are creating new instance of your game inside old one and this seem to be completely awry.
You should consider using only instance properties in your class definition and create new introClassToUse() in external classes;
You didn't include many important details about your code like
How the whole class structures look like - for example you can't place line like MC_M1.addEventListener(Event.ENTER_FRAME, ifHitAct);in the scope of your class so obviously you have this in some function and we don't know when and from where it is called.
Where and how your variables are declared, and assigned. It's hard to tell if your MC_M1 is property of an instance or a class, is it internal/public/private/...
Do you link library symbols to your classes or acquire it from stage.
There could be many things that could give you such result. Based on what you wrote I've reproduced behavior similar to what you've describe but using mouse event and a dummy loose condition. This ends the game each time you drop the mc partially outside right edge of the sage, show restart button and starts again if you click it (basically it's mostly your code). It works fine for about 10s and than suddely you can't move the mc anymore. The frame event is still tracing out but touch/mouse is not.
How can it be? I suspect that you could remove only listeners somewhere and have invisible mc stuck on the new one. And this could be easy overlooked, especially if you using static properties. Again we don't even know where is your movie clip coming from so we can only guess what is happening whit your code but I've tried to take the example simple this is how I did it. The problem may lay in some completely different place but you can guess for all scenarios.
Document class of the project - GameIntro.as
package
{
import flash.display.Sprite;
public class GameIntro extends Sprite
{
//Document class. this need to be compiled with strict mode off.
public function GameIntro() {
GameIntro.STAGE = stage;
GameIntro.stageWidthToUse = stage.stageWidth;
GameIntro.stageHeightToUse = stage.stageHeight;
var intro:IntroClassToUse = new IntroClassToUse();
stage.addChild(intro);
}
}
}
IntroClassToUse.as
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
/**
* You need to have library symbol linked to this class in .fla with two mcs -
* mcFromLibrarySymbol (dragable) and repButton (reapatButton)
*/
public class IntroClassToUse extends MovieClip
{
var t = 0; //timer ticks
var fc:uint = 0; //frames counter
var isDead = 0;
var mc;
static var repButton;
var logicContex:Timer = new Timer(30);
public function IntroClassToUse() {
trace("toUse", GameIntro.stageWidthToUse);
mc = mcFromLibrarySymbol;
if(!repButton) repButton = repButtonX;
logicContex.addEventListener(TimerEvent.TIMER, logicInterval);
logicContex.start();
init();
}
internal function init() {
trace("init");
mc.alpha = 1;
mc.addEventListener(Event.ENTER_FRAME, onFrame);
mc.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
mc.x = 0.516 * GameIntro.stageWidthToUse;
mc.y = 0.75 * GameIntro.stageHeightToUse;
mc.height = 0.2 * GameIntro.stageHeightToUse;
mc.width = mc.height / 1.4;
GameIntro.STAGE.stage.addChildAt(mc, 1);
}
internal function onLoose() {
trace("onLoose");
mc.removeEventListener(Event.ENTER_FRAME , onFrame);
mc.removeEventListener(MouseEvent.MOUSE_DOWN, onMDown);
GameIntro.STAGE.stage.removeChild(mc);
mc.alpha = 0;
isDead = 1;
repButton.x = 0.127 * GameIntro.stageWidthToUse;
repButton.y = 0.91 * GameIntro.stageHeightToUse;
repButton.addEventListener(MouseEvent.CLICK, onReplay);
repButton.alpha = 1;
}
internal function onReplay(e:MouseEvent):void {
trace("onReplay");
repButton.removeEventListener(MouseEvent.CLICK, onReplay);
repButton.alpha = 0;
stop();
new IntroClassToUse();
}
internal function onMDown(e:MouseEvent):void {
trace("mouseDow");
GameIntro.STAGE.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
GameIntro.STAGE.stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
}
internal function onMMove(e:MouseEvent):void {
mc.x = e.stageX;
mc.y = e.stageY;
}
//you loose the game if you release you mc with part of it over rigth stage edge.
internal function onMUp(e:MouseEvent):void {
trace("mouseUp");
GameIntro.STAGE.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
GameIntro.STAGE.stage.removeEventListener(MouseEvent.MOUSE_UP, onMUp);
trace("Stage:", GameIntro.STAGE.numChildren);
if (mc.x + mc.width > GameIntro.STAGE.stageWidth) onLoose();
}
internal function onFrame(e:Event):void {
trace("frames", fc++);
}
internal function logicInterval(e:TimerEvent):void {
if (t++ < 300 || !isDead) return;
init();
mc.alpha = 0;
mc.removeEventListener(MouseEvent.MOUSE_DOWN, onMDown);
isDead = 0;
}
}
}
I'm building a memory Flash game, in which there's a timer that gives you a certain amount of time to finish the deck of cards. The code for this timer is shown below:
public function memory():void
{
levelDuration = 10;
gameTime = levelDuration;
var gameTimer:Timer = new Timer(1000,levelDuration);
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired);
gameTimer.start();
}
function updateTime(e:TimerEvent):void // what happens when the time runs out
{
// your class variable tracking each second,
gameTime--;
//update your user interface as needed
timeText.text = "Tijd : " + String(gameTime); //gameTime is defined before the public function memory
}
function timeExpired(e:TimerEvent):void
{
var gameTimer:Timer = e.target as Timer;
gameTimer.removeEventListener(TimerEvent.TIMER, updateTime);
gameTimer.removeEventListener(TimerEvent.TIMER, timeExpired);
finalScore = score;
musicchannel.stop();
gameTimer.stop();
MovieClip(root).gotoAndStop("gameover");
}
Now, this works fine. The timer counts down, and when it expires, it brings you to the gameover screen. However, when you finish the game BEFORE the time expires, the timer doesn't stop. It will bring you back to the gameover screen when it decides it has run out, even when you've started a new game.
I've tried to fix this by putting gameTimer.stop() in other functions that bring you to the gameover screen, but then there was another problem. This occurred while trying to stop the timer in other functions, like this one (stop button while playing):
function stopplaying(event:MouseEvent){
gameTimer.stop();
finalScore = score;
musicchannel.stop();
MovieClip(root).gotoAndStop("introduction");
}
This will give me a compile error 1120: access of undefined property gameTimer.
I understand that the gameTimer usually can only be influenced within a function if that function listens to a TimerEvent, but I don't see any options to do this in any other way.
I've tried to make gameTimer a public variable, but it won't allow me to do that within the main memory function.
Also, when I try to define it a public variable out of a funcion, but within the class, the timer will still count down. But when it expires, it just gives a random high number in return and doesn't go to the gameover screen.
I hope the explanation of my problem wasn't too vague and that you are able to help me with this. This is a schoolproject and it's due pretty soon! Also, I can't figure this out on my own with internet alone :( Several tries have only made things worse, I'm afraid to screw this up now that I've come this far.
You were doing it probably right-ish by declaring it as a public variable.. but where did you declare it?
In AS (all versions) you have function scope. That means if you declare your variable inside a function, that variable "exists" (is accessible) only inside of that function. Check where you are declaring your variable:
public function memory():void
{
levelDuration = 10;
gameTime = levelDuration;
var gameTimer:Timer = new Timer(1000,levelDuration); // <-
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired);
gameTimer.start();
}
That means your variable "gameTimer" is local to the function memory(). You won't be able to use your variable anywhere outside of this function because it exists only inside of memory(). To solve this issue, you have move it outside of the function:
private var gameTimer:Timer;
public function memory():void
{
levelDuration = 10;
gameTime = levelDuration;
gameTimer = new Timer(1000,levelDuration);
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired);
gameTimer.start();
}
That will solve all your issues.
I have been trying to achieve three things in the project without success. I am new at this and have relied on tutorials to get this far. Here we go!!
a. I want to be able to drop label_3 and label_4 on either or targetlabel_3 and targetlabel_4 but not effect the other labels and targets.
b. I want to be able to drop label_2 on top of label_1 once it has been dropped. I am finding that when label_1 has been dropped, it hides the targetlabel_2 and label_2 can't find it's target.
c. I want to change the Alpa of each of labels _1, _2, _3, _4 and _5 to zero when they are dropped on their targets and change the Apha for labels _11, _21, _31, _41 and _51 to 100. (I have changed the Apha to 25 on these for the sake of making it easier for someone to see what I am trying to do).
I have been mucking around for days on this and have hit a brick wall.
Can anyone help please?
import flash.display.DisplayObject;
import flash.geom.Rectangle;
/* Drag and Drop
Makes the specified symbol instance moveable with drag and drop.
*/
var startX:Number;
var startY:Number;
var counter = 0;
var attempts = 0;
var rect:Rectangle;
rect=new Rectangle(100,100,700,500);
correct_txt.text=counter;
attempts_txt.text=attempts;
label_1.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_1.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_2.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_2.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_3.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_3.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_4.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_4.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_5.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_5.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_1.buttonMode = true;
label_2.buttonMode = true;
label_3.buttonMode = true;
label_4.buttonMode = true;
label_5.buttonMode = true;
function Drag(event:MouseEvent):void
{
event.target.startDrag(true,rect);
feedback_txt.text="";
event.target.parent.addChild(event.target);
startX=event.target.x;
startY=event.target.y;
}
function Drop(event:MouseEvent):void
{
event.target.stopDrag();
var myTargetName:String="target" + event.target.name;
var myTarget:DisplayObject=getChildByName(myTargetName);
if (event.target.dropTarget!=null&&event.target.dropTarget.parent==myTarget){
feedback_txt.text="Well done! You have selcted the correct label and placed it in the recommended position on the package.";
feedback_txt.textColor = 0xCC0000
event.target.removeEventListener(MouseEvent.MOUSE_UP,Drop);
event.target.removeEventListener(MouseEvent.MOUSE_DOWN,Drag);
event.target.buttonMode = false;
event.target.x=myTarget.x;
event.target.y=myTarget.y;
counter++;
correct_txt.text=counter;
correct_txt.textColor = 0x0000ff
attempts++;
attempts_txt.text=attempts;
attempts_txt.textColor = 0x0000ff
}else{
feedback_txt.text="Your attempt is not quite correct. You have either selected the incorrect label or placed it in the wrong position. Please try again.";
event.target.x = startX;
event.target.y = startY;
attempts++;
attempts_txt.text = attempts;
}
if (counter==5){
feedback_txt.text="Well done! You have correctly placed all 5 labels";
percentage_txt.text ="Based on your attempts, you have scored "+Math.round ((counter/attempts) *100)+" %";
percentage_txt.textColor = 0x0000ff
}
}
The easiest way to detect when a label is on another label is by using hittest in an enter frame event listener.
stage.addEventListener(Event.ENTER_FRAME, hit_test);
function hit_test(e:Event):void{
if (label_1.hitTestObject(targetLabel_1)) {
trace("Label_1 is hitting targetlabel_1");
label_hit();
}
if (label_2.hitTestObject(targetLabel_2)) {
trace("Label_2 is hitting targetlabel_2");
label_hit();
}
}
When the hittest is activated, the trace text is shown and the function is called. To change the alphas of the labels, use the function being called by the hittest. For example:
function label_hit()
{
label_1.alpha = 0;
label_2.alpha = 0;
label_3.alpha = 0;
}
If you are trying to have conditions to when things can be dragged, seen, or hit tested, that function is also where you can take care of them. For example, If you don't want a label to be visible until the hittest, you have the alpha set to 0 until the function sets it to 100. If you don't want a label to be drageable until then, you create the listener inside the function instead of earlier.
function label_hit()
{
label_1.alpha = 100;
label_1.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_1.addEventListener(MouseEvent.MOUSE_UP,Drop);
}
If you want hittests to occur only after other hittests have already occured, place them in conditions and have the conditions met in the functions.
stage.addEventListener(Event.ENTER_FRAME, hit_test);
function hit_test(e:Event):void{
if (label_1.hitTestObject(targetLabel_1)) {
trace("Label_1 is hitting targetlabel_1");
label_hit();
}
if(condition)
{
if (label_2.hitTestObject(targetLabel_2)) {
trace("Label_2 is hitting targetlabel_2");
label_hit();
}
}
function label_hit()
{
var condition = true;
}
I'm frustrated. I have a button that when it is clicked on, three timers start. It is no problem the first time the button is clicked on because it runs through the three things it is suppose to do. The problem happens when I click on another button to move away from that area of the stage and then click back on the same button again. If I click back too quickly and hadn't finished letting the timer run out, then I see the tail-end of my sequence... it is not resetting.
You'd think this would be easy... that I should be able to just put in a timer.reset() but it doesn't appear to be working. I can't put the reset call into the code because it keeps saying that the timer I am referencing doesn't exist (TypeError: Error #1009: Cannot access a property or method of a null object reference.)
I tried different ways to make sure the timer was called before it tried to reset it but I keep getting the #1009 error and the various ways I have tried using the reset appear to be not working. I don't know both why timer.reset() won't work and how to get around this error. Thanks,
else if (
event.target.name == "num6a"
)
{
trace("num6a clicked on");
TweenLite.to(shape, 1, {x:-608.55, y:-423.05});
close2.visible = true;
close2.addEventListener(MouseEvent.CLICK, checkforclose);
shape.grey6.visible=true;
counterSix++;
if(counterSix > 1){
trace("inside counterSix");
myDelay_sec6a.reset()
myDelay_sec6b.reset()
myDelay_sec6c.reset()
//if(myDelay_sec6a != null){
//trace("myDelay_sec6a is not null!");
//myDelay_sec6a.stop();
//myDelay_sec6a.reset();
//}
}
//section6 timing
var myDelay_sec6a:Timer = new Timer(1000,1);
myDelay_sec6a.addEventListener(TimerEvent.TIMER, goTosec6a);
//myDelay_sec6a.reset();
myDelay_sec6a.start();
function goTosec6a(event:TimerEvent):void
{
TweenLite.to(shape.section6_a, 2, {alpha:1});
trace("seconds 1: cutting edge title appears");
}
var myDelay_sec6b:Timer = new Timer(3000,1);
myDelay_sec6b.addEventListener(TimerEvent.TIMER, goTosec6b);
//myDelay_sec6b.reset();
myDelay_sec6b.start();
function goTosec6b(event:TimerEvent):void
{
TweenLite.to(shape.section6_b, 2, {alpha:1});
TweenLite.to(shape.section6_c, 2, {alpha:1});
trace("seconds 3: first paragraph appears");
}
Taking a peak at your code the way it is currently setup you are going to have quite some trouble down the road making any adjustments to it. I'm not sure if you are doing this in the timeline or in a separate .as file, but you could have a fundamental scoping issue. That is your timer variables are being created in a function which means they are local to that function, so next time you click this button the variable myDelay_whatever is going to be null referenced ( which means running any of its methods is out of the question ). Either way if this is or is not the case, I rewrote some of this that makes it a bit more flexible.
Some of the things I changed include:
Moved your timer functions to remove local scoping ( currently they were setup inside a function perhaps? Either way it's better to have them separate if they are getting used a lot ).
Setup a way to track your timers and remove them when the function is called again.
Added evaluation of current timers that are running before you attempt to add a new one.
Also just as a side note, I haven't tested a single bit of this code but hopefully this puts you on the right track.
close2.visible = true;
close2.addEventListener(MouseEvent.CLICK, checkforclose);
shape.grey6.visible=true;
counterSix++;
if(counterSix > 1){
trace("inside counterSix");
var i:int;
for ( ; i < _timerList.length; i++ ) {
//reset all the timers
_timerList[i].timer.reset();
}
//clear the list
_timerList.length = 0;
}
addTimer( "timer_sec6a", 1000 );
addTimer( "timer_sec6b", 3000 );
//addTimer( "timer_sec6c", 1000 );
Then these are the functions I added:
private function goTosec6a(event:TimerEvent):void {
TweenLite.to(shape.section6_a, 2, {alpha:1});
trace("seconds 1: cutting edge title appears");
}
private function goTosec6b(event:TimerEvent):void {
TweenLite.to(shape.section6_b, 2, {alpha:1});
TweenLite.to(shape.section6_c, 2, {alpha:1});
trace("seconds 3: first paragraph appears");
}
private function goTosec6b(event:TimerEvent):void {
TweenLite.to(shape.section6_b, 2, {alpha:1});
TweenLite.to(shape.section6_c, 2, {alpha:1});
trace("seconds 3: first paragraph appears");
}
//create this somewhere to kepe track of your timers, dont forget to instantiate it _timerList = new Vector.<Object>();`
private var _timerList:Vector.<Object>;
//set the name parameter to timer_sec6a, timer_sec6b etc and it will setup the timer event function for you
private function addTimer( name:String, delay:Number, repeat:int=1 ):void {
//check to see if timer already exists before creating another
if ( !evalCurrentTimers( name ) ) {
//create new timer
var timer:Timer = new Timer( delay, repeat );
timer.addEventListener( TimerEvent.TIMER, this["goTo" + name.split("_")[1]] );
_timerList.push( {timer: timer, name: name} );
}
}
private function evalCurrentTimers( timerName:String ):Boolean {
var i:int;
//check to see that we don't already have a timer with the same name
for ( ; i < _timerList.length; i++ ) {
if ( _timerList[i].name == timerName ) {
return true;
}
}
return false;
}
I am currently using the following code to play audio recordings from the project library.
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.MouseEvent;
var sound1:Sound = new audio1();
var sound2:Sound = new audio2();
var mySoundChannel:SoundChannel = new SoundChannel();
function stopSound():void
{
//This stops all sound in the sound channel.
//If there is nothing playing, nothing happens.
mySoundChannel.stop();
}
//In this function, we create an argument that allows us to tell the function
//what sound to we want it to play.
function playSound(soundname:String):void
{
try
{
mySoundChannel = this[soundname].play(0, 0);
}
catch(error:ReferenceError)
{
trace("playSound: That sound name doesn't exist.");
return;
}
}
//Hook up buttons-->
button1.buttonMode = true;
button1.useHandCursor = true;
button2.buttonMode = true;
button2.useHandCursor = true;
button1.addEventListener(MouseEvent.CLICK, button1click);
button2.addEventListener(MouseEvent.CLICK, button2click);
function button1click(evt:Event):void
{
stopSound();
playSound("sound1");
}
function button2click(evt:Event):void
{
stopSound();
playSound("sound2");
}
I need to pause the currently playing audio when a button is clicked. How do I do this?
You will need to do five things to your current code in order to pause and resume the currently playing sound:
Create a variable that stores the name of the currently playing
sound, and a variable to store the pause position of the audio.
Create a pause function.
Create a resume function.
Expand the current playSound and stopSound functions to work with the new variables.
Hook up the button event listener.
Step 1:
var currentSound:String = "";
var pausePosition:Number = 0;
Step 2: We're going to save the current position of the audio in that second variable we just created. We can get the current play position of the audio using the mySoundChannel.position property, which returns a Number value (matching the Number type we gave the pausePosition variable).
function pauseSound():void
{
//If there's a song to pause...
if(currentSound != "")
{
//Get pause position.
pausePosition = mySoundChannel.position;
//Stop the sound directly.
mySoundChannel.stop();
}
}
Note we didn't call stopSound(). There's a good reason for that. We're going to put an extra line of code in that function shortly that we don't want to use in pauseSound().
Step 3: Now we create the function to resume audio. Note this is NOT the same as playSound(). We're telling it to start playing from pausePosition, not from 0 (the beginning of the sound clip).
function resumeSound():void
{
//If there's a song to resume...
if(currentSound != "")
{
//Start playing the current audio from the position we left off at.
mySoundChannel = this[currentSound].play(pausePosition);
}
}
Step 4: Since we're now working with those variables we declared in step 1, we need to adjust how playSound() and stopSound() work.
In playSound(), instead of just passing soundname to the sound channel, we're going to save the soundname to currentSound.
function playSound(soundname:String):void
{
try
{
currentSound = soundname
mySoundChannel = this[currentSound].play(0, 0);
}
catch(error:ReferenceError)
{
trace("playSound: That sound name doesn't exist.");
return;
}
}
In stopSound(), we need to actually clear the currentSound and pausePosition variables when we stop, to ensure that resumeSound doesn't start audio after we've totally stopped it.
function stopSound():void
{
//This stops all sound in the sound channel.
//If there is nothing playing, nothing happens.
mySoundChannel.stop();
//Clear our variables.
currentSound = "";
pausePosition = 0;
}
GOTCHA WARNING: Ordinarily, you can loop audio by passing an integer other than 0 in the second argument (where I have the 5) in the following code:
mySoundChannel = this[currentSound].play(0, 5);
In the above code, the sound would play from the beginning, and repeat five times.
However, if you are starting the audio from any position other than 0, what will actually happen is that the audio will loop at the position you start at, not at the beginning.
That is to say, if you use this code:
mySoundChannel = this[currentSound].play(1000, 5);
The sound will loop five times, but every time the sound starts over in the loop, it will start playing from position 1000, and NOT the beginning of the sound (0).
I hope that answers your question!