AS3 - Anonymous function 'this' - actionscript-3

I have played around with some Anonymous functions, and I noticed that this code does not trace the same thing twice:
public function Main()
{
trace(this);
stage.addEventListener(MouseEvent.CLICK, function(e:Event):void
{
trace(this);
});
}
The first trace traces "[object Main]" and the second one traces "[object Global]" (after I clicked). Why does that happen? And what is object Global, is it useful for something?

In this case, the keyword this represents the global object, some alternate universe where your function was created, because it was defined outside any custom class or object.
Main class
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
public function Main()
{
// trace(this);
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void
{
trace(this);
});
}
}
}
output
[object global]
In the following example, the function listener toClick is defined as method of the Main class, so this refers to the object Main.
Correct code
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
public function Main()
{
// trace(this);
stage.addEventListener(MouseEvent.CLICK, toClick);
}
private function toClick(e:MouseEvent):void
{
trace(this);
}
}
}
Output
[object Main]

An anonymous function allows you to create variations to behavior, without having to create a subclass, or some complicate switch statements, so you can now simply assign a function to perform a certain task at runtime. Is like any variable - only this special kind of variable doesn't have a value, but a behavior.
//clasic
bar = function(arg1, arg2, etc) {
// do something here
}
when you trace(this) you refere to what function returns and that's a special global 'bar' variable.
The standard example for this is event listeners, but you can also apply this to any other functionality you desire.
You can find out about anonymous functions here : http://blogs.adobe.com/simplicity/2007/10/post.html.

Related

1151: A conflict exists with definition mcPlayer in namespace internal

Every time I try to run my ActionScript 3 program, I get this error:
1151: A conflict exists with definition mcPlayer in namespace internal.
Here is my script:
package
{
import flash.display.MovieClip;
public class Knight extends MovieClip
{
var mcPlayer:MovieClip;
public function Knight()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown)
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp)
}
private function keyUp(e:KeyboardEvent):void
{
trace(e.keyCode)
}
private function keyDown(e:KeyboardEvent):void
{
}
}
}
How can I fix it?
If I understand things correct, your Library contains some object with class Knight and inside this object there's a child MovieClip of instance name mcPlayer. The thing is, all designed elements go to namespace public, while all the class fields/methods with no explicitly stated namespaces go to internal.
Always declare designed elements as public:
public var mcPlayer:MovieClip;

Acces of undefined property cerc

I have this code in AS3:
package clase
{
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author cry
*/
public class CercNegru extends MovieClip
{
var growthRate:Number = 2;
cerc.addEventListener(Event.ENTER_FRAME,grow);
public function CercNegru()
{
}
private function grow(e:Event):void
{
trace("asdda");
}
}
}
When you run this program receive error:
Line 12 1120: Access of undefined property cerc.
Line 12 1120: Access of undefined property grow.
I put an image to understand better :
Can you help me to solve this problem please?
Thanks in advance!
The errors are because in class files, all functional code needs to live inside a function.
So take this line, which is just floating in the class:
cerc.addEventListener(Event.ENTER_FRAME,grow);
And move into the constructor (assuming you want it to run right away when you instantiate the class):
public function CercNegru()
{
cerc.addEventListener(Event.ENTER_FRAME,grow);
}
In class files, the constructor (which is the function whose name exactly matches the class name), is what get's called you use the new keyword.
So doing new CercNegru() will call that function.
NOW, I'm also assuming that this class file is attached to FlashPro library object, and you have something on the timeline with an instance name of cerc. (if that is not the case, then that is the reason for your error)
Timeline stuff though, isn't always available in the constructor, so you may need to wait until the instance has been added to the screen.
public var cerc:MovieClip; //you may want to create a reference to the timeline item, so you get compile time checking
public function CercNegru()
{
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//this is the equivalent of timeline code now
cerc.addEventListener(Event.ENTER_FRAME,grow);
}
package clase
{
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author cry
*/
public class CercNegru extends MovieClip
{
var growthRate:Number = 2;
var cerc:DisplayObject; // ADD THIS
public function CercNegru()
{
cerc.addEventListener(Event.ENTER_FRAME,grow);
}
private function grow(e:Event):void
{
trace("asdda");
}
}
}
As the error says cerc is undefined. So you should define it. Assuming that your 'cerc' is a Sprite,
var cerc:Sprite;

ActionScript 3 - Stage object is null for first operation

I have basically been trying to create a chess game, and it has some basic functionality. I have encountered some runtime errors that I can't seem to fix. I've tried searching around for solutions, and I have found several, but none of them seem to work for me.
I then created a new flash project to see if the error still occurs, just to make sure that it's not another part of my program that is causing the issue.
The stage has a pentagon object (a MovieClip) on it, which has an instance name of PentaGray and a class of Gray. There is an intermediary class called PentaClass.
The Main (document) class:
import flash.display.MovieClip;
import PentaClass;
import Gray;
public class Main extends MovieClip
{
// public var Natsu:String;
public function Main()
{
FairyTail();
}
public function FairyTail()
{
trace("PentaGray = " + PentaGray);
trace("PentaGray's name is " + PentaGray.name);
PentaGray.TraceThis();
}
}
PentaClass class:
public class PentaClass extends Main
{
public function PentaClass()
{
}
public function TraceThis():void
{
trace("Fairy Tail :D");
}
}
Gray class:
public class Gray extends PentaClass
{
public function Gray()
{
// TraceThis();
}
}
Running the program like this causes this to be printed to the output window:
PentaGray = null
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Main/FairyTail()
at Main()
at PentaClass()
at Gray()
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at Main()
PentaGray = null
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Main/FairyTail()
at Main()
If I change the code in the Main class to:
if (PentaGray)
{
trace("PentaGray's name is " + PentaGray.name);
PentaGray.TraceThis();
}
Then this is output:
PentaGray = null
PentaGray = [object Gray]
PentaGray's name is PentaGray
Fairy Tail :D
Also, if I run the function from Gray by uncommenting the statement in its constructor, it works properly, but for my game, I need to run a subclass function from the document class.
What I would like to to know is, why is PentaGray null when the program starts? I thought that the objects that are placed on the stage using the IDE are initialised before any written code runs, but this doesn't seem to be the case.
I've tried using event listeners (ENTER_FRAME and a Timer) but they still didn't solve the issue.
How can I change the program so that the object isn't null when certain code, e.g. the FairyTail() function, is executed? Have I not written my code properly or is this an issue with Flash/ActionScript itself?
By putting the call to FairyTail() in the Main class in the Main function, you have put that in the 'constructor' for the main object. The constructor of the Main object is the very first thing that has to run, because nothing can be created until the main object is created. And when the main object is created, the constructor is called first.
If you want something to run right when PentaGray is created, put it in the constructor of PentaClass:
public class PentaClass extends Main
{
public function PentaClass()
{
Main.FairyTail();
}
}
Or, if you just want it to happen at the start, you can just put it after the class declaration in the main file.
#main document
import flash.display.MovieClip;
import PentaClass;
import Gray;
public class Main extends MovieClip {
//...
}
Main.FairyTail();
By the way, it doesn't make sense to me that the PentaClass extends the Main class. Why don't you just make another class for it to extend?
Off course, your stage is not ready. Use the bootstrap done below in your main class.
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
FairyTail();
}
Cheers

ActionScript - Keyboard Events Without Stage?

is it true that keyboard events can not be accessed outside of the stage on non display objects?
example:
package
{
//Imports
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
//Class
public class TestClass extends EventDispatcher
{
//Constructor
public function TestClass()
{
init();
}
//Initialization
public function init():void
{
addEventListener(KeyboardEvent.KEY_UP, keyUpEventHandler);
}
//Key Up Event Handler
private function keyUpEventHandler(evt:KeyboardEvent):void
{
trace("Test Class: " + evt.keyCode);
}
}
}
here i would like to initialize a new TestClass() then press a on the keyboard to receive the output Test Class: a.
To my knowledge (and according to the livedocs example) you need to add a KeyboardEvent listener to a displayObject. I've done this in abstract and static classes by passing a reference to the stage (or any displayObject) to your class's init method or constructor.
So, for example, in your document class, you could do:
var testClass:TestClass = new TestClass();
testClass.init(stage);
and in TestClass.as do:
public function init(stageReference:DisplayObject):void
{
stageReference.addEventListener(KeyboardEvent.KEY_UP, keyUpEventHandler);
}
While I agree it's a little wonky, I don't think there's a way to do it without using a DisplayObject.

Accessing main class stage event listener

I wanted to remove an event listener from main class stage, but i get the error 1120: Access of undefined property stage. How do I actually access the stage?
custom class:
import main;
main.disableVcam();
main class:
public static function disableVcam():void {
trace("disable");
stage.removeEventListener(MouseEvent.MOUSE_MOVE, movevC);
}
Unless the object is on the display stage, the stage object will be undefined (or null). You have to addChild the object for the stage object to have a value.
Edit: Perhaps you can handle this in the event handler?
protected function clickHandler(e :Event) :void {
if (e.target.stage) {
e.target.stage.removeEventListener(...);
}
}
Edit2: Static methods don't have a stage, so to solve your problem you can make your Main-class a singleton, and work like this:
public class Main {
static private var instance :Main;
static public function getInstance() :Main {
if (Main.instance == undefined) {
Main.instance = new Main();
}
return Main.instance;
}
// The rest of the class goes here
}
// snip
import Main;
public static function disableVcam():void {
trace("disable");
Main.getInstance().stage.removeEventListener(MouseEvent.MOUSE_MOVE, movevC);
}
If your Main-class is the main class of the project, you need to assign the static instance variable's value in the constructor.