How to save data in previous frame in Flash - actionscript-3

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.

Related

Hidden objects on one frame need to stay hidden when returning to the frame

I have created point and click games in AS2 but now developing in AS3. When you click an object to add to your inventory the object is .visible=false; Then when you leave a room (frame) and return the object would still remain .visible=false;
I achieved this in AS2 using the following:
(set up of a movieclip instance MCTake)
var MCTakeVisible;
MCTake._visible=MCTakeVisible;
(when I click the movieclip)
MCTake._visible=false;
MCTakeVisible=false;
MCTake._visible=MCTakeVisible;
Now the object is gone no matter how many times I return back to the frame. My question is what is the AS3 equivalent to this behavior.
Also vise-versa. If an object is hidden at first and made to appear like an open door that stays open. I used the following for that in AS2:
if(MCTakeVisible == undefined) MCTakeVisible = false;
Thank you in advance.

AS3: How to jump to another scene (or frame sequence) and return back to frame having jumped from

Right now I'm building a simulation of a sports match, played in 2 linear halves, divided in 2 separate scenes. Goals that have been scored in-match appear as a button on the stage as scoring occurs. The button works as a reference to replay the goal. Goals scored in let's say the first half (scene 1) should be accessible to replay whilst in the second half (scene 2).
I've created extra scenes per goal that serve as individual replays to refer to.
What I would like to have the user be able to, is to click that replay button at any chosen time, view the replay, and then return to the exact frame it originally jumped from, and play on from there when preferred.
The reason why I 'cannot' use movieClips and addChild methods, is that I want the final SWF to keep its transparent background, as I will embed it in html later on.
If (and how?) I use the addChild method, you see 2 partially transparent movieClips on top of each other, running at the same time.
If I'd find out how to replace the one with the other, this could be suited method.
Another would be using currentFrame and/or currentLabel methods I guess but I wouldn't know how to.
I have the project .fla file to give you a clearer insight on things.
Let's assume you have a replay button with the instance name of replayBtn. Here is one way to set this up:
On the first frame of your timeline, create the following vars and functions:
//define a variable to hold the last replay frame
var lastReplayFrame:int = 0;
//define a variable to hold the frame to go back to once a replay is done
var replayReturnFrame:int = 0;
//create a function to call after a replay is done
function replayReturn(){
//if we've set a frame to jump back to
if(replayReturnFrame > 0){
//go there and resume playing
this.gotoAndPlay(replayReturnFrame);
//reset the return frame so we don't go back there the next time if the button isn't hit
replayReturnFrame = 0;
}
}
//create the click handler for the replay button:
function replayClick(e:Event):void {
//check if there is a replay available
if(lastReplayFrame > 0){
//store the current frame before jumping back
replayReturnFrame = this.currentFrame;
gotoAndPlay(lastReplayFrame);
}
}
//add the click event listener to the replay button instance
replayBtn.addEventListener(MouseEvent.CLICK, replayClick);
Now, in your timeline, whenever a goal starts (eg the first frame of where a replay should start), put the following code on a keyframe:
lastReplayFrame = this.currentFrame;
Then, on the last frame of a replay, put this code on a keyframe:
replayReturn();

Replacing movieclip

I m currently working on converting one of my as2 game project into as3 (flash pro cs4). But there is a problem on the background movieclip.
I have a function called disposemc:
function disposemc(mcname:MovieClip):void{
mcname.parent.removeChild(mcname);
mcname = null
}
Another function called changelayer:
function changelayer(mcname:MovieClip,layer:MovieClip):void{
layer.addChild(mcname)
}
So in main timeline frame 2 I have a movieclip on stage (placed in IDE) with instance name "bg_mc", then on main timeline frame 3 I have a DIFFERENT mc on stage with the SAME instance name "bg_mc". The purpose of this is to replace the old bg_mc by the new one.
The problem is,
In frame 2, I applied changelayer function to bg_mc and moved it into a child mc of root by addChild, and then applied a function of my CPU image post processing framework and added the bg_mc into an array.
After some stuffs happened, I went nextFrame to frame 3, and found that the new bg_mc didnot replace the old one, instead it overlaps.
So I tried disposemc function when leaving frame 2 to get rid of the old bg_mc, and at frame 3 I applied changelayer to bg_mc and added bg_mc to my render array.
And I found that the old bg_mc is off the stage but it is still rendering onto my bitmap data, means it is not nullified like it suppose to be in disposemc function. And it is also hard to access it because the name overlaps. When I call bg_mc in frame 3 it is the new one, but the old one still exists, and from the rendered bitmap data it can see it is still playing.
Will making the old mc stop in disposemc function help?
Can anyone give any help? If my structure of making bg is bad, is there any other way to override an instance with a different mc in library?
The purpose of this is to replace the old bg_mc by the new one
You work with MovieClip and frames. So use keyframes by design. If you need to place different background in third frame, don't program it, place it. If you want program, don't use MovieClip with keyframes as main navigation instrument.
Main timeline could be easily swapped with very simple logic and several movie clips with only one frame
//Some MovieClips from the library, with only one frame, still designed in Flash IDE
var currentScene:DisplayObject;
var home: MyHove = new MyHove()
var intro:MyIntro = new MyIntro();
navigate(home);
//after some interaction from the user, go to another page
navigate(intro);
//It will work like gotoAndStop... but better, and give you more control
function navigate(scene: DisplayObject):void{
if(currentScene != null){
removeChild(currentScene);
}
currentScene = scene;
if(currentScene != null){
addChild(currentScene);
//apply logic for swapping background
}
}

Have images change using Flash AS3

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.

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.