When it comes to object oriented design principles, Flash and Actionscript 3.0 do things a little differently. My current project, Salvager: A Dredger's Tale, ran into an early hurdle. While trying to keep true to the object oriented design principle of encapsulation, I discovered that adding items to the stage became a bit convoluted when trying to do so from a child of the parent class where the stage was instantiated.
Most of the rendering is being done through Actionscript classes rather than animated MovieClip objects. I still use MovieClip objects as the containers for my classes, but most of them have no graphics. The reason is that MovieClips are easily linked to ActionScript classes and provide easy access from within the Flash IDE.
In the IDE, the stage is linked to its own ActionScript 3.0 file. This main class instantiates the other classes I've written. From the main class, adding a display object to the stage is as easy as using the addChild function. Trying to add an object from a child class was a bit of a challenge.
For this example, I will use my classes Star and Starfield. Star is a MovieClip that contains a 1 frame graphic of a star. The MovieClip is linked to an ActionScript file. The Star definition includes the x position of the object, the y position of the object, and an integer from 1 through 3 to notate the depth layer. Starfield is a class that was designed to manage all the Star objects on the main stage that will make up the background. There are 300 Star objects on the main stage, and using Starfield as a manager class to update all of them during gameplay keeps the main class neat and tidy.
When Starfield is instantiated, it creates 300 Star objects. Their position on the screen is set. Their brightness is determined by their depth layer. A depth layer of 1 will be closer to the camera than depth layer 3, and thus brighter. When the game camera moves during gameplay, the Star objects in depth layer 1 will also scroll faster than those in depth layer 3. The objects were originally created in the constructor method for Starfield. I then tried to add them to main stage by using this line.
parent.addChild(thisStar);
It seemed simple. Starfield is a child of the main class. In the line of code, "parent" references the main class and the addChild() method should push the object pointed to by thisStar onto the stage to display it. The compiler did not like the code.
It turns out that one of the peculiarities of Flash is that an object does not know it has a parent until the object itself has been added to the stage as a display object. Starfield is a manager class and is not a display object by itself, but it is the container for which all the Star objects are held, and those Star objects are display objects.
The workaround for this hurdle is actually quite simple. From the main class, we instantiate the Starfield class and then add that class to the stage.
This is the variable declaration in the main class.
private var gameStarField:Starfield;
And this is where we instantiate it and add it to the stage.
gameStarField = new Starfield(300);
addChild(gameStarField);
But that means we cannot create and draw the Star objects in the Starfield constructor because the constructor must finish executing before Starfield is added to the stage from the main class. To solve this problem, we need to take out all the code from the Starfield constructor and replace it with an event.
public function Starfield(numberOfStars: int)
{
//Constructor initializes the class and waits for the object to be drawn on the main stage.
this.numberOfStars = numberOfStars;
this.addEventListener(Event.ADDED_TO_STAGE, DrawStarfield);
}
The event listener waits until the Starfield object myStarfield is added to the stage in the main program. Once it has been added to the stage, the function CreateStarfield() is called from within the Starfield object. This enables us to now create the number of Star objects we need and then push them onto the main stage so that they are now displayed.
public function DrawStarfield(myEvent: Event): void
{
//The Starfield object has been added to the stage by its parent. We now create and draw
//the Star objects.
//Remove the event listener.
this.removeEventListener(Event.ADDED_TO_STAGE, DrawStarfield);
//Temporary variables to create and display the Star objects.
var thisIndex:int;
var thisStar:Star;
//Loop to iterate the creation and display of each Star object.
for (thisIndex = 0; thisIndex < numberOfStars; thisIndex++)
{
//Create a new Star object.
thisStar = new Star(Math.random() * 640,Math.random() * 480, Math.random() * 3 + 1);
//Add the Star object to the parent's stage.
parent.addChild(thisStar);
//Add the Star object to the reference array for the Starfield object.
myStarfield.push(thisStar);
}
}
Presto! We can now instantiate the Starfield object myStarfield, add it the stage, and immediately have a method executed that creates all the Star objects and pushes them to the main stage from inside a child object of the main class. Don't forget to remove the event listener once the appropriate method is called. Also don't forget to import the proper package in order to use the ADDED_TO_STAGE event.
If you would like to see the full Actionscript 3.0 code for both the Starfield and the Star classes, they are available here: Code Examples: Starfield and Star Classes.
No comments:
Post a Comment