flash as3 serial port - actionscript-3

Hey trying to bring data in through the serial port but i get this error.
1037: Packages cannot be nested.
I then need to take these values and use 1 to control video playback and the other to control the audio volume
package
{
import flash.display.Sprite;
import flash.net.XMLSocket;
import flash.events.DataEvent;
public class receiveData extends Sprite
{
public static const PORT:Number = 5331;
public static const COMMA:String = ",";
public static const LOCALHOST:String = "127.0.0.1";
private var socket:XMLSocket = null;
public function receiveData()
{
super();
init();
}
private function init():void
{
socket = new XMLSocket();
socket.addEventListener( DataEvent.DATA, doSocketData );
socket.connect( LOCALHOST, PORT );
}
protected function doSocketData( event:DataEvent ):void
{
var parts:Array = null;
var sensorone:Number = 0;
var sensortwo:Number = 0;
var values:String = event.data.toString();
parts = values.split( COMMA );
trace( parts[0]);
trace( parts[1]);
sensorone = new Number( parts[0] );
sensortwo = new Number( parts[1] );
}
}
}

So basically you need to put that code in a separate AS3 file and set that as the document class or as the class file for a MovieClip you make in Flash. Alternatively you could use a different IDE like FlashBuilder or FlashDevelop or FDT and avoid the Flash IDE (which as a programmer primarily I feel muddles things up quite a bit).
http://www.actionscript.org/forums/showthread.php3?t=136364 (haha SO won't let me LMGTFY)
Looks like you're on the right track though if you're using tinkerproxy or something of the sort to forward the data (have fun I gotta get myself back into that, check out links in th description of my vid http://www.youtube.com/watch?v=71eFWknHKEM&list=UUSz-eugjE1d6yki6ZT51CKg&index=17&feature=plcp :)

Related

What am I missing in this Embed & Texture create code?

I am trying to follow the Starling video tutorials by Hemanth Sharma. I have typed the code as he has done on his 2nd video (linked here), but I am having difficulty getting the same results.
At first, when my code matched Mr. Sharma's and appeared as:
var bitmap:Bitmap = new Assets[name]();
gameTextures[name] = Texture.fromBitmap( bitmap );
I received the error using this code. The error stated that I was trying to instantiate a class from a non-object.
I traced the code process by breaking this into steps. Now my code appears as:
trace( "Building for", name );
var classObj : Class = Assets[name];
trace( "Class", classObj );
var bitmap : Bitmap = new classObj() as Bitmap;
trace( "Bitmap", bitmap );
trace( "Assign value" );
Assets["gameTextures"][name] = Texture.fromBitmap( bitmap );
trace("Value assigned" );
Using this code, I am able to see that the reason I get the error with Mr. Sharma's code is that the classObj, which Mr. Sharma accesses using Assets[name], initializes to null.
Mr. Sharma has no constructor to set the value of the static variables, so I assume that the Embed meta tag has something to do with the assignment of value to this field.
I will copy my code from that file and paste it below.
Does anyone see where I am making my error?
Can anyone explain how Embed metatags work so that I can find the error with more skill than I have now?
Assets.as:
package
{
import flash.display.Bitmap;
import flash.utils.Dictionary;
import starling.textures.Texture;
public class Assets
{
[Embed(source="../media/graphics/bgWelcome.jpg")]
public static const BgWelcome:Class;
[Embed(source="../media/graphics/welcome_hero.png")]
public static const WelcomeHero:Class;
[Embed(source="../media/graphics/welcome_title.png")]
public static const WelcomeTitle:Class;
[Embed(source="../media/graphics/welcome_playButton.png")]
public static const WelcomePlayButton:Class;
[Embed(source="../media/graphics/welcome_aboutButton.png")]
public static const WelcomeAboutButton:Class;
private static var gameTextures:Dictionary = new Dictionary();
public static function getTexture( name: String ): Texture
{
if( Assets.gameTextures[name] == undefined ){
trace( "Building for", name );
var classObj : Class = Assets[name];
trace( "Class", classObj );
var bitmap : Bitmap = new classObj() as Bitmap;
trace( "Bitmap", bitmap );
trace( "Assign value" );
Assets["gameTextures"][name] = Texture.fromBitmap( bitmap );
trace("Value assigned" );
}
return Assets.gameTextures[name];
}
}
}
You as well might try..catch it to diagnose error immediately.
public static function getTexture(name:String):Texture
{
if (!Assets.gameTextures[name])
{
try
{
var aClass:Class = Assets[name];
var aRaster:Bitmap = new aClass();
Assets.gameTextures[name] = Texture.fromBitmap(aRaster);
}
catch (fail:Error)
{
throw "There's no texture <" + name + "> in Assets.";
}
}
return Assets.gameTextures[name];
}
I'm currently working on a game and have a similar setup like yours, this is the code I have been using with success:
EmbeddedAssets.as (inside a folder named utils):
package utils
{
import starling.textures.Texture;
public class EmbeddedAssets
{
[Embed(source = "./../assets/icons/stats.png")]
private static const stats:Class;
public static const statsButtonTexture:Texture = Texture.fromEmbeddedAsset(stats);
Embed(source = "./../assets/icons/stats_down.png")]
private static const stats_down:Class;
public static const statsButtonDownTexture:Texture = Texture.fromEmbeddedAsset(stats_down);
}
}
Then, somewhere else in my code I use those reference as follows:
private function setStatsButtonStyles(button:Button):void
{
var defaultICon:ImageLoader = new ImageLoader();
defaultIcon.source = EmbeddedAssets.statsButtonTexture;
defaultIcon.width = 60;
defaultIcon.height = 60;
var downIcon:ImageLoader = new ImageLoader();
downIcon.source = EmbeddedAssets.statsButtonDownTexture;
downIcon.width = 60;
downIcon.height = 60;
button.defaultIcon = defaultIcon;
button.downIcon = downIcon;
button.width = button.height = 60;
}
Note that I use a Feathers UI Button, not a Starling one (Feathers Buttons have more functionality but the idea is the same).

How to free memory after use of FileRerence?

See [Solution]
FileReference.load(); does not have a function to unload, just as there is new Loader ().unload();.
Must be a "BUG" from Flash or FileReference needs improvement, type in a new version add a function like this: FileReference.unload();
Or am I mistaken and exists a SOLUTION?
I tried to set "NULL" to a variable of type FileReference, but clearly this does not work for the Flash works with GC (garbage collector), but this is not the focus of the question.
The problem is that a lot of memory when loading multiple files with new FileReferenceList is necessary, but I can not free memory after the process.
How to free memory after use of FileRerence?
See my code:
Main.as
package {
import com.mainpackage.LoaderTestCase;
import flash.net.FileReferenceList;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.events.Event;
import flash.display.MovieClip;
public class Main extends MovieClip {
private var listFiles:Array;
private var allTypes:Array;
private var fileRef:FileReferenceList;
private var test:int;
public function Main()
{
test = 0;
listFiles = [];
allTypes = [];
fileRef = new FileReferenceList();
fileRef.addEventListener(Event.SELECT, select);
fileRef.browse(allTypes);
}
private function select(e:Event):void
{
listFiles = fileRef.fileList;
for(var i:uint=0, j:uint=listFiles.length; i<j; i++)
{
insert(i);
}
}
private function insert(c:int):void
{
var fire:LoaderTestCase = new LoaderTestCase(listFiles[c]);
fire.destroy(function():void
{
//Delete LoaderTestCase after timeout ???
fire = null;
test++;
if(test>=listFiles.length) {//Remove FileReference
fileRef.removeEventListener(Event.SELECT, select);
fileRef = null;
for(var i:uint=0, j:uint=listFiles.length; i<j; i++) {
listFiles[i] = null;
}
listFiles = null;
trace("Clear memory");
}
});
}
}
}
LoaderTestCase.as
package com.mainpackage
{
import flash.net.FileReference;
import flash.events.Event;
import flash.display.Loader;
public class LoaderTestCase
{
private var file:FileReference;
private var loader:Loader;
private var callback:Function;
public function LoaderTestCase(e:FileReference)
{
file = e;
trace("OPEN: " + file.name);
file.addEventListener(Event.COMPLETE, loadFile);
file.load();
e = null;
}
public function loadFile(e:Event):void
{
file.removeEventListener(Event.COMPLETE, loadFile);
trace("LOAD: " + file.name);
file = null;
e = null;
callback();
}
public function destroy(a:Function):void
{
callback = a;
}
}
}
Remove the event listeners before you null the listening object.
You could use weak references to let the listeners be removed when the object is Garbage Collected.
object.addEventListener( ......, ......., false, 0, true );
for example, in your LoadFile function:
...
LoadFile(file);
}
});
...
should be:
...
LoadFile(file);
}
}, false, 0, true );
...
Or you will have to remove them manually.
To do that you will need to move the event handlers into new named functions.
Also you will need an array for storing the references to listeners and listening objects, to be able to remove the listeners AFTER the listeners are not needed any more and BEFORE nulling the listening object.
PLEASE NOTE:
When you are testing it and watching the current memory usage, make sure to force the Garbage Collector when you feel the memory usage should have dropped by now, but it didn't.
GC kicks in when it wants and very not necessarily after something has been nulled on unloaded.
To be clear, I am only talking about forcing GC during the development/testing.
Even if you null every reference to an object, it won't be deleted immediately from the memory. You have to remove the event listeners aswell. Also, never use "unnamed" functions... it is harder to remove a listener when the event calls an unnamed function. So create a new function, and call that one. For example:
test.contentLoaderInfo.addEventListener(Event.COMPLETE, contentLoaderInfoComplete);
...
function contentLoaderInfoComplete(e:Event){
test.contentLoaderInfo.removeEventListener(Event.COMPLETE, contentLoaderInfoComplete);
test.unload();
test = null;
}
This will clean the memory.
I reached my goal, if I so did FileReferenceList.fileList[5] = null; (when the "sixth file" is not being used more) Flash memory immediately frees this specific FileReference.
In the others words:
This not work:
private var file:FileReference;
...
file = FileReferenceList.fileList[5];
...
file = null;
But this worked:
FileReferenceList.fileList[5] = null;
Worked on all Desktop/Plugins/PepperFlash.
See worked code:
package {
import flash.net.FileReferenceList;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.Sprite;
public class Main extends Sprite
{
private var listFiles:Array;
private var allTypes:Array;
private var fileRef:FileReferenceList;
private var tmpFile:FileReference;
private var i:uint=0;
private var j:uint=0;
private var timer:uint;
private var imageTypes:FileFilter;
private var enable:Boolean;
public function Main()
{
imageTypes = new FileFilter(
"Images (*.JPG;*.JPEG;*.JPE;)", "*.jpg; *.jpeg; *.jpe;"
);
listFiles = [];
allTypes = [imageTypes];
eventBrowse(true);
}
private function eventBrowse(a:Boolean):void
{
enable = a;
if(a===true) {
stage.addEventListener(MouseEvent.CLICK, browse);
fileRef = new FileReferenceList();
fileRef.addEventListener(Event.SELECT, select);
} else {
fileRef.removeEventListener(Event.SELECT, select);
fileRef = null;
stage.removeEventListener(MouseEvent.CLICK, browse);
}
}
private function browse(e:MouseEvent):void
{
if(enable===true) {
fileRef.browse(allTypes);
}
}
private function select(e:Event):void
{
listFiles = fileRef.fileList;
eventBrowse(false);
i=0;
j=listFiles.length;
if(j>0) {
loadNextFile();
}
}
private function loadNextFile():void
{
if(!(i<j)) {
listFiles = null;
trace("Free memory???");
trace("--------------");
trace("listFiles:"+ listFiles);
trace("allTypes:" + allTypes);
trace("fileRef:" + fileRef);
trace("tmpFile:" + tmpFile);
trace("i:" + i);
trace("j:" + j);
trace("timer:" + timer);
trace("--------------");
eventBrowse(true);
return;
}
tmpFile = listFiles[i];
trace("Initiate load:" + tmpFile.name);
tmpFile.addEventListener(Event.COMPLETE, loadedFile);
tmpFile.load();
}
private function loadedFile(f:Event):void
{
trace(listFiles);
trace("Finished load:" + tmpFile.name);
tmpFile.removeEventListener(Event.COMPLETE, loadedFile);
tmpFile = null;
listFiles[i] = null;
i++;
loadNextFile();
}
}
}
The issue is a combination of all the things noted above.
You do need to remove the event listener(s) manually. While its possible to use weak references its better if you make a habit of keeping track of the listeners you register and always unregister them properly. This way you can better avoid memory leaks(not quite a memory leak but has a similar effect) you didn't expect or weren't thinking about.
You are creating event listeners in a loop and re-using the same function to handle all of them. If you do this you must somehow get a reference to the original loader and remove the event listener from it. I have no idea how you tried to incorporate Zhafur's answer but if you re-used file reference for each new file that will be the reason its still not working. Perhaps you can update you example above with the code you currently have so we can critique further.
You should never force the gc(garbage collector), if you need to do this you have issues elsewhere you should solve instead as san.chez mentioned. Forcing the GC is a good way to see that you are creating too many objects too fast, if you see your memory usage go way down after forcing the GC you probably did this and should rewrite your code to be more efficient in its use of new.
Judging by the amount of memory you have consumed your either creating a ton of small files or a few extremely large ones, perhaps you can tell us more about that as well.

OSMF serial composition with smooth streaming media element

I want to create serial composition for smooth streaming media element with some specific portion of media element from multiple or single manifest(.isml). I have try to create serial composition with isml contain that clip section start from 10 sec to 50 sec and then add next element in serial composition for play 50 sec to 150 sec section from other manifest. but instead of play specified portion of manifest It play from start to end and once the first isml played it is not switch to next element of serial composition. when it check it's working on fire bug on mozila I found that fragment request is send continuously but player not able to show it.
code :-
package
{
import flash.display.*;
import com.microsoft.azure.media.AdaptiveStreamingPluginInfo;
import org.osmf.containers.MediaContainer;
import org.osmf.elements.SerialElement;
import org.osmf.elements.VideoElement;
import org.osmf.events.MediaErrorEvent;
import org.osmf.events.MediaFactoryEvent;
import org.osmf.events.MediaPlayerStateChangeEvent;
import org.osmf.layout.*;
import org.osmf.media.*;
import org.osmf.net.StreamType;
import org.osmf.net.StreamingURLResource;
import org.osmf.net.StreamingItemType;
[SWF(width="1024", height="768", backgroundColor='#ffffff')]
public class OSMFComposition extends Sprite
{
public var _container:MediaContainer;
public var _mediaFactory:DefaultMediaFactory;
private var _mediaPlayerSprite:MediaPlayerSprite;
private const Media_Url1:String="http://<media server>/Sintel/Sintel_H264.ism/manifest";
private const Media_Url2:String="http://<media server>/PushToPublishPoint/test.isml/manifest";
private const add1:String="assets/1.mp4"
private const add2:String="assets/2.mp4"
private var serialElement:SerialElement;
private var mediaPlayer:MediaPlayer;
private var container:MediaContainer;
public function OSMFComposition()
{
serialElement=new SerialElement();
mediaPlayer=new MediaPlayer();
stage.quality = StageQuality.HIGH;
initMediaPlayer();
}
private function initMediaPlayer():void
{
// Create a mediafactory instance
_mediaFactory = new DefaultMediaFactory();
// Add the listeners for PLUGIN_LOADING
_mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD,onPluginLoaded);
// Load the plugin class
loadAdaptiveStreamingPlugin( );
}
private function loadAdaptiveStreamingPlugin( ):void
{
var pluginResource:MediaResourceBase;
pluginResource = new PluginInfoResource(new AdaptiveStreamingPluginInfo( ));
_mediaFactory.loadPlugin( pluginResource );
}
private function onPluginLoaded( event:MediaFactoryEvent ):void
{
// The plugin is loaded successfully.
// Your web server needs to host a valid crossdomain.xml file to allow plugin to download Smooth Streaming files.
loadMediaSource();
}
private function loadMediaSource():void
{
var preRoll:MediaElement = _mediaFactory.createMediaElement( new URLResource(add1) );
var preRoll2:MediaElement = _mediaFactory.createMediaElement( new URLResource(add2) );
var resource1:StreamingURLResource=new StreamingURLResource(Media_Url1,null,10,50);
var element1:MediaElement = _mediaFactory.createMediaElement( resource1 );
var resource2:StreamingURLResource= new StreamingURLResource(Media_Url2,null,150,200);
var element2:MediaElement = _mediaFactory.createMediaElement( resource2 );
serialElement.addChild( preRoll);
serialElement.addChild(element2);
serialElement.addChild( preRoll2);
serialElement.addChild(element1);
mediaPlayer=new MediaPlayer(serialElement);
container=new MediaContainer();
container.addMediaElement(serialElement);
this.addChild(container);
}
}
}
Thanks

Adding eventlisteners in main document class for external classes

I have a small project I'm trying to help learn as3. It is a variation from the book Foundation Game Design with Actionscript 3.0. I am using an fla only to have a document class. All art is loaded within the as files. In the book, he just put all the code in the document class, I followed along and it worked as expected. I am trying to break out the code into separate classes to get a handle on OOP. One class makes a background - Background.as, one makes a character - Character.as, and one makes a button, which I instantiate 6 times for 6 different buttons - GameButton.as. And of course there is GameWorld.as which is the document class. Everything loads and shows up as expected. However when I try and add an eventListener for the buttons, I don't get any response. I have tried putting the eventListener in the GameButton.as and also tried it in the GameWorld.as neither of which has worked. Also I pass a reference to the stage when instantiating the various classes, because when I tried to addChild in the GameWorld.as, nothing would show up. I searched the site and found something similar, but it didn't seem to help. Thank you in advance for any advice you my have. Here is the code:
GameWorld.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.DisplayObject
import flash.events.MouseEvent;
import GameButton;
import Character;
import Background;
[SWR(width = "550", height = "400", backgroundColor = "#FFFFFF", frameRate = "60")]
public class GameWorld extends Sprite
{
//public variables
//Background
public var gameBackground:Background;
//Character
public var catCharacter:Character;
//Buttons
public var upButton:GameButton;
public var downButton:GameButton;
public var growButton:GameButton;
public var shrinkButton:GameButton;
public var vanishButton:GameButton;
public var spinButton:GameButton;
public function GameWorld ()
{
//Add the background to the stage
gameBackground = new Background("../images/background.png", stage);
//Add the character(s) to the stage
catCharacter = new Character("../images/character.png", stage);
//Set initial character position
catCharacter.CharacterPos(225, 150);
//Add the buttons to the stage
upButton = new GameButton("../images/up.png", stage, 25, 25);
downButton = new GameButton("../images/down.png", stage, 25, 85);
growButton = new GameButton("../images/grow.png", stage, 25, 145);
shrinkButton = new GameButton("../images/shrink.png", stage, 425, 25);
vanishButton = new GameButton("../images/vanish.png", stage, 425, 85);
spinButton = new GameButton("../images/spin.png", stage, 425, 145);
//Button event handlers
upButton.addEventListener(MouseEvent.CLICK, upButtonHandler);
}
public function upButtonHandler(event:MouseEvent)
{
trace("You clicked the up button!");
catCharacter.CharacterMove(15);
}
}
}
GameButton.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
public class GameButton extends Sprite
{
//public variables
public var stageRef:Stage;
public var urlRequest:URLRequest;
public var gameButtonLoader:Loader;
public var gameButtonSprite:Sprite;
//Constructor
public function GameButton (urlRequest:String, stageRef:Stage, xPos:Number, yPos:Number)
{
this.stageRef = stageRef
this.urlRequest = new URLRequest();
gameButtonLoader = new Loader();
gameButtonSprite = new Sprite();
this.urlRequest.url = urlRequest;
gameButtonLoader.load(this.urlRequest);
gameButtonSprite.addChild(gameButtonLoader);
this.stageRef.addChild(gameButtonSprite);
gameButtonSprite.buttonMode = true;
gameButtonSprite.x = xPos;
gameButtonSprite.y = yPos;
}
}
}
Character.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
public class Character
{
//private variables
private var stageRef:Stage;
private var urlRequest:URLRequest;
private var characterLoader:Loader;
private var characterSprite:Sprite;
//public variables
public var character_x_pos:Number;
public var character_y_pos:Number;
//Constructor
public function Character (urlRequest:String, stageRef:Stage)
{
this.stageRef = stageRef;
this.urlRequest = new URLRequest();
characterLoader = new Loader();
characterSprite = new Sprite();
this.urlRequest.url = urlRequest;
characterLoader.load (this.urlRequest);
characterSprite.addChild (characterLoader);
this.stageRef.addChild (characterSprite);
characterSprite.mouseEnabled = false;
}
//Set the position of the character
public function CharacterPos(xPos:Number, yPos:Number):void
{
characterSprite.x = xPos;
characterSprite.y = yPos;
}
//Move the position of the character
public function CharacterMove( yPos:Number):void
{
characterSprite.y -= yPos;
}
}
}
Background.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
public class Background
{
//Private variables
private var stageRef:Stage;
private var urlRequest:URLRequest;
private var backgroundLoader:Loader;
private var backgroundSprite:Sprite;
//Constructor
public function Background (urlRequest:String, stageRef:Stage)
{
this.stageRef = stageRef;
this.urlRequest = new URLRequest();
backgroundLoader = new Loader();
backgroundSprite = new Sprite();
this.urlRequest.url = urlRequest;
backgroundLoader.load (this.urlRequest);
backgroundSprite.addChild (backgroundLoader);
this.stageRef.addChild (backgroundSprite);
backgroundSprite.mouseEnabled = false;
}
}
}
All art is loaded within the as files.
This is not an approach I recommend. There's a reason God gave us the Flash IDE--and it's not to write code! Any time you're spending on layout and viduals in code is just wasted, unless you have an actual requirement to change the visuals at runtime. The fact that your paths are all hard-coded suggests that you don't have that requirement.
So let's step back and imagine that you have a Symbol that contains 6 Symbols that you've created as just Flash buttons (when you select Button as the Symbol type). These will be SimpleButtons, but in the Class below we're just going to type them as DisplayObject. The Class doesn't care what they are, but using Simplebutton gives them up, over, down and hit states that require no code.
Note that the below assumes you have "automatically declare stage instances" off, which is IMO the best way to do things.
package view {
public class NavBar extends Sprite {
//because you put these on stage in the Symbol, they will be available in the constructor
public var upButton:DisplayObject;
public var downButton:DisplayObject;
public var growButton:DisplayObject;
public var shrinkButton:DisplayObject;
public var rotateButton:DisplayObject;
public var vanishButton:DisplayObject;
//makes it easier to do the same setup on all buttons
protected var allButtons:Vector.<DisplayObject> = <DisplayObject>([upButton, downButton, growButton, shrinkButton, rotateButton, vanishButton]);
public function NavBar() {
super();
for each (var btn:DisplayObject in allButtons) {
btn.buttonMode = true;
btn.mouseChildren = false;
btn.addEventListener(MouseEvent.CLICK, onButtonClick);
}
}
protected function onButtonClick(e:MouseEvent):void {
switch (e.target) {
case upButton:
dispatchEvent(new CharacterEvent(CharacterEvent.UP));
break;
case downButton:
dispatchEvent(new CharacterEvent(CharacterEvent.DOWN));
break;
case growButton:
dispatchEvent(new CharacterEvent(CharacterEvent.GROW));
break;
case shrinkButton:
dispatchEvent(new CharacterEvent(CharacterEvent.SHRINK));
break;
case rotateButton:
dispatchEvent(new CharacterEvent(CharacterEvent.ROTATE));
break;
case vanishButton:
dispatchEvent(new CharacterEvent(CharacterEvent.VANISH));
break;
default:
break;
}
}
}
}
Note that there's zero layout code. This code is dependent on a custom Event Class. I'm going to write that Event Class so that it always bubbles. That way, it can be dispatched anywhere on the display list and received at the top level:
package control {
class CharacterEvent extends Event {
public static var UP:String = 'characterUp';
public static var DOWN:String = 'characterDown';
public static var GROW:String = 'characterGrow';
public static var SHRINK:String = 'characterShrink';
public static var ROTATE:String = 'characterRotate';
public static var VANISH:String = 'characterVanish';
public function CharacterEvent(type:String) {
super(type, true, true);//always bubbles
}
public function clone():Event {
return new CharacterEvent(type);
}
}
}
Now, if you want to manually handle instantiation of the Symbol that has view.NavBar as its base class, it will look like this:
package {
public var navBar:NavBar;
class GameWorld {
public function GameWorld() {
try {
var navClass:Class = getDefinitionByName('NavBarSymbol') as Class;
} catch (e:Error) {
trace('You need to have a Library symbol called NavBarSymbol');
}
if (navClass) {
navBar = new navClass() as NavBar;
//unnecessary layout code here
//Note that this is NOT the responsibility of the child Class!
addChild(navBar);
}
//instantiate character
...
//by listening to the whole Document, you can add other things that
//dispatch Character events on the display list, like a keyboard listener
addEventListener(CharacterEvent.UP, moveCharacterUp);
//listeners for the rest of the character events...
}
public function moveCharacterUp(e:CharacterEvent):void {
//character move logic
}
//other handlers
}
}
Personally, I'd just add the navBar to the stage, and then there's no need to manage it at all (not even reference it with a variable), simply add the event listeners for the various character events.
The root of your problem doesn't seem to be the character code. However, I'm going to give you a few "best practice" pointers about it.
The convention in AS3 is for Class members (properties and methods) to be camel case starting with a lower case letter. So, characterPos() and characterMove().
Your Class already contains character in the name, so really these should just be pos() and move() (though there's no need now to shorten position()).
The only thing your child Classes are doing with their references to the parent are adding themselves. They don't need and shouldn't have a reference to the parent for this purpose. It is the parent's responsibility to add the Children (or the responsibility of the Flash Player if you use the stage).
That said, you could give your Character a reference to the parent Class typed as IEventDispatcher and allow the Character to listen to this channel. This concept is called an event bus.
Note that the reason that so many people do what you're doing is that Adobe failed to document how to properly use OOP with the timeline. Unfortunately, by the time a few of us started documenting that around late 2009/early 2010, the damage was done and everyone assumed that if you wanted to write good code you had to pretend the timeline and stage didn't exist.
I know I've covered a lot of ground, and probably most of what I said directly contradicts what you thought you knew, so please don't hesitate to ask any questions you might have.

Unable to have Flash Component (SWC) access the library in live preview

I am building a set of Flash components with the ability to replace the skin of the component with another one in the library.
Currently, I am able to access the library after running the application, but not during live preview and I'd like to know if it is possible for the component to access the library while running in live preview mode (the mode where you can drag the component around the stage and change its properties in the Component Parameters window)
Here is a simplified code that just looks to see if there is a symbol of the name specified and than instantiates it and adds it as a child.
package
{
import fl.core.UIComponent;
import flash.display.MovieClip;
import flash.system.ApplicationDomain;
/**
* ...
* #author Roy Lazarovich
*/
public class CompTest extends UIComponent
{
private var customfile :String;
public function CompTest()
{
}
override protected function configUI():void
{
}
override protected function draw():void
{
super.draw();
}
private function setCustomFile():void
{
if (ApplicationDomain.currentDomain.hasDefinition(customfile))
{
var c:Class = Class(ApplicationDomain.currentDomain.getDefinition(customfile));
var mc:MovieClip = new c();
addChild(mc);
}
}
[Inspectable(name = "_Custom File", defaultValue = "")]
public function set _customfile(value:String):void
{
customfile = value;
setCustomFile();
drawNow();
}
}
}
Thanks!
I'm not entirely sure what you have already tried to fix this situation. But hopefully this might help.
Right click on the MovieClip in your library, select Linkage and give it a class name, ie. MyThing.
In your code,
newMyThing = new MyThing();
this.addChild(newMyThing);
trace("tada!");
Hope that helps or gets you closer to a solution.
This works for me in LivePreview, as long as I apply it in configUI, and not draw:
public class EditableBitmap extends UIComponent
{
protected var placeholder:String = "None";
protected var bitmap:Bitmap;
protected var scale:Number = 1;
[Inspectable(name = "Placeholder", type = String, defaultValue="None")]
public function set Placeholder($value:String):void
{
placeholder = $value;
configUI();
}
public function get Placeholder():String { return placeholder; }
public function EditableBitmap()
{
//Console.Debug("NEW EditableBitmap");
super();
}
override protected function configUI():void
{
//Console.Debug("EditableBitmap configUI: " + width);
if (!isNaN(width))
{
wDim = width;
hDim = height;
graphics.clear();
graphics.beginFill(0x000000, 0.1);
graphics.drawRect(0, 0, wDim, hDim);
}
if (placeholder != "None" && placeholder != "")
{
var asset:Class = getDefinitionByName(placeholder) as Class;
var data:BitmapData = new asset() as BitmapData;
bitmap = new Bitmap(data);
}
super.configUI();
}
override protected function draw():void
{
if (bitmap)
{
addChild(bitmap);
bitmap.x = off_x * scale;
bitmap.y = off_y * scale;
bitmap.scaleX = bitmap.scaleY = scale;
}
}
}
NOTE: When I'm working on the FLA where I am editing the component, the bitmap is only displayed from the library inconsistenty. Sometimes it works, sometimes it doesn't. But when I export the SWC and then import the component to another movie, it works every time, in LivePreview as well as at runtime.
UPDATE
It seems this doesn't work in CS6 unless the symbol is already embedded in the component .SWC I wanted to see if I could trick it, by embedding one image in the SWC and then replacing it with another of the same name in the destination file. This didn't work, but it did point me to how you can do this:
So, it's a bit laborious, but you could work around this by:
1) Creating a dummy asset for each property in the component SWC.
2) Overriding this using a custom class in the file where you deploy the component
... all of which may be more trouble than it's worth, but which should provide a solution to the problem.