Go Back   kirupaForum > Flash > ActionScript 3

Reply
 
Thread Tools Display Modes
Old 08-24-2006, 04:51 PM   #181
icio
looks better in lowercase
 
icio's Avatar
Location Edinburgh, Scotland

Posts 3,794
I tried this code:
Code:
package {
	import flash.display.Sprite;
	public class stage_test extends Sprite {
		public function stage_test() {
			var myClass:MyClass =  new MyClass();
		}
	}
}

import flash.display.Stage;
import flash.display.Sprite;
	
class MyClass {
	public var stage:Stage = (new Sprite()).stage;
	public function MyClass():void {
		trace(stage);
	}
}
But it didn't work. It would appear that the `stage` property of a Sprite isn't set when the Sprite is created. Where does the value of the `stage` property come from, then ?

Thanks
icio is offline   Reply With Quote
Old 08-24-2006, 05:15 PM   #182
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Quote:
Originally Posted by icio
I tried this code:
...

But it didn't work. It would appear that the `stage` property of a Sprite isn't set when the Sprite is created. Where does the value of the `stage` property come from, then ?

Thanks
display objects only have access to the stage when they are within a visible display list (or, rather, a display list attached to the stage). To be able to have a valid reference to the stage from a sprite, you'd have to use addChild to add it to a container - either the stage itself or some other container attached to it.

A suggestion I've used before was have your application or document class extend a custom subclass of sprite rather than sprite itself. This class could then have that static stage reference which would instantly available since the application/document class is inherently a child of the stage when the SWF starts.

On a similar topic, I have a class allowing you to detect when the stage property is available for a display object (i.e. when it has been added to a visible display list) but I was saving that for another tip of the day. If anyone is interested, I can post that one next.

__________________
senocular is offline   Reply With Quote
Old 08-24-2006, 07:03 PM   #183
Enemу
Registered User
Hi, Sen and everyone

I have a tip request: Singleton in AS3

private
is no longer available as constructor's attribute, it makes me just unhappy

I've found two workarounds for this, here about singletons in general and here
more concrete.

But, there are a lot of discussions and comments about what way is more hackish or useful. I'm confused.

The question: Singleton in AS3: best practice, the most common and easy to use (and understand) way, if any...

Thanks!
Enemу is offline   Reply With Quote
Old 08-24-2006, 07:42 PM   #184
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Quote:
Originally Posted by Enemу
Hi, Sen and everyone

I have a tip request: Singleton in AS3

private
is no longer available as constructor's attribute, it makes me just unhappy

I've found two workarounds for this, here about singletons in general and here
more concrete.

But, there are a lot of discussions and comments about what way is more hackish or useful. I'm confused.

The question: Singleton in AS3: best practice, the most common and easy to use (and understand) way, if any...

Thanks!
gskinners post is your best approach (private variable usage prefered over helper class).

__________________
senocular is offline   Reply With Quote
Old 08-25-2006, 07:41 AM   #185
Enemу
Registered User
Quote:
Originally Posted by senocular
gskinners post is your best approach (private variable usage prefered over helper class).
You mean throwing an error if allowInstantiation == false ?

But what about compile time errors?
Enemу is offline   Reply With Quote
Old 08-27-2006, 11:37 AM   #186
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
TextField.appendText()

The TextField class (flash.text.TextField) in ActionScript 3 has a new method called appendText (flash.text.TextField.appendText()). This method allows you to add additional text onto the end of the text contained within the current text field. This should be used in place of TextField.text += newText since appendText is faster and more efficient.
Code:
var my_tf = new TextField();
my_tf.text = "Hello";
my_tf.appendText(" world!");  // my_tf.text == "Hello world!"

__________________
senocular is offline   Reply With Quote
Old 08-28-2006, 09:14 PM   #187
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
include Directive

ActionScript 3 continues to allow you to include code located in external files within your scripts at compile time using the include directive (include directive).
Code:
include "scripts/myscript.as"
Notice that the include directive in ActionScript 3 does not contain a # before "include" as it did in ActionScript 1 and 2.

Note: You should keep as files included in your ActionScript outside of your class path(s) so that they are not accidentally interpreted as classes.

__________________
senocular is offline   Reply With Quote
Old 08-28-2006, 09:31 PM   #188
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Duplicate Variable Definitions

In ActionScript 1 and ActionScript 2, it was possible to define a variable twice in the same scope without error. For example:
Code:
// ActionScript 1 and 2  
var i:Number = 1;
var i:String = 2;
This is no longer allowed in ActionScript 3. In ActionScript 3, once you define a variable for a scope, that variable is set for that scope and cannot be redefined as a new variable or as a new type. This, of course, doesn't mean you cannot change the value of a variable. It just means, essentially, that the var keyword should only be used once to declare/define any one variable given any scope.
Code:
// ActionScript 3  
var i:Number = 1;
var i:String = 2; // ERROR: duplicate definition or undefined property
For ActionScript 3, if you need a new type, you will need to create a new variable to contain that type. Also, if you have situations where var was used twice in, for instance, two separate if blocks, you will want to first declare the variable outside the blocks and assign them within.
Code:
// ActionScript 3 INCORRECT
// (but works in AS1 and AS2)
if (my_btn.enabled == true) {
	var returnValue:Number = 1;
}else{
	var returnValue:Number = 0;
}
if (provideAsString == true) {
	var returnValue:String = "1";
}else{
	var returnValue:String = "0";
}
The correct way to do this for AS3 is:
Code:
// ActionScript 3 CORRECT
var returnValueNum:Number;
var returnValueStr:String;
if (my_btn.enabled == true) {
	returnValueNum = 1;
}else{
	returnValueNum = 0;
}
if (provideAsString == true) {
	returnValueStr = "1";
}else{
	returnValueStr = "0";
}
Notice that two different variables were used instead of 1 since they have different types. Also the variables were declared once outside of the if blocks instead of twice within. Alternatively, you could also use one variable with the * type.
Code:
// ActionScript 3 ALSO OK
var returnValue:*
if (my_btn.enabled == true) {
	returnValue = 1;
}else{
	returnValue = 0;
}
if (provideAsString == true) {
	returnValue = "1";
}else{
	returnValue = "0";
}

__________________
senocular is offline   Reply With Quote
Old 08-30-2006, 10:59 AM   #189
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
mouseEnabled and Event Blocking

In ActionScript 1 and 2, instances with button events like onPress and onRollOver intercepts control of all button events that occurred over that instance. This means that if there was overlap between two instances with button events, the events occuring within the overlapping area would always go to the instance on top and never on the one below since those events were intercepted by the overlapping instance. Events to the underlying instance could be accessible in those overlapping areas only if all button events were removed from the topmost instance.

In ActionScript 3, the same concept applies, but the behavior is no longer dependant on button events like onPress since events are now handled exclusively with EventDispatcher. Instead, a property is used: mouseEnabled (flash.display.InteractiveObject.mouseEnabled).

The mouseEnabled property actually kind of serves two purposes. First it prevents (true, default) or allows (false) mouse events going to instances below the topmost instance. It also enables (true, default) or disables (false) mouse instances from being dispatched to the that instance. It acts very much like the enabled property of AS1 and AS2.

Notice the behavior of the following AS3 script. The topmost circle will be clicked when it is enabled. When not, events will go to the underlying circle.
Code:
function createCircle(name:String = ""):DisplayObject {
	var circle:Sprite = new Sprite();
	circle.name = name;
	circle.graphics.lineStyle(0);
	circle.graphics.beginFill(0xFF8080);
	circle.graphics.drawCircle(50, 50, 50);
	return circle;
}

circle1 = createCircle("circle 1");
circle2 = createCircle("circle 2");
circle2.x += 25;

addChild(circle1);
addChild(circle2);

circle1.addEventListener(MouseEvent.MOUSE_DOWN, click);
circle2.addEventListener(MouseEvent.MOUSE_DOWN, click);

function click(e) {
	trace(e.target.name + " clicked."); // trace name
	
	// disable and re-enable circle2 with each click
	circle2.mouseEnabled = !circle2.mouseEnabled;
}
Keep in mind that mouseEnabled is true by default. This means that even without button (or any) events associated with a display object instance, it will block events to those instances below it. If you don't want that to happen, you will have to appropriately set mouseEnabled = false where needed.

__________________
senocular is offline   Reply With Quote
Old 08-30-2006, 02:01 PM   #190
Enemу
Registered User
Quote:
Originally Posted by senocular
since appendText is faster and more efficient.
I'm just curious, what makes it faster?

Any ideas about what implementation brings this improvement are welcome.
Enemу is offline   Reply With Quote
Old 08-30-2006, 02:34 PM   #191
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Quote:
Originally Posted by Enemу
I'm just curious, what makes it faster?

Any ideas about what implementation brings this improvement are welcome.
Its an internal method that doesn't rely on the get/set of the text property. Essentially any single method used to replace += will be much more efficient.

__________________
senocular is offline   Reply With Quote
Old 09-03-2006, 11:19 AM   #192
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
mouseChildren with Event Propagation

The mouseChildren property (flash.display.DisplayObjectContainer.mouseChildren) is a new property that allows you to essentially control the mouseEnabled of all the children of a sprite (or other display object container). This allows the parent sprite to have its own events without having to worry about interference with events coming from its children.
Code:
spriteInstance.mouseChildren = false;
Though ActionScript 3 now has a SimpleButton class (flash.display.SimpleButton). this property would play an important role in making custom buttons with the MovieClip or Sprite classes. Consider what would happen if you created a rollover event that caused a sprite or movie clip-based button to remove its current graphics and create new ones for a rollover state. With the children of that sprite capable of receiving mouse events, events would fire for the children within the button - events which would propagate to the main sprite. This could mean duplicate events as well as making the event target for those events the children of the button instead of the button itself. Setting mouseChildren to false you can prevent that from happening.

The easiest demonstration is a simple click of a sprite containing another sprite. Change the value of mouseChildren between true and false and notice which sprite is designated as the target of the event:
Code:
// main button
var spriteButton:Sprite = new Sprite();
spriteButton.name = "spriteButton";
spriteButton.mouseChildren = true;

// graphics
var spriteGraphics:Sprite = new Sprite();
spriteGraphics.name = "spriteGraphics";
spriteGraphics.graphics.beginFill(0x4080A0);
spriteGraphics.graphics.drawCircle(50, 50, 25);

// add to display list
spriteButton.addChild(spriteGraphics);
addChild(spriteButton);

// events
spriteButton.addEventListener(MouseEvent.CLICK, click);
function click(evt:MouseEvent):void {
	trace(evt.target.name);
}
When true (default), the sprite within the button that was clicked is marked as the target. When false, the button sprite itself is the target - something which is more desirable in this case.

mouseChildren = true; output
Code:
spriteButton
mouseChildren = false; output
Code:
spriteGraphics

__________________
senocular is offline   Reply With Quote
Old 09-03-2006, 11:38 AM   #193
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
rollOver and rollOut vs. mouseOver and mouseOut

The InteractiveObject class (flash.display.InteractiveObject) in ActionScript 3 has both rollOver and rollOut events as well as mouseOver and mouseOut events.

Both sets of events determine when a mouse enters or leaves the graphics area of an interactive object. The rollOver and mouseOver events fire when the mouse comes in contact with an interactive object, while rollOut and mouseOut occur when the mouse leaves the interactive object.

Where they differ is with their interaction with interactive object children. The roll events (rollOver and rollOut) simplify the process and prevent interference with child events. Essentially, this is the same as using mouseOver and mouseOut with mouseEnabled set to false. mouseOver and mouseOut with mouseEnabled provide a parent sprite with events from its children. rollOver and rollOut keeps the events on the parent object.

Example: toggle between the use of the ROLL_OVER & ROLL_OUT and MOUSE_OVER and MOUSE_OUT events.
Code:
// main button
var spriteButton:Sprite = new Sprite();
spriteButton.name = "spriteButton";

// graphics
var spriteGraphics1:Sprite = createGraphics("spriteGraphics1", 0xFF, 50, 50, 25);
var spriteGraphics2:Sprite = createGraphics("spriteGraphics2", 0x80, 50, 50, 15);

// add to display list
spriteButton.addChild(spriteGraphics1);
spriteButton.addChild(spriteGraphics2);
addChild(spriteButton);

// events
spriteButton.addEventListener(MouseEvent.ROLL_OVER, over);
spriteButton.addEventListener(MouseEvent.ROLL_OUT, out);
//~spriteButton.addEventListener(MouseEvent.MOUSE_OVER, over);
//~spriteButton.addEventListener(MouseEvent.MOUSE_OUT, out);

function over(evt:MouseEvent):void {
	trace("over: " + evt.target.name);
}
function out(evt:MouseEvent):void {
	trace("out: " + evt.target.name);
}

// create circles
function createGraphics(name:String, color:uint, x:Number, y:Number, radius:Number):Sprite {
	var circle:Sprite = new Sprite();
	circle.name = name;
	circle.graphics.beginFill(color);
	circle.graphics.drawCircle(x, y, radius);
	return circle;
}
You'll notice that with rollOver and rollOut, spriteButton is the target and doesn't receieve events from its children while the opposite is true for mouseOver and mouseOut.


rollOver and rollOut output
Code:
over: spriteButton
out: spriteButton
over: spriteButton
out: spriteButton
mouseOver and mouseOut output
Code:
over: spriteGraphics1
out: spriteGraphics1
over: spriteGraphics2
out: spriteGraphics2
over: spriteGraphics1
out: spriteGraphics1

__________________
senocular is offline   Reply With Quote
Old 09-03-2006, 11:47 AM   #194
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
DisplayObjectContainer contains()

With ActionScript 3, you can easily determine if a sprite or other display object container contains any otherr display object using the contains method (flash.display.DisplayObjectContainer.contains()). The contains method returns true if the display object passed is within the target display object container or any of its children.

Example:
Code:
var king:Sprite = new Sprite();
var queen:Sprite = new Sprite();
var jack:Sprite = new Sprite();
var joker:Sprite = new Sprite();

queen.addChild(jack);
king.addChild(queen);
addChild(king);
addChild(joker);

trace(king.contains(queen)); // true
trace(king.contains(jack)); // true
trace(king.contains(joker)); // false
If you just want to see if the instance is within the target only and not any of its children, just compare the target with the parent property of the instance you're checking for.

Code:
trace(queen.parent == king); // true
trace(jack.parent == king); // false

__________________
senocular is offline   Reply With Quote
Old 09-03-2006, 12:14 PM   #195
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Cleaning Up Event Listeners

When dealing with display objects in ActionScript 3, its important to remember that they can exist when not actually within a display list or visible on the screen. By removing objects from a display list, you do not stop events from occuring within that object (save for mouse events, obviously). This means that enterFrame events will continue to run for display objects even when removed from the screen. This is contrary to the behavior in ActionScript 1 and 2 where removal from the screen also meant removal from the entire movie, killing off all events related to it.

If you want to events like enterFrame to stop when you remove a display object from a display list, you'll want to do that manually, cleaning up after yourself when through with your display objects. To make this easier, you can use the removed event to determine when the display object has been removed from its parent. You can even use the added event to determin when its been added (thereby letting you reinstate an enterFrame listener, for example).

Example:
Code:
var sprite:Sprite = new Sprite();
sprite.addEventListener(Event.ADDED, addEnterFrame);
sprite.addEventListener(Event.REMOVED, removeEnterFrame);

// add/remove enter frame event
function addEnterFrame(evt:Event):void {
	trace("added");
	sprite.addEventListener(Event.ENTER_FRAME, enterFrame);
}
function removeEnterFrame(evt:Event):void {
	trace("removed");
	sprite.removeEventListener(Event.ENTER_FRAME, enterFrame);
}
function enterFrame(evt:Event):void {
	trace("Time: " + getTimer());
}

// add and remove by clicking
stage.addEventListener(MouseEvent.CLICK, addRemove);
function addRemove(evt:Event):void {
	if (this.contains(sprite)) {
		this.removeChild(sprite);
	}else{
		this.addChild(sprite);
	}
}
If removed wasnt used to cleanup the enterFrame event listener for the sprite when it was removed from the current display list, it would continue to run even though the sprite was removed from the screen.

output
Code:
added
Time: 813
Time: 927
removed
added
Time: 2509
Time: 2597
removed

__________________
senocular is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 29 (1 members and 28 guests)
Uli
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 10:25 AM.

SHARE:

SUPPORTERS:

cdn
content delivery network (cdn)

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd. Copyright 2010 - kirupa.com Copyright 2010 - kirupa.com