Have images change using Flash AS3 - actionscript-3

So I have this assignment due tomorrow and Its to make an audio player in Flash using as3. I don't understand as3 at all. I have the code for the player working becuase I just used the same code we used in class, but I kind of want to make it my own.
I have created an Ipod style player.
First thing, I want the Forward button to play the next song. How would I write the code for that?
Next When a song plays I want a specific image to show up. and when the next song comes on the next image to show
This is the code i have for the songs
function playTrack(e:MouseEvent) :void {
switch(e.target.name) {
case "track1":
trackToLoad = "audio/Don't Stop Believing.mp3";
trackName = "Journey • Don't Stop Believing"
break;
case "track2":
trackToLoad = "audio/Never Never Land.mp3";
trackName = "Metallica • Never Never Land"
break;
...
but instead of having just a stop and play button and 10 buttons that play each song I want to have a skip button to go to the next song..
hope this is enough info for some help
Thanks

Set your tracks up as an array of objects:
var track1:Object = {
track: 'Don\'t stop believing',
artist: 'Journey',
file: 'dont_stop_believing.mp3'
};
var track2 //same as above
var tracks:Array = [track1, track2, ...];
You could really create a Track class, but it sounds like you aren't to that point yet.
Instead of making your playTrack function actually be the mouse event handler, you should separate it out so that it can be used universally no matter how the track begins to play (i.e. clicking on that track's button, clicking on the next button, or after the previous song ends). Write a separate function just to handle the mouse event (i.e. clickTrack()), which will call your playTrack() function.
Setting your tracks up within the array will allow you to keep note of the indices of each track (including the currentTrack) as a number. That way you can iterate through the tracks by just incrementing the currentTrack variable.
This way, you can set your playTrack() function up to take a trackNumber parameter (i.e. playTrack(1). Then just use that parameter to reference the index of the track you want to play within the tracks array. Remember that arrays are on a 0 index meaning that the first element is index [0], the second is [1], etc. So you'll either have to write your playTrack() function in that way, or convert by subtracting 1.

Try storing some kind of Track object in an indexed array. You can keep track of the index, and change it when the user clicks skip or back. The Track object could store the filepath, the track name, and the art that you want to display. When the index changes, grab the correct track from your array and update the player.
Here is an example that actually uses song titles.

Related

How to save data in previous frame in Flash

I have some movieclips called one, two, three, four, five that appear on stage with addChild. I also have 4 editable text fields on stage called theText1, theText2, theText3 and theText4 where users must write the numbers 4, 1, 5, 2 in each one. If they write something wrong they are sent in a next frame where they take some feedback and come back in current frame to correct their answer. The problem is that when they come back all are "reset". Movie clips added before and numbers written before must be on stage. How can i do that? (I need something simple because i am new to flash and as3).
Because MovieClips don't store frame states.
You should store values, and restore them, after returning to the frame.
//Add these 2 helper functions in your frame with Quiz UI
function restoreValues():void{
if(this.storedValues != null){
//Restore data
theText1.text = this.storedValues.txt1;
}
}
function storeValues():void{
//Save as much data as you want
this.storedValues = {
txt1 : theText1.text
};
}
When you go to the another frame, call storeValues right before you change frame and store all necessary data in simple object.
checkQuizButton.addEventListener(MouseEvent.CLICK, onCheck);
function onCheck(e: MouseEvent):void{
storeValues();
nextFrame();
}
In the frame with Quiz ui components, just after initialisation of all ui components, call restoreValues(); Don't forget to change functions for your needs.

as3 how can i prevent that a new instance is created by entering a frame?

i am working with several nested movieclip objects in a project. but i get into trouble with the buttons i created and implemented in the nested movieclips:
to describe it in a simple way:
I have a main movieclip with five frames, including two buttons with listeners to browse between the frames. Then inside of one Frame I have another movieclip with its own buttons. i instanciated it by hand not through code and gave it a specific name like "nestedMc".
Now I dont want to build the Listeners for those buttons inside the class of the nested movieclip class but in its parent class, which works fine until i then goto another frame in the main movieclips timeline and come back.
obviously every time flash enters a frame its contents get created anew (and therefore get new instance names). I could now try solve this through filling the frames via code.
But maybe there is another way to make sure the frame contains the same instance everytime i enter?
Timeline scripting is a dirty business, and really, a carry-over compatibility layer for Actionscript 2 projects. Whenever possible, I highly recommend not doing it, and simply keeping all of your code in your document class. As you're experiencing, timeline code causes headaches.
Consider instead just creating both states of your Stage (it sounds like that's what your two buttons are jumping between) and simply hiding them offstage or setting their alpha to zero and their mouseEnabled state to false. Furthermore, if the purpose of your frames is to play animation (a tween), consider instead switching to a much more powerful suite such as TweenLite. Moving an object over a hundred pixels (smoothly) can be as easy as:
TweenLite.to(redBall, 3, {x:100});
Now, if you're manually adding these items to the stage, as long as the object is a dynamic one, you can assign an instance name to it which will be saved between frame loads. Be aware the object name is not the same as the instanced name. For example:
var redBall:Ball = new Ball();
redBall.name = "bubbles";
The object's name is Ball, but it's represented as a variable called redBall. Its actual DisplayList name will likely be ambiguous (such as "Instance71"), and I can manually define it as "bubbles". 3 different names for the same object, all very different and necessary.
Even if you give the object a displayList name, you may not be able to reference it through code unless you enable Automatically declare stage instances, which basically creates on each object a pointer to the displayList object.
That said, you can always fetch the object by other means. Obviously, your buttons are always appearing, but you're trying to find a very specific object on the stage. At this point, we can use getChildByName() or getChildAt().
Hope that helps.
-Cheers

Actionscript to play/pause audio on different buttons

I've created a few buttons in Flash. I'm trying to make it so that if you click one button, the audio starts playing for that button. If you click another button, the active audio stops and the new audio of the button you clicked last start playing.
Any help please?
What you're describing is actually quite easy to do.
First things first, I recommend importing the audio into your Flash project. Alternatively, there is a way to play it directly from an external file. This is beyond the scope of my answer, so if you need help on that, you should post a question specifically covering it.
Assuming you have imported the audio file into your Flash project's library, make an as3 instance of it. (Right click the file in the library, click Properties --> ActionScript [tab] --> [Check] Export for ActionScript & [Enter name in] Class)
Now, create a definition of the sound in your code. (Assuming your two sounds were named "mySound1" and "mySound2" in the Class field of the previous step.)
var mySound1:Sound = new mySound1();
var mySound2:Sound = new mySound2();
Now, define your sound channel.
var mySoundChannel:SoundChannel = new SoundChannel();
There are two alternate ways of stopping one sound and playing another. The first is to create one function that does both every time. The second method is to create two formulas, one for "play" and one for "stop". You will need to decide which method works best for you. I'll use the two-function method below:
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
{
mySoundChannel = this[soundname].play(0, 0);
}
[Note, you can tweak the play() properties to meet your needs, doing things like starting in the middle of the song, or looping it forever. 0,0 starts at the beginning, and doesn't loop. See the documentation for this.]
Now you hook up the event listeners for the buttons. (If you need help with event listeners, read the documentation.)
myButton1.addEventListener(Mouse.CLICK, btn1Click);
myButton2.addEventListener(Mouse.CLICK, btn2Click);
function btn1Click(evt:Event):void
{
stopSound();
playSound(mySound1);
}
function btn2Click(evt:Event):void
{
stopSound();
playSound(mySound2);
}
This should be enough information to get you started. In my game core, I actually have a custom class for dealing with sound playback that gives me the ability to repeat sounds, change volume, and keep sounds from conflicting with each other. I say that to emphasize that you can do quite a bit with the sound class. Do some digging in that documentation for ideas and help.
You may also consider putting a try-catch statement in the playSound function, since it will throw an reference error if you pass a name for a sound that doesn't exist.

AS3 save previous frame while going in next to do something

Is posible something like this: in frame1 I have some user interaction (drag drop graphics etc), when user click some button I open frame2 or frame3 where are fields for taking some input from user, then when user finish, I back him to frame1 but frame is not "reset"? I tried what described here, and I can even send data from frame 2 to frame 1 using global vars, but frame 1 is "reset" all user actions are clean, so is there a way in this situation to keep frame1 in memory or something?
Previous or next go to a frame if the frame is being initialized is natural. There's no way to save it. In other words, move the frame is The following concepts, removeChild(previous-stage), addChild(next-stage)
In my experience, the script code to control the frame, increasing complexity are highly undesirable. Maintenance is difficult and in the future, the readability of the code is very poor. Recommend to handle than that in a single frame. Something like a single frame of the object location, size, status, and stored as a variable because it can restore it, it's more reasonable to think that.
If you are working with Flash & AS3 together you can put the code:
gotoAndStop(3); // 3 is the number of the frame
If you are using:
gotoAndPlay(3); // it will begin to play the frames from 3 till the timeline finds a stop mark.
So, you'll need to put a stop on the frame you want.
e.g. stop();
check out this tutorial: http://www.youtube.com/watch?v=9N9vE7wjoc4

EventDispatcher between an as and an fla?

I am making a fighting game in Flash and while I have everything running, I am missing something: a victory/loss screen. Logically, I know how to do it:
if character.hp < 0
{
character.dead = true;
dispatchevent("death", event)
}
My problem is that I have no idea as to how to code it. I know I will use two classes and my two .fla files (unless I am wrong).
I have two .fla files that are in play here: the Menu.fla file and the Arena.fla file. Menu.fla contains the entire navigation of the game, options, character selection screens, etc. and when it is time for the player to engage in battle, it loads the Arena.fla file, which contains only the backgrounds (depending on the selected stage) and for now is set to a length of one frame only. For Arena.fla, the real action happens in my classes, but logically, I would only need HP.as and Character.as.
In Character.as, I have declared the following variable:
var isDead:Boolean = false; //is character dead?
In HP.as, believe I should have the following:
if(currentHp<0)
{
currentHp = 0;
character.isDead = true; //declared as var `character:Object;`
EventDispatcher.dispatchEventListener("playerDead", playerDead);
}
And finally, in Arena.fla, I want to be able to detect the above-mentioned eventlistener and simply move on to a second frame which will display a message in the style of "PLAYER ONE HAS WON" or "PLAYER ONE HAS LOST" with a button that will allow me to go back to the character selection screen. This is the first part in which I am stuck: how do I detect the dispatched event listener in my main .fla file?
Secondly, if the player clicks on the "CONTINUE" button, which displays regardless if the player has won or lost, how can my Menu.fla (which loads the Arena.swf) detect this click event, unload the game, and go back to the character selection screen?
Thank you in advance for helping me out. I realize this is a lot of text but it's the most descriptive I can be. If you have any questions or need any clarification concerning my question, feel free to speak up.
-Christopher
I'm not sure about the code you have to read the HP but do you know that character.dead is actually becoming true?
You could always have the Arena.swf call a function in the HP.as that will end the game and declare a winner.You could add a second Frame to Arena.swf that contains a dimmed background and a WINNER or LOSER text.'
In general, the easiest way for a user-defined class to gain event dispatching capabilities is to extend EventDispatcher. If this is impossible (that is, if the class is already extending another class), you can instead implement the IEventDispatcher interface, create an EventDispatcher member, and write simple hooks to route calls into the aggregated EventDispatcher.
activate
Dispatched when Flash Player or an AIR application gains operating system focus and becomes active.
deactivate
Dispatched when Flash Player or an AIR application loses operating system focus and is becoming inactive.
Event dispatcher
Thank you all for your help, but I have figured it out. Turns out my method was far too complicated for what I wanted to do, and for the time I had left. I will explain how I did it.
Instead of using an EventDispatcher like I thought I would, I used a SharedObject, which simply made everything work like magic.
A SharedObject can be accessed from anywhere in the application/game, as long as it is referred to it correctly. So I simply created a SharedObject called "winLossData" set to "NO WINNERS" in my character selection screen. This cookie is never saved nor written to the disk, so there's no chance for the user to find it (generally speaking).
I have decided to use the Movement.as class which contains all of my controls and wrote an event listener of type Event.ENTER_FRAME that checks constantly my characters' health status. If one of them is below 100, my SharedObject immediately takes for value either "PLAYER ONE" or "PLAYER TWO", depending on who won (i.e. whose health points are not under 100). Afterward, just for precaution, I reset the losing character's health points to 100. Here's the code:
function whoWon(event:Event):void
{
if(playerSpriteBar.getPower() <= 0)
{
winner.data.winner = "Player Two";
playerSpriteBar.update(100);
}
if(playerAIBar.getPower() <= 0)
{
winner.data.winner = "Player One";
playerAIBar.update(100);
}
}
In my Menu.fla, I have another event listener of type Event.ENTER_FRAME that waits for the cookie to change value. As soon as the cookie changes values, Menu.fla automatically unloads the external swf (in our case, Arena.swf) and displays the results, accordingly to the received SharedObject. The rest of the actions happen inside the Menu.fla file, so no need for any extra coding.
Once again, thank you all for your help.