how to convert string to object name. as3 - actionscript-3

public class ColorLibrary {
private var _allColorCodes:Object;
public function ColorLibrary() {
init();
}
private function init(){
_allColorCodes = {
'black' : '000000',
'white' : 'FFFFFF',
'yellow' : '000000'
}
}
public function exchangeColor(colors:String){
var colorArray:Array = colors.split(',');
for ( var i:int = 0; i < colorArray.length; i++ ) {
_allColorCodes.getDefinitionByName(colorArray[i]);
}
}
}
any idea how to convert string to instance name? Thanks very much~! Strugglying here

You've already got an object there, so you can already go:
_allColorCodes.black .. etc
Considering that _allColorCodes is private, you can do a really nice little getter like so:
public function get colorCode():Object
{
return _allColorCodes;
}
And then just have:
trace(colorCode.black);
trace(colorCode.yellow);
All that said, what I would do is store all this stuff against constants in a class like ColorCodes, like this:
package
{
public class ColorCodes
{
public static const BLACK:uint = 0x000000;
public static const RED:uint = 0xFF0000;
public static const BLUE:uint = 0x0000FF;
public static const GREEN:uint = 0x00FF00;
public static const WHITE:uint = 0xFFFFFF;
}
}
And then access them via:
trace(
ColorCodes.RED
);
Something slightly more advanced that you can do is make use of Proxy and flash_proxy to override the getProperty() method. This means you'll be able to go ColorLibrary.color straight off the bat:
package
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class ColorLibrary
{
private var _allColorCodes:Object;
public function ColorLibrary()
{
_allColorCodes = {
'black' : '000000',
'white' : 'FFFFFF',
'yellow' : '000000'
}
}
override flash_proxy function getProperty(name:*)*
{
return _allColorCodes[name];
}
}
}
Response to comment:
Okay, you don't need to use getDefinitionByName here, you can simply use brackets to access a value of an object by parsing a string.
Example:
var object:Object = {
something: 2,
anotherThing: "something awesome"
};
trace(object["something"]); // same as object.something
trace(object["anotherThing"]); // same as object.anotherThing
Try something like this for your exchangeColor() function:
public function exchangeColor(colors:String):void
{
var colorArray:Array = colors.split(',');
for each(var i:String in colorArray)
{
trace(
_allColorCodes[i]
);
}
}

I canĀ“t see why you would want to do it like this, but here is a function that passes a list of colors (String) and returns hex codes (Array). If one color does not exist you will get lost in the Array. I Recommend using ColorList.RED or at least ColorManager.getColor("red").
var colorList : Array = getColorList("black,yellow");
public function getColorList(colors : String) : Array
{
var result : Array = new Array();
var colorArray : Array = colors.split(',');
for(var i : int = 0; i < colorArray.length ; i++)
{
if(_allColorCodes[colorArray[i]])
result.push(_allColorCodes[colorArray[i]]);
}
return result;
}

Related

Image remains null no matter what I do

I am working on a Action Script project and no matter what I did I wasn't able to get a texture from a Atlas, in the end I had to do some quick changes that I rather not keep. Does anyone know why I cannot get a texture from the createDiabloCrashArt method with this:
package gameObjects
{
import starling.core.Starling;
import starling.display.Image;
import starling.display.MovieClip;
import starling.display.Sprite;
import starling.events.Event;
import starling.utils.deg2rad;
public class Diablo extends Sprite
{
private var _type:int;
private var _speed:int;
private var _distance:int;
private var _alreadyHit:Boolean;
private var _position:String;
private var _hitArea:Image;
private var diabloImage:Image;
private var diabloAnimation:MovieClip;
private var diabloCrashImage:Image;
public function Diablo(_ptype:int, _pdistance:int)
{
super();
this._type = _ptype;
this._distance = _pdistance;
this._speed = GameConstants.DIABLO_SPEED;
_alreadyHit = false;
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
createDiabloArt();
}
private function createDiabloArt():void
{ //Gets some other stuff using the same getAtlas but as MovieAnimation and works.
}
private function createDiabloCrashArt():void
{
// trace("diablo_chingo" + _type + "KO");
if (diabloCrashImage == null)
{
diabloCrashImage = new Image(Assets.getAtlas().getTexture("diablo_chingo" + _type + "KO"));
this.addChild(diabloCrashImage);
}
else
{
diabloCrashImage.texture = Assets.getAtlas().getTexture("diablo_chingo" + _type + "KO");
}
diabloCrashImage.visible = false;
}
private function hidePreviousInstance():void
{
if (diabloAnimation != null && _type <= GameConstants.DIABLO_TYPE_4)
{
diabloAnimation.visible = false;
Starling.juggler.remove(diabloAnimation);
}
if (diabloImage != null) diabloImage.visible = false;
}
public function get type():int { return _type; }
public function set type(value:int):void
{
_type = value;
resetForReuse();
hidePreviousInstance();
createDiabloArt();
}
public function get alreadyHit():Boolean { return _alreadyHit; }
public function set alreadyHit(value:Boolean):void
{
_alreadyHit = value;
if (value)
{
diabloCrashImage.visible = true;
if (_type >= GameConstants.DIABLO_TYPE_1 || _type <= GameConstants.DIABLO_TYPE_4)
{
diabloAnimation.visible = false;
}
else
{
diabloImage.visible = false;
Starling.juggler.remove(diabloAnimation);
}
}
}
public function resetForReuse():void
{
this.alreadyHit = false;
this.rotation = deg2rad(0);
}
}
}
But it works by changing the following things:
private function onAddedToStage(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
createDiabloArt();
createDiabloCrashArt();
}
private function createDiabloCrashArt():void
{
// trace("diablo_chingo" + _type + "KO");
if (diabloCrashImage == null)
{
diabloCrashImage = new Image(Assets.getTexture("Diablo1"));
this.addChild(diabloCrashImage);
}
else
{
diabloCrashImage.texture = Assets.getTexture("Diablo1");
//Assets.getAtlas().getTexture("diablo_chingo" + _type + "KO");
}
diabloCrashImage.visible = false;
}
I verified time and time again with debugger, trace and the like that the right parameters where reaching the function such as _type, as a matter of fact in the long method that I didn't include getting the texture I need using the above syntax worked wonderfully.
I tried to:
Change Image to MovieClip
Initialize before getting to createCrashArt
Getting other textures like the ones I can already display (didn't work)
Staring at it really hard.
Setting a default string for the texture.
None yielded anything until I changed the code to look like in the second snippet, the thing is that I don't get why it didn't work and I rather not depend on a quick fix that may or may not turn into a setback later.
Seriously any help to understand this would be great. I don't even care that ir is working right now I just can't for the life of me figure what was wrong in the first place.
Thanks in advance.
EDIT:
public static function getAtlas():TextureAtlas
{
if (gameTextureAtlas == null)
{
var texture:Texture = getTexture("AtlasTextureGame");
var xml:XML = XML(new AtlasXmlGame());
gameTextureAtlas=new TextureAtlas(texture, xml);
}
return gameTextureAtlas;
}
/**
* Returns a texture from this class based on a string key.
*
* #param name A key that matches a static constant of Bitmap type.
* #return a starling texture.
*/
public static function getTexture(name:String):Texture
{
if (gameTextures[name] == undefined)
{
var bitmap:Bitmap = new Assets[name]();
gameTextures[name]=Texture.fromBitmap(bitmap);
}
//trace("Tomando textura!");
return gameTextures[name];
}
EDIT: Assets class
package
{
import flash.display.Bitmap;
import flash.utils.Dictionary;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
public class Assets
{
/**
* Atlas de texturas.
*/
[Embed(source="../Witchmedia/graphics/Spritesheet/ScarletWitch.png")]
public static const AtlasTextureGame:Class;
[Embed(source="../Witchmedia/graphics/Spritesheet/ScarletWitch.xml", mimeType="application/octet-stream")]
public static const AtlasXmlGame:Class;
/**
* Assets de Fondo y botones.
*/
[Embed(source="../Witchmedia/graphics/bgLayer3.jpg")]
public static const BgLayer1:Class;
[Embed(source="../Witchmedia/graphics/Diablo1.png")]
public static const Diablo1:Class;
/**
* Cache de Texturas
*/
private static var gameTextures:Dictionary = new Dictionary();
private static var gameTextureAtlas:TextureAtlas;
/**
* Returna una instancia del atlas de texturas.
* #return the TextureAtlas instance (Singleton)
*/
public static function getAtlas():TextureAtlas
{
if (gameTextureAtlas == null)
{
var texture:Texture = getTexture("AtlasTextureGame");
var xml:XML = XML(new AtlasXmlGame());
gameTextureAtlas=new TextureAtlas(texture, xml);
}
return gameTextureAtlas;
}
/**
* Returns a texture from this class based on a string key.
*
* #param name A key that matches a static constant of Bitmap type.
* #return a starling texture.
*/
public static function getTexture(name:String):Texture
{
if (gameTextures[name] == undefined)
{
var bitmap:Bitmap = new Assets[name]();
gameTextures[name]=Texture.fromBitmap(bitmap);
}
//trace("Tomando textura!");
return gameTextures[name];
}
}
Can you check with this method, Give the texture declaration in a separate class, i guess it doesnt take the appropriate texture.
public static function getAtlas(atlasNumb:uint = 1):TextureAtlas
{
if(sTextureAtlas[atlasNumb - 1] == null)
{
var texture:Texture = getTexture("AtlasTexture"+atlasNumb);
var xml:XML = XML(create("AtlasXml"+atlasNumb));
sTextureAtlas[atlasNumb-1] = new TextureAtlas(texture, xml);
}
return sTextureAtlas[atlasNumb - 1];
}
private static function create(name:String):Object
{
var textureClass:Class = AssetEmbeds_2x;
return new textureClass[name];
}
And define the textures .png and xml in a separate file called AssetEmbeds_2x.
while calling the texture define like
Assets.getAtlas(1).getTextures("xxx"). I hope it wll

AS3 TypedDictionary?

public dynamic class TypedDictionary extends Dictionary {
private var _type:Class;
public function TypedDictionary(type:Class, weakKeys:Boolean = false) {
_type = type;
super(weakKeys);
}
public function addValue(key:Object, value:_type):void {
this[key] = value;
}
public function getValue(key:Object):_type{
return this[key];
}
...
I want to make TypedDictionary with typisation. But I can not use _type in addValue and getValue. The idea is to use next construction :
var td:TypedDictionary = new TypedDictionary(myClass, true);
td.addValue("first", new myClass());
...
var item:myClass = td.getValue("first");
item.someFunction();
Is any ability to use dynamic class type?
If I un derstand what you are asking for.
This is untested code so it could be error prone, but it should get you on the right path.
public dynamic class TypedDictionary extends Dictionary {
private var _type:Class;
public function TypedDictionary(type:String, weakKeys:Boolean = false) {
_type = getDefinitionByName(type) as Class;
super(weakKeys);
}
public function addValue(key:Object, value:*):void {
if(_type == getDefinitionByName(getQualifiedClassName(value))){
this[key] = value;
}else{
trace('failed type match')
}
}
public function getValue(key:Object):*{
return this[key];
}
...
var td:TypedDictionary = new TypedDictionary("com.somepackage.myClass", true);
td.addValue("first", new myClass());
var item:myClass = td.getValue("first");
item.someFunction();

Flex : dynamically created series doesnt show on the chart?

I have the follow class :
package my.controls.charts.series
{
import mx.charts.series.LineSeries;
import mx.collections.ArrayCollection;
import mx.graphics.SolidColorStroke;
import my.controls.charts.ICommonCharts;
public class TimeLineSeries extends LineSeries implements ICommonCharts
{
[Bindable]
protected var dataProviderLineSeries : ArrayCollection;
public var rawData : Array;
public function TimeLineSeries( seriesName : String )
{
super();
this.displayName = seriesName;
this.yField = "value";
this.xField = "dateBegin";
this.sortOnXField = true;
this.filterData = true;
this.setStyle( "form", "segment" );
var stroke : SolidColorStroke = new SolidColorStroke();
stroke.color = 0xFF0000;
stroke.weight = 1;
this.setStyle( "lineStroke", stroke );
rawData = new Array();
dataProviderLineSeries = new ArrayCollection();
this.dataProvider = dataProviderLineSeries;
}
public function Clear() : void
{
rawData = [];
dataProviderLineSeries.removeAll();
}
public function ApplyData() : void
{
dataProviderLineSeries.removeAll();
dataProviderLineSeries = new ArrayCollection( rawData );
dataProviderLineSeries.refresh();
}
}
}
on the application i am trying the follow :
dinamicSeries : Array = new Array();
mySeries : TimeLineSeries = new TimeLineSeries( 'chronos' );
mySeries.rawData = randomData(); // it is a function which gain some random data
mySeries.ApplyData();
dinamicSeries.push( mySeries );
mainChart.series = dinamicSeries;
The new series name appear on the chart, but the data doest, and the chart always remains blank.
- What wrong I am doing ?
Did you affect a vertical axis to your newly created series ?
You need to make public var rawData into a getter/setter pair, so you can populate the ArrayCollection with it. So:
protected var _rawData:Array;
public function get rawData():Array {
return _rawData;
}
public function set rawData(value:Array):void {
if (value != _rawData) {
_rawData = value;
dataProviderLineSeries.source = value;
}
}

undefined method in object?

I get an error when I want to compile the following code...
I get undefined method when I'm trying to set a variable with the Filters class..
trace(filters.txt()); // returns undefined method
trace(filters); // returns [object Filters]
but I'm using this same object in other scripts without problems?
package player {
import flash.display.Sprite;
import filters.Filters;
public class Time_bar extends Sprite {
private var bar = null;
public var color = null;
public var _w = 0;
public var _h = 0;
public var _x = 0;
public var _y = 0;
public function Time_bar(){
this.bar = new Sprite();
addChild(this.bar);
}
public function cnstr(){
this.bar.graphics.beginFill('0x'+this.color);
this.bar.graphics.drawRect(0, 0, this._w, this._h);
this.bar.graphics.endFill();
this.bar.x = this._x;
this.bar.y = this._y;
this.bar.alpha = 0.75;
this.bar.scaleX = 0;
var filters = new Filters();
trace(filters);
trace(filters.txt());
//filters.txt(this.bar);
}
public function progress(float){
this.bar.scaleX = float;
}
}
}
the Filters class looks like this:
package filters {
import flash.display.Sprite;
import filters.Filters_glow;
public class Filters extends Sprite {
private var Glow = new Filters_glow();
public function txt(instance){
Glow.color = '93fafe';
instance.filters = [Glow.filter()];
}
public function loader(instance){
Glow.color = '93fafe';
Glow.alpha = 0.5;
instance.filters = [Glow.filter()];
}
}
}
Filter_glow:
package filters {
import flash.filters.GlowFilter;
public class Filters_glow {
public var color = '000000';
public var alpha = 0.25; // range: 0-1
public var blurX = 4; // range: 0-255; optimized values: 2,4,8,16 etc
public var blurY = 4; // range: 0-255; optimized values: 2,4,8,16 etc
public var strength = 1; // range: 0-255
public var quality = 3; // range: 0-15
public var inner = false;
public var knockout = false;
public function filter(){
this.color = '0x'+this.color;
return new GlowFilter(this.color, this.alpha, this.blurX, this.blurY, this.strength, this.quality, this.inner, this.knockout);
}
}
}
var _filters = new Filters();
_filters.txt(this.bar);
aparently filters is a reserved property name.. after changing filters to _filters the error disapeared :)
To verify whether the method "txt" exists on the filters object you'd have to write trace(filters.txt);. Instead you're executing the txt-method with a missing parameter by adding the brackets. And while executing, it tries to access instance which is undefined. I agree with Matti though that the error message should say something else.
As to why filters.txt(this.bar); doesn't work, I suspect the problem lies elsewhere, can you include the invoking code and the Filters_glow class?
The error is clearly visible. You are not passing the only required argument to the function txt.
public function txt(instance){
Glow.color = '93fafe';
instance.filters = [Glow.filter()];
}
So you can only call txt function by passing it an instance even. something like:
trace(filters.txt(YourObject));
I assume the argument is an instance of the object you want to apply the filter to or something like that. Well it's your function...
try modifying your code as follows, this might help with the error:
//...
public class Filters extends Sprite {
private var Glow: Filters_glow;
public function Filters(){
Glow = new Filters_glow();
}
public function txt(instance: DisplayObject = null): Boolean{
if(!instance){
return false;
}
Glow.color = '93fafe';
instance.filters = [Glow.filter()];
return true;
}
//...

In ActionScript 3, tracing all properties of a value object

I have a number of value objects and I want to be able to create a function within it to trace out the properties and the values without specifying them directly. It will allow me to use the same code in all value objects as opposed to referring to variables within the value object. Ideally, I would like to replace the code in blogURLVars with this code.
Here's a sample value object
package items {
public class Blog {
private var _itemID:uint;
private var _blogTitle:String;
private var _blogText:String;
private var _blogCreated:String;
private var _blogCategory:String;
private var _blogFrontpage:Boolean;
public function Blog (itemID:uint,blogTitle:String,blogText:String,blogCategory:String,blogCreated:String,blogFrontpage:Boolean=false) {
_itemID = itemID;
_blogTitle = blogTitle;
_blogText = blogText;
_blogCreated = blogCreated;
_blogCategory = blogCategory;
_blogFrontpage = blogFrontpage;
}
public function get itemID():uint {
return _itemID;
}
public function get blogTitle():String {
return _blogTitle;
}
public function get blogText():String {
return _blogText;
}
public function get blogCategory():String {
return _blogCategory;
}
public function get blogCreated():String {
return _blogCreated;
}
public function get blogFrontpage():Boolean {
return _blogFrontpage;
}
public function toString():void {
}
public function blogURLVars():String {
var s:String;
s = "itemID="+ _itemID;
s += "blogTitle="+ _blogTitle;
s += "blogText="+ _blogText;
s += "blogCategory="+ _blogCategory;
s += "blogCreated="+ _blogCreated;
s += "blogFrontpage="+ _blogFrontpage;
return s;
}
}
}
DescrybeType could be of help here. I'm basing this answer in this other answer (you might want to check it out): Fastest way to get an Objects values in as3
Basically, the describeType function will let you inspect the public interface of your object. That means public variables, getter/setters and methods (plus some other info not relevant to your problem). So you get a list of all the getters and with that, return the names of said properties plus their actual values for a given object. Not that this is not exactly the same as your sample code, since this will not use the private variables, but rather will call the getters.
In code, this could be something like this (based on code in the linked question).
package {
import flash.net.URLVariables;
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
public class PropertiesHelper {
public function PropertiesHelper() {
}
private static var typePropertiesCache:Object = {};
public static function getPropertyNames(instance:Object):Array {
var className:String = getQualifiedClassName(instance);
if(typePropertiesCache[className]) {
return typePropertiesCache[className];
}
var typeDef:XML = describeType(instance);
trace(typeDef);
var props:Array = [];
for each(var prop:XML in typeDef.accessor.(#access == "readwrite" || #access == "readonly")) {
props.push(prop.#name);
}
return typePropertiesCache[className] = props;
}
public static function getNameValuePairs(instance:Object):URLVariables {
var props:Array = getPropertyNames(instance);
var vars:URLVariables = new URLVariables();
for each(var prop:String in props) {
vars[prop] = instance[prop];
}
return vars;
}
}
}
Use:
var blog:Blog = new Blog(1,"title&","text","cat","created");
var urlVars:URLVariables = PropertiesHelper.getNameValuePairs(blog);
trace(urlVars);
I'm using a URLVariables object since it seems that's what you want (though not actually what you blogURLVars method does), but you could change that in the getNameValuePairs method to suit your needs if necessary. An advantage of using a URLVariables object is that it handles the url-encoding for you automatically, so reserved characters such as &, =, etc, should not be a problem.