AS3 interclass variables - actionscript-3

I have a button, that's a class, say, Button. And a main document(class Main) where I can see all the changes in a text field, refreshed every frame (yeah, I don't like trace()). The button has a function of changing a variable that's used in main file. So when I press the button, that I add in the main file to the stage, I need it's function to work. Button class has this.addEventListener(MouseEvent.CLICK,function), further function adds to the var from main class. So if it did add, I would see the changes in the text field. I see changes made by an object I add directly, in the graphic editor, but no changes from the button, whose child I add. Variables are public. Functions are all public. So...
Classes cannot exchange variables freely?
How do I change a variable via a function in a different class?
Maybe I need to export and import var? I thought they all work as a united program that shares all public variables.
Main: I create var i, add Button child to stage and show i every frame =D
Button: When you press me, I add 1 to i =D
SherWood: Main, Y U don't show i, changed by Button? T_T
Code example:
http://piratepad.net/g5tTMFX4Bo

The Button (or any other class) has no built-in knowledge of the environment that is using it's instance.
The DisplayObject ancestors have the ability to check the parent container, and "main" container via parent and stage properties.
The programmers role (you) is to code flexible way to exchange information that any 2 (or more) classes needs to have, e.g. by exposing public methods/properties, dispatching events (that other party can listen) etc.
So, if the Main needs to know that Button (instance of Button) was clicked add listener to that button for click event, and then you will be able to do whatever you want e.g. add one to i
If Button then, for instance needs to present up-to-date value Main via exposed method can do that e.g. myButton.setLabel("Value of i="+i); which may be executed in aforementioned click listener,
regards

Related

How to make visible infinite movieclips with one button?

I'm working on an interactive map in Actionscript-3 (Adobe Flash CS6).
What I'm trying to do is, with a single button, to show multiple objects (movieclips) with each mouse click.
I'm currently working with this code, but I can't manage to find out how to show multiple movieclips, I can only show ONE:
btn_ally_unit.addEventListener(MouseEvent.CLICK, mostrar_ally_unit2);
function mostrar_ally_unit2(event:MouseEvent):void
{
map_editor.ally_unit.visible = true;
}
How do I extend this to apply to any number of movieclips?
I'm sure by infinite you mean indefinite.
Target the unit clicked by using the target property of the Event class. Looks something like this:
btn_ally_unit.addEventListener(MouseEvent.CLICK, mostrar_ally_unit2);
function mostrar_ally_unit2(event:MouseEvent):void
{
event.target.visible = true;
}
You see? (event:MouseEvent) is saying that this function expects one argument (a MouseEvent) which you are giving the variable name of event. That's a convention but I like to use me as an abbreviation for mouse event. Others just use the letter e. Ok. Now event has a property, target, which is the thing receiving the event. In this case it will be one of your units. Your units have a property of visible which you can toggle off like you have been doing but by using the relative mouse event target, you can use the same line of code for all units.
note
Of course you must add the event listener to each unit. You could make it part of the class or just add it when a new unit is instantiated.
note
Using the event flow in actionscript 3 can be tricky. Seek out a tutorial on this. Here is one link related to event flow from Adobe.

activating a function of a parent as3

I'm attempting to set up a saving and loading system for a flash game I am creating. At the moment I decided to attempt to get the Save File Selection part of my new game menu to work before I proceeded any further with it. I drew up the 'DifficultySelect' screen (which contains save file selection as well as a few other things) in flash, then converted it into a symbol. I made 10 save file symbols inside of this, and created base actionscript files for them. The entire 'DifficultySelect' becomes a child of my 'Main.as' once you proceed through the title screen. I am trying to have my save file data inside of my Main.as, such as levels, health, progress, etc, as well as which save file is currently in use. However, I am unable to create a way for my Main.as to access a MouseClick function for the save file, as I can't simply have a Savefile0.MouseEvent.CLICK event in my Main.as file, as I am not creating a variable to add it to the stage.
I suppose the tl;dr question version of my situation is: How can I get my Main.as to activate one of its functions when SaveFile0 has been clicked? Also, how do I refer to a child from a parent class?
You ask how to refer to a child from parent, but since the child usually "knows" its parent, I suggest following solution:
Your child (SaveFile) should listen for the event (MouseEvent). Once the event is dispatched, you have two options. Either you can dispatch a custom event on parent or directly invoke a public function of the parent.
This is assuming your SaveFile is a MovieClip added to Main:
Inside SaveFile:
var _parentMC:MovieClip = this.parent as MovieClip;
_parentMC.functionToCall();
The best practice, however is to dispatch a custom event in SaveFile, and listen for it in main:
Inside SaveFile:
var customEvent:Event = new Event("customEvent");
this.dispatchEvent(customEvent);
Inside Main:
saveFile.addEventListener("customEvent",functionToCall();
functionToCall(e:Event):void{
}

Issue with Document Class and Tutorial

So I've been following this tutorial on AS3 and Flash. Its been going well until, note I have tried to contact the writer of the tutorial and had no reply. Here's what it tells me to do;
Right-click PlayScreen in the library, select Properties, and check Export for ActionScript. This time, instead of accepting the default value, enter the name of your document class. Click OK.
So it pops up an error, first we’ll have to make a new document class, since no two different objects can share the same class. Cancel the Properties box.
Hit File > New and select ActionScript File. Enter the (by now familiar) code.
Save this in the Classes directory as DocumentClass.as. (There’ll be no confusing the purpose of this file!) Now, back in your FLA, change the document class to DocumentClass.
Check everything’s fine by clicking that pencil icon — if it’s all OK, that should bring up the AS file that you just created.
// So this bits all fine, its the next that i'm stuck with:
Now you can set the PlayScreen‘s class to AvoiderGame. So do so!
// So I go ahead into the properties and change the name but then it pops up with the same error as before: 'Please enter a unique class name that is not associated with other library symbols'
What does this mean!? How do I resolve this!?
Full tutorial here:Flash Tutorial
Its hard to tell what you are trying to accomplish without knowing what all the parts you are referring to actually do, which are objects in the library and which are classes, but maybe this can help:
First of all, document class in AS3 typically refers to the project's main set of code that initializes the app. This class can be called anything but is often called Main, and is entered in the property panel that is displayed when you click the projects main stage in the field called class.
Now, when linking a class to an object in the library, its a little different. In the library object's property panel, tick the box for Export for Actionscript, and put a unique name in the top box. This is what you reference in your code to call it, like new somethingOrOther() or using the pic below as an exaample, new Ball(). The second box is the base class, pathed to where it lives in your code base. This is the class you will write that actually controls the object you've linked the class to. Giving a linked object a base class and a unique identifier allows you to use the same base class for multiple linked objects.
Note that when you do this approach, Flash will warn you that there is no class associated with Ball and one will be created for you. Don't worry, this is normal behavior. If you set this up properly, your object will still be controlled by its base class.

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

use class to handle mutiple nested movieclips and their specific events

I have a menu with five buttons. Menu is visible all the time. there is click event for each menu item. which slides corresponding movie clip from left to right. each movie clip has different nature events and respective animation and activity. for example tab 1 brings the video page. and within that movie clip I have video events like play pause volume and on complete etc. events and code. tab 2 has button group for Time and another button group Features. depending on user selection code will calculate and show value on a animated counter. tab 3 has button group for Time and button group Source. as per the user selection it will calculate and show the values as animated graph. and so on.
Right now I have all the individual tab movie clip has its own time line code for its own events. and some crossover variables and references with other tabs. Everything is working as expected. No problem. I know time line code is not the best way to do any complex project.
So, I would like to get the entire coding as one class or more classes if that is the correct way.
I am beginner as far as class logic. I have already created Main as document class and could control the general navigation of tabs and their initial look. But stuck at tab specific button events and other such unique events for the specific tab.
Any help is greatly appreciated. Thanks in advance.
any similar example or suggestions.
First of all, thanks a lot for a prompt response. It seems like I am not even a beginner. I need to read a lot and probalbly grasp all fundamental concepts thoroughly. I have gone through both the links suggested in your comments. I am trying to digest the stuff slowly. I do not have any formal informal education regarding OOP or any sort of programming. To be honest, I have hard time understanding the code you have suggeted. Not because of your code but because of my level of caliber. I will have to spend some time to make myself clearer regarding events and sequence etc. different tab contents are as movieclips to main timeline and already placed on stage. It comes and goes to its corresponding tab button click event. I am not marking your answer as yes because I still need to my own homework based on your suggestion. Thanks a lot once again. I am sure I will ask few more questions later.
This is how I would design it:
I'd have a Menu Class, which only contains the buttons and "converts" clicks on them into more specific events. That might look something like this:
public Class Menu extends Sprite {
protected var buttons:Vector. = new Vector.();
public function Menu() {
super();
var loops:int = numChildren;
for (var i:int=0; i<loops; i++) {
var button:SimpleButton = getChildAt(i) as SimpleButton;
if (button) {
buttons[buttons.length] = button;
button.addEventListener(MouseEvent.CLICK, broadcastMenuEvent);
}
}
}
public function broadcastMenuEvent(e:Event):void {
var button:DisplayObject = e.currentTarget as DisplayObject;
dispatchEvent(new Event(button.name, true));//bubbling, can catch at any level
}
}
The way this is built, you can change the events that are being dispatched simply by changing the name you give the instance of the button on stage. Note that you need to apply Menu as the Base Class and not the Class for this to work if you have "declare instances automatically" unchecked, because doing it that way allows the compiler to generate those instance names for you in a way your base Class doesn't have to know about.
At this point, you can then deal with those events in another place--whether it's your main document Class or whether you have a separate Controller.
I would define each of the Views you described as a separate Class as well. If you have objects coming and going on the stage, you can use one of the techniques described here to handle that. Otherwise, it's fairly straightforward to address your timeline instances from the base Class instead of timeline code. Again, you can listen for those events in the main document Class or a dedicated Controller--the main point is to make sure your Views are not making any important decisions and usually they should not be editing data.
You can choose to have your Main Document orchestrate how the tabs get added and removed (I'm a big fan of using the timeline with goToAndStop, but not everyone shares this preference), or, again, you can separate this logic out to a dedicated Controller. I would suggest that if it's possible to generalize how your Views work to have them implement a single Interface. That way, you can give them a single instance name and manage them all with the same getter/setter pair (assuming you go the timeline route).
Note the Flash compiler isn't terribly sophisticated in this regard, so if you do this and your Views extend different parent Classes, you'll get compiler warnings. Just ignore these--they don't mean anything.
The thing you shoud try to root out of your code completely is the part where Views are referencing each other. The only time it's acceptable for one View to know about another is when it's a parent knowing about its child. Even then, try to have as little specific knowledge as possible. Notice in the Menu View I wrote as an example, the parent only knows there may be some SimpleButtons, but it has no specific knowledge of where they are on stage, what, specifically, is in them, or even what there instance names are.
Instead of having your Views know about one another, have a third party (which, again, you can choose to use the main Document Class for or not) that transfers requests for state changes (in the form of events) from one to another.