Timeline Code to Object Oriented Code, Access Instances Already On Stage
Good Morning,
As stupid as my question might sound, i have spent the last 2 weeks reading oop books; but could use some guidance.
I have a flash project that is basically a supped up slide show. On the stage i have the following:
main_mc (instance name = images_mc) = movieclip which holds "pictures"
ui1 (instance name = ui1_mc) = user interface that allows user to draw on picture (when drawing is enabled)
ui2 (instance name = ui2_mc) = activates invisible hit areas (buttons) on select pics, when hit area is clicked, we jump to another pic in the main_mc.
I accomplished all of this on the timeline, but am updating the code to OOP.
I am having A HELL OF A TIME trying开发者_如何学编程 to figure out how to store references to the instances (images_mc etc..), so i can control them from varying class files. I have found it is easy to control the instances from the documentclass, but not from unrelated class files.
Example: images_mc.stop(); works in document class; but Movieclip(Parent).images_mc.stop() doesn't seem to work from any class file.(ui2 class file for example);
Should i create a class called References, and pass the variables to other unrelated class files that way (could i see an example)? Basically what is the best practice in this situation? I don't want to add the instances to the stage via code, because everything is positioned perfectly as is. Honestly I don't foresee the need to add anything to the stage programically during this project, so having references to the already existing instances is very important. I want to accomplish this task the "right way", any help would be greatly appreciated.
Your question basically shows the difference between OOP and structural programming. Learning OOP is good decision, you will like it and it will make your life easier.
I will try not to bother you too much with the theory - I am sure you will learn that later on - but help you finish your project:
First of all, I would say it's a good practice to have a separate class for every comprehensive UI asset. That is not for every image or button but for groups of objects that serve the same purpose, for instance: slide show, log in form, controls, sound/volume buttons etc. Such class should contain only logic related to presenting the graphic and user interaction. It's part of a principle called Model-View-Controller. You can learn that later but the point is your should have separate class for the images_mc and related objects. Create it in your document class and give it the reference to document stage.
slideShow = new SlideShow(this);
and
package {
import flash.display.MovieClip;
public class SlideShow {
private var images : MovieClip;
public function SlideShow(stageRef : MovieClip) {
images = stageRef['images_mc'] as MovieClip;
}
}
}
NOTE: What I call document stage is not Stage, it's the first MovieClip.
Second principle you should follow in OOP is encapsulation. Long story short, no one should know that there is a images_mc in your SlideShow and that you can play or stop it. Instead other objects should know you can play or stop the whole slide show without knowing the details. Therefore you should have such public function in the SlideShow class:
public function stopShow() : void {
images.stop();
}
and if you want to stop the show from document class simply call
slideShow.stopShow();
NOTE: take care not to name methods like play() or stop() if your class inherits from MovieClip (if you don't want to override them but that's a different story).
Now when it comes to accessing/controlling all those classes there are several approaches:
The MVC is one of them: keep most of the references in the Controller (which can be the document class) and let it decide what to do. Let your View classes (like the SlideShow) dispatch events on the stage reference (document stage is in fact a MovieClip what means it's EventDispatcher too) and make the Controller listen to them and in turn call methods like that stopShow().
If you are not familiar with Events and this whole Controller concept is confusing to you simply put all references to all classes to one special class and pass that one to the constructor of every class you create. It's a mess but for a small project like your slideshow it should be ok.
EDIT
Event handling:
It may be too complicated for your slide show but this is how to do it in bigger projects. Let's assume you have form field and button in your Ui2 class and you want to dispatch custom event that contains the text from the form field on submit:
private var formField : TextField;
private var submitBut : SimpleButton;
and in constructor:
formField = stageRef['form_txt'] as TextField;
submitBut = stageRef['submit_but'] as SimpleButton;
submitBut.addEventListener(MouseEvent.CLICK, buttonHandler);
then you need the handler property that will dispatch the custom event that will carry the text from the form field:
private funstion buttonHandler(e : MouseEvent) : Void {
var customEvent : CustomEvent = new CustomEvent(CustomEvent.FORM_SUBMIT);
customEvent.text = formField.text;
this.dispatchEvent(customEvent); //check the note
}
NOTE: now you are dispatching it from this class so extend EventDispatcher. Eventually you may dispatch it from the stageRef (store it in constructor for use in handlers).
then in the controller / document class listen to:
ui2.addEventListener(CustomEvent.FORM_SUBMIT, doSomething);
The custom event should look like this (for simplicity it's without settter/getter):
package {
import flash.events.Event;
public class CustomEvent extends Event {
public static const FORM_SUBMIT: String = "form_submit";
public var text : String;
public function CustomEvent (type : String) {
super(type);
}
}
}
This is just a beginning, keep learning, good luck.
There are many ways to deal with this problem. One method is to use a static variable. Have a look at this example:
Static Stage Reference
That example is a little complex because it uses private vars and getters. If you don't want to play it so safe you can just do this in your doc class:
public static var display:MovieClip;
...and then in the constructor of the document class:
MyDocClass.display = this;
This means that you can now say:
MyDocClass.display.myClip
I usually call my doc classes Main. So you end up with :
Main.display.myClip
Static variables are interested if you don't already know what they are. Normal variables exist within a class instance - Lets say we have two classes, each with a property time:
var day1:Day = new Day();
day1.time = "morning";
var day2:Day = new Day();
day2.time = "night";
Simple enough on day1 the time var is "morning" and on day2 the time var is "night". These variables are unique to their instances. This is not the case with static variables - static vars exist on the class itself. Like this:
// inside the class
public static var YEAR:String = "1980";
// outside the class
Day.YEAR;
Static variables are powerful, but they can also be dangerous. They're globals and using globals can soften lead to hard to manage code.
精彩评论