Referring to objects with the same parent via as3 class file - actionscript-3

recently I got many (about 70) #1119 and #1120 errors in Flash. I've searched the web, but none of the solutions has solved my problem. Attempting to find the cause of the error myself, I made a new Flash animation. The contents:
A movieClip called "nr1" without instance name.
Inside of nr1 there are two movieClips, "nr2" with the instance name "ob2" and "nr3" with the instance name "ob3". Associated with nr2 is the as3 class file "nr2.as3". Here is the code inside nr2.as3:
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class nr2 extends MovieClip {
public function nr2() {
// constructor code
this.addEventListener(MouseEvent.CLICK,func1);
}
function func1(e:MouseEvent){
parent.ob3.x += 50;
}
}
}
This should refer to the object with the instance name "ob3", which has the same parent as this (nr2). Still, I get two identical #1119 errors at line 15 (parent.ob3.x += 50;). How do I refer to an object with the same parent via an as3 class file?

It isn't a good idea to set ob3's property in nr2. You could dispatch an event in nr2, and add eventListener in parent, so the parent could catch the event and do something with bo3.
If you really want to set ob3's property in nr2, try this
function func1(e:MouseEvent) {
var ob3:MovieClip = parent['ob3'] as MovieClip;
if (ob3)
{
ob3.x += 50;
}
}

Agree with Pan, it's not a good idea to control a child from another child. Let the parent (nr1) who has references to both child do the control. So you should create nr1 class
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class nr1 extends MovieClip {
public function nr1() {
// constructor code
ob2.addEventListener(MouseEvent.CLICK,func1);
}
function func1(e:MouseEvent){
ob3.x += 50;
}
}
}

Related

Actionscript 3 passing variable from parent to child

I am still having problems so I made a very basic main.swf that loads sub.swf.
Sub.swf has 2 rectangle movieclips (red and blue) that have their alpha = 0.
Both swfs compile fine and no errors but the red alpha does not get turned on so the value of "spanish" from main.swf variable must not be getting recognised in sub.swf. Any ideas?
Main.swf actionscript:
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
var child_loader:Loader = new Loader();
var req:URLRequest = new URLRequest("sub.swf");
child_loader.load(req);
child_loader.contentLoaderInfo.addEventListener(Ev ent.COMPLETE, done);
function done(e:Event):void{
addChild(child_loader);
MovieClip(child_loader.content).language = "spanish";
}
sub.swf actionscript:
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
function callFunction(_txt:String):void{
var sublanguage = (MovieClip(parent.parent).language)
if (sublanguage == "spanish"){
red.alpha = 1;
}else if (sublanguage == "english"){
blue.alpha = 1;
}
}
The problem is that AS3 is not dynamic in the way AS2 was, so the child document needs to have a property or method that the parent knows is there.
One way to do this is relatively simple:
package {
public class ChildClass extends MovieClip {
protected var _property:String;
public function get property():String {
return _property;
}
public function set property(value:String):void {
if (value != _property) {
_property = value;
//do something, because now the property has been set
}
}
}
}
You'd just apply that as the Document Class to the swf you're loading, and then in your onLoaded function, you'd do something like:
//cast to ChildClass, so you will know you have the property available
var childClass:ChildClass = Loader(event.currentTarget).contentLoaderInfo.content as ChildClass;
//if the variable content is null, the swf had a different Document Class
if (childClass) {
//now you can set your variable, you're good
childClass.property = 'foo';
}
Like most things in Actionscript, you can do it the easy way (shown above), or you can do it the right way. The right way is to use an Interface. What an Interface is is the "blueprint" for a Class. In this case, it would need to say that any Class that implements that Interface would always have a property getter and a property setter. You can't just use a variable, because Interfaces only allow functions.
But at any rate, the advantage of using the Interface, especially in your case, is that you will not have to compile in the specific Class associated with the swf that you're loading. Instead, you'd just need to compile in the "contract" for the Class, which is much lighter weight. But because the player won't cast the contentLoaderInfo.content to ISomeInterface unless it fulfills that contract, you can confidently set that property once you have done the casting.
You should be able to set up a function in your child movie that can be called from your parent. You could pass anything you want as an argument.

Adding to Stage in ActionScript 3 from a .as file

Note: Yes, I know that similar questions have been asked before. However, after following the answers in such questions I'm still stuck and can't find a solution to my problem.
I'm having a problem which requires adding DisplayObjects to the Flash stage. Since I have to Display elements of several different classes, I decided to create a class to work as an intermediary between the .as files and the addChild function called "Displayer" as shown below:
package
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.Stage;
public class Displayer extends Sprite //I read somewhere that DisplayObject
//as an extension can't be used for this, so Sprite will have to do.
{
private var _stage:Stage;
function Displayer()
{
_stage = new Stage;
}
public function displayElement(displayable:DisplayObject)
{
_stage.addChild(displayable);
}
}
}
I compile it and there appears a problem that I don't understand: Error #2012: Can't instantiate Stage class. Evidently, something in this code is either missing or out of place, but since it's so straightforward I fail to see what the problem can be. I'm sure that it's not very complicated, I probably just need an outsider's perspective.
The Stage object is not globally accessible. You need to access it through the stage property of a DisplayObject instance.
refer a following docs.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Stage.html
package
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.Stage;
public class Displayer extends Sprite
{
var isAddedToStage:Boolean;
public function Displayer()
{
if(stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
isAddedToStage = true;
}
public function displayElement(displayable:DisplayObject):void
{
if(isAddedToStage)
this.stage.addChild(displayable);
}
}
}
You don't instantiate the Stage class, as the error says. Just like you cannot instantiate the DisplayObject class (which is why you have to extend Sprite).
Basically, you have two options here:
1) You add the child from a DisplayObjectContainer instance.
var displayerInstance:Displayer = new Displayer();
this.addChild( displayerInstance );
You would run this from a DisplayObjectContainer object that has already been added to the global stage. There is only a single stage in every project, even if you embed SWFs, the stage property of the SWF is actually the stage property of the top level application. So if you have this Displayer instance nested inside a class which is nested inside another class that is created in your main application, you would have to run "addChild" in each of those classes to get the Displayer to show.
2) You cheat. This is not recommended, at all. Basically, you pass in the stage object of an object when you instantiate the Displayer class.
var displayerInstance:Displayer = new Displayer( this.stage );
public function Displayer( stage:Stage ) {
this.stage = stage;
if ( this.stage ) {
this.stage.addChild( this );
}
}
This is a method that is good for adding Singletons to the stage (except there is not constructor for a Singleton). I created a profiler just before Christmas that was a Singleton (And later found Scout, damnit) that used this method for adding things to the stage when appropriate.
Again, that second option is not recommended for this situation, but it is a possibility.
As an aside, you should never add things directly to Stage, unless there is a clear reason for doing so (such as a popup). You should follow the display list methodology, where a DisplayObjectContainer adds another DisplayObject or DisplayObject container as a child and so on and so forth so that they are all connected to the TopLevelApplication.
Ok, I think instantiating a stage class won't do because as the as3 documentation says: "The Stage object is not globally accessible. You need to access it through the stage property of a DisplayObject instance."
You should instead pass a reference to the Stage object to your Displayer class and you can get a reference to the stage object, as the docs say, via a display object instance.
So the constructor might now look like:
function Displayer( stage:Stage )
{
_stage = stage;
}
Assuming that the object which instantiates your Displayer is a child of the stage you can instantiate the Displayer by
displayer = new Displayer( stage );
If you use this approach there is no need for the Displayer class to extend anything or be added to the stage ( which is required btw in the approach of bitmapdata.com ).
There is always a simple solutions.if you need to add a child element into a stage from your class you can just pass the stage into your class as a object and add the child element into it, i did this for adding an image into my stage like this.
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.display.Bitmap;
public class ImageLoader extends Sprite{
private var stageObj:Object; //create local variable to refarance stage
public function loadeimage(StageObject:Object, Url:String){ //StageObject will bring the stage refarance into the class
var reQuest:URLRequest = new URLRequest(Url);
loader.load(reQuest);
stageObj=StageObject; //make local refarance for stage inside the class
var image:Bitmap;
image=Bitmap(loader.content);
image.x = 100;
image.y = 100;
stageObj.addChild(image); // add whatever object into stage refarance and this means the real stage..
}
}
}
only the things with comments are important and you can save this file as ImageLoader.as and import it and use it like this.
import ImageLoader;
var IL:ImageLoader = new ImageLoader();
IL.loadeimage(this,"img.jpg");
its simple as that. i think this is what you have search for... good luck. (you can pass any container or parant container this or this.stage it doesn't matter your child will be a part of it.

AS3 - How to use child classes, how to create an instance of a child class?

Very new to the forum, and AS3, but help would be much appreciated.
Not sure if i'm using all the right terms, but how do you create an instance of a child class?
This is what I have so far:
I have a 'mob_troll' movieclip with Class: troll and Base Class: [blank]
Main.as:
import mob
var troll:mob = new troll();
troll.Speed = 10
troll.Hp =10
troll.as:
package {
import mob
public class troll extends mob {
public function troll(){
trace('I work')
}
}
}
mob.as:
package {
import flash.display.MovieClip;
public class mob extends MovieClip {
public var Speed:int;
public var Hp:int;
public function mob() {
trace('mob')
}
}
}
I apologize if I'm stating the obvious but I wanted to make sure we understood each others terms.
Child classes (also known as sub classes or derived classes) are exactly what you've created with the line
public class Troll extends Mob { ... }
The class Troll is a child class of Mob.
An instance is an occurrence of the class. which you have created with this line:
var troll:Mob = new Troll();
Specifically the part new Troll() creates the Troll instance. Then it is set to a variable which references a Mob.
So in this example you have already created a child class (the troll).
If you're wondering about how to see your movieclip visually on the stage, then you should read up on the AS3 Display list here's a good starting point. But essentially it would involve adding that instance to the stage. Assuming Main.as is your document class it would look something like this:
import Mob;
import Troll;
var troll:Mob = new Troll();
troll.Speed = 10
troll.Hp =10
this.addChild(troll);
Notice the import of Troll (you will need to import every type used)

AS3: Accesing function on the maintime line from a extended movieclip class

I have some movieclips on my main timeline with a class to extend these movieclips
ClickableMovieClip.as:
package {
import flash.display.MovieClip;
import flash.events.*;
public class ClickableMovieClip extends MovieClip {
public function ClickableMovieClip():void {
this.buttonMode = true;
this.addEventListener(MouseEvent.MOUSE_UP, onReleaseHandler);
}
public function onReleaseHandler(myEvent:MouseEvent) {
//trace(" > "+this.name);
testing();
}
}
}
And on my maintime line I have this function testing();
function testing(){
trace("hello world!");
}
But the I can't 'reach' the testing function. I get this error:
"1061: Call to a possibly undefined method testing through a reference with static type flash.display:DisplayObjectContainer."
What am I doing wrong?
First of all, how are you connecting your AS3 class to the stage? Importing it in a frame or using it as the Document Class?
This may have to do with inheritance.
Second, you may need to call it using (root As MovieClip).testing() or something like that. The idea is that you need to call it as a method of the stage or root. I don't remember exactly how it works.
EDIT:
As you said MovieClip(parent).testing(); is the answer. I forgot the exact syntax before...

ActionScript 3.0 stageWidth in custom Class

How do I access Stage Class properties in Costum Class?
Class:
package {
import Main;
import flash.events.*;
import flash.display.Sprite;
import flash.display.Stage;
public class Run extends Sprite {
var obj:a1_spr;
public function Run() {
runAssets();
}
private function runAssets():void {
obj = new a1_spr()
addChild(obj);
obj.x = stage.stageWidth/2;
}
}
}
Output:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
To expand on what Joel said, and put it into context:
Every display object has a .stage property, but that property is null until you add you display object onto the display list. So during construction, you will never be able to access it, (because it gets added afterwards)
The event ADDED_TO_STAGE gets fired when you add your object to the stage, ltting you know that the .stage property is now populated. After that happens you can access the stage from anywhere in you object.
Hope that clarifies things for you.
this.addEventListener(Event.ADDED_TO_STAGE, handleAdedToStage)
private function handleAddedToStage(event:Event):void
{
this.runAssets()
}
private function runAssets():void
{
obj = new a1_spr();
addChild(obj);
obj.x = this.stage.stageWidth/2;
}
You aren't going to have access to the stage in the constructor (unless you inject the stage into the class). Sprite has a stage property.
when flash compiles the fla assets with your .as files, there's no stage. so the code is initiated as preparation for your documentclass, you have to listen to if there's a stage so it can be rendered.
that's why you listen to ADDED_TO_STAGE , to check it's actually in the display list.
This problem occurs for all display objects, since they must be added to the display list when there's an actual stage.
get used to add that listener, and check for a stage. specially when working in a team and your doing your own components in a larger project.