Why i get this error - actionscript-3

I have a png image on Library that i have declared it via Properties as Background class which extends BitmapData.
When i type:
var BMDClass:Class = getDefinitionByName( "Background" ) as Class;
i get: variable Background is not defined!!
But when i do:
trace( getQualifiedClassName( new Background(0,0) ) );
i get: Background !!
I can't figure out the cause of the error.

I believe this is because you need to have a reference to the Background class before you can actually get the definition by name. Simply importing the Background class will not compile the class in to your swf, you need to reference it in some way. Creating an instance of the class is one way, however you can also reference the class after your import.
try something like...
import com.somedomain.Background;
Background;
This should create a reference to you class and ensure it is compiled in to your swf.
Edit to show multiple class usage.
If you have multiple background classes, I would recommend trying to make them adhere to an interface. I would then also create a background factory class that would allow you to create background instances from your configuration file. This also means that you would be able to put all your references to your background classes in the factory class. Here is what the factory could look like.
// let the compiler know we need these background classes
import com.somedomain.backgrounds.*;
DarkBackground;
LightBackground;
ImageBackground;
class BackgroundFactory
{
public function create(type:String):Background
{
var bgClass:Class = getDefinitionByName(type) as Class;
return new bgClass();
}
}
Then to get a background instance from your config, you would do something like...
// parse your config file...not sure what format you've got it in.
// instantiate a background factory and create an instance based on the name from your config.
var bgFactory:BackgroundFactory = new BackgroundFactory();
var bg:Background = bgFactory.create(someStr);
Edit to extend example
package com.somedomain.background
{
interface Background
{
function get img():Bitmap;
}
}
package com.somedomain.background
{
class SomeImageBackground extends Sprite implements Background
{
protected var _img:Bitmap;
public function SomeImageBackground():void
{
_img = new SomeAssetFromLibrary();
}
public function get img():Bitmap
{
return _img;
}
}
}
Using these external classes would give you a bit more control over where the images come from. You could load them external, embed them using the embed meta data and even load them from the stage.

Related

linking fla files together in actionscript using document classes

I am working in actionscript3, and since I'm self-taught, I think I've developed some bad habits, including coding on the timeline and using multiple scenes.
I am hoping to rectify this now that I'm working on a larger project.
Based on what I've read, linking multiple .fla files together is a better practice, each with their own document class. Is that correct?
If so, how do I load one .fla with its document class and then link that into the subsequent .fla file (instead of using scenes)? Or am I misinterpreting what was recommended?
Thanks!
There's no point to split your application in several loadable modules unless you have any of the following preconditions:
you have smart resource management to load and unload content
if you put everything into one file it gets just too big and hard to work with in design time or it takes far too long to compile
Regular AS3 alternative to working with scenes is creating/destroying content instances and using the main document class as their manager. You design content in the library and create behavior AS3 classes for them. Lets say, you have two content classes A and B. At the start the manager should show one of them and wait for the signal to show next one:
private var APage:A;
private var BPage:B;
gotoA();
function gotoA():void
{
if (BPage)
{
BPage.destroy();
removeChild(BPage);
BPage.removeEventListener(Event.CLOSE, gotoA);
}
APage = new A;
APage.addEventListener(Event.CLOSE, gotoB);
addChild(APage);
}
function gotoB():void
{
if (APage)
{
APage.destroy();
removeChild(APage);
APage.removeEventListener(Event.CLOSE, gotoB);
}
BPage = new B;
BPage.addEventListener(Event.CLOSE, gotoA);
addChild(BPage);
}
So, both A and B should have respective methods .destroy() that release used resources, unsubscribes methods from events, remove display objects, and so on, and they both should fire Event.CLOSE when they're done.
If you have many pages like that, you need to go for more algorithmic approach. For example, to create class BasicPage which will interact with manager and have the methods needed in all pages already declared:
package
{
import flash.display.Sprite;
class BasicPage extends Sprite
{
// A reference to the page manager instance.
public var Manager:PageManager;
public function destroy():void
{
while (numChildren > 0) removeChildAt(0);
Manager = null;
}
// Subclasses will have an access to this method to tell manager to show another page.
protected function showOtherPage(pageClass:Class):void
{
Manager.showPage(pageClass);
}
// A method that is called by manager when everything is ready.
// If page should take any actions on start it is a good idea to override this method.
public function startEngine():void
{
}
}
}
Then, example page A:
package
{
import flash.events.MouseEvent;
public class A extends BasicPage
{
// Lets say, class A in library have a designed button named Click.
public var Click:SimpleButton;
// We have things to undo here.
override public function destroy():void
{
Click.removeEventListener(MouseEvent.CLICK, onClick);
Click = null;
// Pass the destruction to superclass so it wraps its existence either.
super.destroy();
}
override public function startEngine():void
{
Click.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void
{
// Lets use inherited method to show other page.
showOtherPage(B);
}
}
}
So, PageManager will be like:
package
{
public class PageManager extends Sprite
{
private var Page:BasicPage;
// constructor
function PageManager()
{
super();
showPage(A);
}
function showPage(pageClass:Class):void
{
if (Page)
{
Page.destroy();
removeChild(Page);
Page = null;
}
Page = new pageClass;
Page.Manager = this;
addChild(Page);
Page.startEngine();
}
}
}
This all could look scary at first, but it really isn't. PageManager will always have a current page, once there's a need to show another page, the current will be destroyed on a regular basis. Each page class will tend to its own content, which makes coding simpler, for you don't need to see the whole picture. If you need any persistent data, keep it in the PageManager so each page will have access to the data with no need for the pages to communicate with each other.

In Flash Pro, how to get the Properties panel to expose the properties you define on your ActionScript class?

I'm dabbling with game design and trying to create some characters for the game. Right now I've just created a single MovieClip that contains a rectangle. The MovieClip symbol extends a class that I've created in Flash Builder that implements the logic of a monster. I can then drag an instance of this monster symbol from the library to the stage and the code works when I run the simulation. So far, so good.
Now I want to create several monsters, all slightly different:
public class Monster extends MovieClip
{
public var isFriendly:Boolean = true;
public var strength:int = 10;
public var catchPhrase:String = "Booyah!";
public function Monster()
{
}
}
One way to do this is to write a new class for each monster that extends Monster and sets the properties I want in the constructor (I'd also have to create a unique symbol in the library for each of these variations too). However, this seems to be overkill if my monsters only differ by their property values.
Looking at the Flash Professional use interface, I see that at the very bottom of the Properties panel is a section that looks like a small table headed by 'Properties/Value'. Can I use this to somehow set the properties of my classes from within the Flash Professional UI? I can't find any info on how this is used.
Okay, I figured it out. The key is converting my symbol into a flash Component.
First I edited my ActionScript class to export the properties I wanted to set (including the Inspectable tag):
public class Monster
{
private var _catchPhrase:String;
public function Monster()
{
}
public function get catchPhrase():String
{
return _catchPhrase;
}
[Inspectable(name = "catchPhrase", type = String, defaultValue = "Booyah!")]
public function set catchPhrase(value:String):void
{
_catchPhrase = value;
}
}
Then I right clicked on the Monster symbol in my library and selected 'Component Definition...'. This brought up the Component Definition dialog. I then entered the name of my ActionScript class in the Class field and clicked the checkmark to validate it. Flash then automatically generated the properties I needed.
I also found this tutorial helpful:
http://redbjarne.wordpress.com/actionscript-3-0-custom-components-from-hell/

Where can I define a class globally?

I have a class, and I'd like to make it available for use anywhere within a Flash project. Where should I put it? Ideally, it'd be in a separate ActionScript file.
If your ActionScript 3 project using classes, you can simply create global variable using public static like this :
//MyClass.as
package {
public class MyClass {
public static var myValue = 3;
}
}
//Arbitrary.as
package {
public class Arbitrary {
function Arbitrary():void {
trace(MyClass.myValue); //3
}
}
}
You in every project, follow these steps to enable.
Click ActionScript 3.0 Settings...
Click Source path folder icon, select a you want src folders.
You can use top level default package declaration.
package com.abc.globals
{
//Note here No Class Declaration
public var globalVars:String = "Global is horrible";
}
So that you can use without import statement and you can use access variable without class or instance.
It is like our trace("Hello Global").
globalVars will access from anywhere in application.

movie clip class parameters ane null

I have a movie clip with an external class attached.
here is the MC code (I've shorten it only for the relevant part...)
package {
//all the imports here...
public class mc_masterChapter extends MovieClip {
public function mc_masterChapter() {
trace (picFile,strChapTitle);
}
//Properties
public var picFile:String;
public var strChapTitle:String;
}
}
In the main class file I'm adding this object to stage using addChild:
var masterChapter:mc_masterChapter = new mc_masterChapter;
masterChapter.picFile = "pic_Chap1.jpg";
masterChapter.strChapTitle = "ABCD:
addChildAt(masterChapter,1);
now, the trace in the MC class code gives nulls to both parametes but if i put a trace inside the MC timeline (instead of the attached class code), it gives the right value!
how can I access the values from the MC class itself without getting nuls?
Thank you.
It works! Let me explain:
var masterChapter:mc_masterChapter = new mc_masterChapter; // Calls class constuctor
// so calls trace() too!
// You will get null null
masterChapter.picFile = "pic_Chap1.jpg"; // Assign the variables
masterChapter.strChapTitle = "ABCD"; // so they can be read
trace(masterChapter.picFile, masterChapter.strChapTitle); // Should trace pic_Chap1.jpg ABCD
If you add the following method to your class:
public function test():void {
trace(picFile, strChapTitle);
}
Then call masterChapter.test() it will successfully trace those two properties. So yes, the class can read its properties.
Make the var you use in your main class public static vars.
OK!
I solved the mystery.
I put two traces. one in the main MC class saying "hey, I'm inside the MC - the picFile="
and one in the put Function saying "I'm putting this file into picFile:"
well this is what I've got:
hey, I'm inside the MC - the picFile=null
I'm putting this file into picFile:image.jpg
got it!?! at the moment I asked him to give birth to an instance of the MC (even before putting it on stage - just defining the object (with this line:)
var masterChapter:mc_masterChapter = new mc_masterChapter;
it allready run the class, so of course that in this stage the parameters were not defined allready and were null.
the definition code came right after that line (in the main.as)
masterChapter.pic="pic_Chap1.jpg";
so what I did, was to move all the code from the main class of the MC object to a public function inside the same package called init(). Then I called this function manually from the parent main class.
By that I can decide when to call it (after I declare all the parameters of course).
That's it.
god is hiding in the small details : )
tnx for all the helpers.
Possibly a better solution would be to use a getter/setter pair, so you can know at the exact moment the properties are set:
protected var _picFile:String:
public function get picFile():String {
return _picFile;
}
public function set picFile(value:String):void {
if (value != _picFile) {
_picFile=value;
trace('picFile set to', _picFile);
}
}

In AS3, can a library symbol extend another library symbol, assuming each are linked to a class?

For example:
Library symbol "Card" is linked to class "Card" which extends "MovieClip". Library symbol "Card" contains a card background image.
Library symbol "Ace" is linked to class "Ace", which extends class "Card". Library symbol "Ace" contains a TextField with a big letter "A".
So we have Ace extends Card which extends MovieClip. Ace therefore extends MovieClip, but does not DIRECTLY extend MovieClip.
When I drop an instance of Ace on the stage and compile the clip, all that shows up is the big letter A. However, I expected the background image from Card to be included, since Ace extends Card, and the Card symbol contains the background.
It seems like Flash ignores symbol content unless it belongs to the top-level class being instantiated. I think it's LAME that one symbol can't extend another. The IDE could easily draw Card as a non-editable background while I'm editing Ace which extends it, and it should instantiate Card's content and then Ace's content when an Ace is instantiated. Thoughts?
Yeah, I've tried to do that. In theory you'd expect the display list of each extended class to stack, but they don't - it works as you describe, where you only see the graphics associated with the most recent class.
It's not a deal-breaker for you, though - various architectural options are at your disposal. You could, for instance, create a CardBackground class which is exported out of your library and has the card shape etc. Then you create a Card class which has a background:CardBackground property. Then your Ace class can extend Card and it should have the desired background.
Technically you're supposed to favor composition over inheritance, but Flash really encourages the inheritance mindset. Once you get used to breaking out of that you'll realize it's possible to create much more powerful, robust classes using composition in the manner described.
Cheers, and I hope that helps!
The base class to your card_mc(Card movieclip) may be your Card class but it doesn't make your Card class synonymous with card_mc.
Try doing this instead:
1) Create a movieclip containing the card background image and call it cardSprite_mc. Give it the class name CardSprite and set its base class to flash.display.Sprite.
2) Create a movieclip containing the textfield containing the letter "A" and call it ace_mc. Give it the class name Ace and a base class of com.cards.Ace.
3) Create a class called Card with the following code:
package com.cards
{
import flash.display.Sprite;
public class Card extends Sprite
{
public function Card():void
{
addChildAt(new CardSprite(), numChildren - 1);
}// end function
}// end class
}// end package
4) Create a class called Ace with the following code:
package com.cards
{
import com.cards.Card;
public class Ace extends Card
{
public function Ace():void
{
}// end function
}// end class
}// end package
Now if you add an instance of Ace to the stage you should see the card background image too.
I hope this helped :)
You can't do this in a programmatic way.
Instead you have to use the Flash Authoring environment. Extend symbols by creating one which includes the base symbol inside it.
And, yes I agree, it's quite LAME.
Taurayi's solution is inspiring, because it establishes that missing explicit link from Class to Symbol, ensuring the Symbol's content is instantiated whether it's the top-level class or just a base class in an inheritance chain. A side effect of that approach, however, is that it adds an extra containment level in Card's content, namely the CardSprite container.
I have managed to implement a practical generic solution that actually preserves the expected stacking behavior of all inherited symbols. For example, if you check "numChildren" on an instance of Symbol2 below, it will be exactly the sum of Symbol1.numChildren and Symbol2.numChildren, so it's a true merge stacking of symbol content.
When your symbol is in an inheritance chain, simply add this "ensureLinkage" call anytime after a call to the super() method.
package
{
public class Symbol1 extends Sprite
{
public function Symbol1()
{
super();
BugFixes.ensureLinkage( this, "Symbol1" );
}
}
}
package
{
public class Symbol2 extends Symbol1
{
public function Symbol2()
{
super();
BugFixes.ensureLinkage( this, "Symbol2" );
}
}
}
Note: Don't forget to make sure your top-level symbol also explicitly defines a class with the above pattern.
When Symbol2 and Symbol1 are linked to corresponding symbols in the library, their content will now stack. Just drop an instance of Symbol2 on the stage, and test the movie. You'll see that Symbol1's content appears under Symbol2's content. (Note: does not appear in the designer, since this is a runtime fix).
The implementation of ensureLinkage is as follows:
package
{
import flash.utils.getQualifiedClassName;
import flash.utils.getDefinitionByName;
import flash.events.Event;
public class BugFixes
{
public static var linkageMonitor:Object = new Object();
private static var linkageMonitorAuthority:Array = new Array();
public function BugFixes()
{
}
public static function ensureLinkage( instance:*, className:String )
{
if (getQualifiedClassName( instance ) != className) //detect non-top-level construction
{
//prevent inevitable factorial-recursive construction
var stack:Array = linkageMonitor[instance] as Array;
if (stack == null)
{
stack = new Array();
stack["numChildren"] = instance.numChildren;
linkageMonitor[instance] = stack;
}
var barredByAuthority:Boolean = false;
if (linkageMonitorAuthority.length > 0)
barredByAuthority = (linkageMonitorAuthority[linkageMonitorAuthority.length - 1] as Array).indexOf( className ) > -1;
if (stack.indexOf( className ) == -1 && !barredByAuthority)
{
stack.push( className ); //remember construction
trace( "ensuring Linkage of inherited class " + className );
//perform top-level construction to trigger symbol linkage and child object instantiation
linkageMonitorAuthority.push( stack );
var temp:* = new (getDefinitionByName( className ) as Class)();
linkageMonitorAuthority.pop();
//Merge children
while (temp.numChildren > 0)
instance.addChild( temp.getChildAt( 0 ) );
//Merge properties
for (var prop:String in temp)
instance[prop] = temp[prop];
}
else
{
trace( "skipping redundant construction of: " + className );
}
}
else
{
var stack:Array = linkageMonitor[instance] as Array;
if (stack != null)
{
var nc:int = int(stack["numChildren"]);
trace("construction completing for " + getQualifiedClassName( instance ) );
for (var i:int = 0; i < nc; i++)
instance.setChildIndex( instance.getChildAt( 0 ), instance.numChildren - 1 );
}
delete linkageMonitor[instance]; //top-level constructor is completing, all relevant sub-objects have been constructed
}
}
}
}
Basically, it detects whether symbols are going to need manually instantiated, by seeing whether the qualified class name of the instance matches the expected class name passed to the call from the class itself. Since it's called after "super", the calls start at the deepest class and ensure its library symbol's children are instantiated by making a temporary top-level instance and claiming its children as its own. The very first call for the instance also grabs the original number of children present, since the top-level clip in the stack will have already instantiated its children before any constructor code is run at all. By storing that number, a final step can then pull those initial children to the top where they belong. The class ensures no unnecessary recursion takes place, by using an "authority" stack to ensure the main stack is always visible to child constructors.
One issue is that static strokes are not persisted, but that is only because AS3 provides no API for accessing strokes (i.e. once you draw a line in the designer, or with graphics.lineTo, there is no way to programatically access that stroke for enumeration or modification purposes, except to clear all strokes at once). So that's not a limitation of this approach, but rather Flash's API.
Perhaps Adobe was simply unable to come up with this implementation :P
Please note that if your symbols do any work that ties the symbol instance to other code, there could be an issue, since this class claims ownership of children from a temporary instance. It also claims the values of variable references from the temporary instance using a for loop, but that's the best it can do in a generic implementation such as this.