[AS3]Accessing data from a Vector of Arrays

Subscribe to [AS3]Accessing data from a Vector of Arrays 19 posts

avatar for Mond Mond 749 posts
Flag Post

I am creating a data structure so I can pass a few parameters to a function…

public class CodeExplosionData extends Array
{
	public function CodeExplosionData(	typeOfExplosion:int = 0,	//type of explosion
						numOfSectors:Number = 6,	//number of sectors
						amplitude:Number = 0.0,		//maximum amplitude
						minAmplitudePercentage:Number = 0.5,//minumum amplitude as a percentage of maximum amplitude
						numOfStepsInExplosion:int = 15,	//number of steps
						theColor:uint = 0xFFFFFF,	//the fillcolor																
						theAlpha:Number = 1.0,		//the beginning alpha of the fill and strokes
						beginFadeAtThisStep:int = 10,	//begin fading the alpha of the Sprite at this step
						withStrokes:Boolean = true,	//include strokes
						strokeColor:uint = 0xFFFFFF,	//stroke color
						strokeSize:Number = 1.0,	//stroke size
						modNum:int = 1,			//modulus number decides when to clear graphics
						reverseControlPoints:int = 1000,//reverse control point amplitude at this step
						reverseEndPoints:int = 1000,	//reverse end point amplitude at this step
						stopControlPoints:int = 1000,	//stop control point amplitude at this step
						stopEndPoints:int = 1000):void 	//stop end point amplitude at this step
	{
		this.push(typeOfExplosion);		//[0]
		this.push(numOfSectors);		//[1]
		this.push(amplitude);			//[2]
		this.push(minAmplitudePercentage);	//[3]
		this.push(numOfStepsInExplosion);	//[4]
		this.push(theColor);			//[5]
		this.push(theAlpha);			//[6]
		this.push(beginFadeAtThisStep);		//[7]
		this.push(withStrokes);			//[8]
		this.push(strokeColor);			//[9]
		this.push(strokeSize);			//[10]
		this.push(modNum);			//[11]
		this.push(reverseControlPoints);	//[12]
		this.push(reverseEndPoints);		//[13]
		this.push(stopControlPoints);		//[14]
		this.push(stopEndPoints);	        //[15]
	}
}

And I used this code to check it out….

var testArray:Vector.<CodeExplosionData> = new Vector.<CodeExplosionData>();
testArray.push(new CodeExplosionData(0, 8, 60.0, 0.2, 30, 0xFB8062, 0.7, 20, true, 0xEEEEEE, 1.0, 3, 1000, 1000, 18, 1000));
trace(testArray[0][3]);

But I am getting a…

[Fault] exception, information=ReferenceError: Error #1069: Property 3 not found on CodeExplosionData and there is no default value.

from the trace statement. And that is true, there is no property called 3 on an instance of the CodeExplosionData Class. Is my syntax incorrect…I was expecting the trace to output 0.2

 
avatar for Draco18s Draco18s 6860 posts
Flag Post

When you extend array, you don’t get the array access ability (e.g. myExtendedArray[0]). Sorry.

 
avatar for Mond Mond 749 posts
Flag Post

I can’t do this = new this(); in the constructor?……lol, damn!

EDIT:What about calling super(); to get the Array Constructor to run?

 
avatar for Ace_Blue Ace_Blue 1091 posts
Flag Post

This code looks very clumsy and cumbersome.

public class Explosion
{
    public var type:int;
    public var sectors:Number;
    public var amplitude:Number;
    public var minAmplitudeFraction:Number;
    public var maxStep:int;
    public var currentStep:int;
    public var color:uint;
    public var alpha:uint;
    public var beginFadeStep:int;
    public var hasStrokes:Boolean;
    public var strokeColor:uint;
    public var strokeSize:Number;
    public var clearingModulus:int;
    public var reverseControlStep:int;
    public var reverseEndStep:int;
    public var stopControlStep:int;
    public var stopEndStep:int;
}

That’s it. That’s all you need. Whoever needs to create explosions just goes:

my_explo = new Explosion();
my_explo.type = 3; // or what-have-you
my_explo.alpha = 1.0;
// same with other variables.
// Once it's all set up, assign it in the proper Vector and _voila_, you're done!

It really cannot get much simpler than this. Incidentally, I was appalled by your calling your Vector ‘testArray’. Are you trying to confuse yourself?

 
avatar for Mond Mond 749 posts
Flag Post

Thanks Blue…that was funny.

There was a discussion a while back about limiting parameters on function calls to just a few…maybe 5 tops. (I never understood why the number of parameters should be limited since I think of them as just RAM locations being pushed onto the stack and popped off when the function needs the data from RAM…and pushing and popping from a stack must be incredibly fast…anyhow…)

I like addChild(new CodeExplosion(bunch of parameters right here));….it makes my code much neater and sophisticated. But I only want to pass three parameters…x position, y position and an instance of CodeExplosionData.

EDIT:I understand what you mean Blue..but I wanted to avoid having to reach into the properties of a CodeExplosionData instance to get the data. It seems like (common sense wise) that once I had to reach into properties like that I would be slowing down my game…and would be better off just passing the 17 parameters to CodeExplosion in the first place.

 
avatar for BobTheCoolGuy BobTheCoolGuy 3757 posts
Flag Post

My guess would be that limiting the number of parameters in a function is more about readability, maintainability, and design than performance.

You could always just take an Object of options, as described here. Be sure to read the comments though, nothing wrong with your way in my opinion.

 
avatar for Mond Mond 749 posts
Flag Post

I avoid using Objects as Associative Arrays because the dynamic properties assigned to the Object (which are the keys used to get data from a key:data pair) are treated as Strings (as far as I know). Making it the slowest form of property access there is.

The flexibility is awesome though.

 
avatar for NineFiveThree NineFiveThree 1370 posts
Flag Post
Originally posted by Mond:

What about calling super(); to get the Array Constructor to run?

What about rtfm if you want to extend Array?

 
avatar for Mond Mond 749 posts
Flag Post

Hey….my first dynamic Class…thanks 953. If I can ever figure out what “implements” means I might be a programmer one day…woo hoo!

 
avatar for Ace_Blue Ace_Blue 1091 posts
Flag Post
Originally posted by Mond:

Thanks Blue…that was funny.

There was a discussion a while back about limiting parameters on function calls to just a few…maybe 5 tops. (I never understood why the number of parameters should be limited since I think of them as just RAM locations being pushed onto the stack and popped off when the function needs the data from RAM…and pushing and popping from a stack must be incredibly fast…anyhow…)

I like addChild(new CodeExplosion(bunch of parameters right here));….it makes my code much neater and sophisticated. But I only want to pass three parameters…x position, y position and an instance of CodeExplosionData.

EDIT:I understand what you mean Blue..but I wanted to avoid having to reach into the properties of a CodeExplosionData instance to get the data. It seems like (common sense wise) that once I had to reach into properties like that I would be slowing down my game…and would be better off just passing the 17 parameters to CodeExplosion in the first place.

Yes, accumulating function parameters makes the code difficult to read, understand, maintain and expand. Since your class is just a repository for information and does nothing else, just open access to it and let the good times roll. Calling out object properties is not the huge slowdown you’re making it out to be, especially since you’d otherwise have to retrieve the value from an Array, so you’re doing data retrieval in both cases.

Regarding your middle paragraph… How do I say this gently? Words fail me.
OK. Deep breaths. So, a bunch of parameters is not neat, and it’s not sophisticated. It’s ugly Ugly Ugly. I bet half of those parameters are hard-coded magic numbers, too. And why in the world would you not include x and y in your CodeExplosionData Class? Or better yet, fold all of that stuff into the CodeExplosion Class which, unless your game contains other kinds of explosions, should really be the Explosion Class, because it being code is pretty much a given.

It’s amazing to me that you consider “passing the 17 parameters to [the constructor]” to be something you “would be better off” with. I can’t think of a lot of things worse than passing 17 (seventeen!) parameters to a function, and all of them involve physical pain.

 
avatar for Mond Mond 749 posts
Flag Post

I already had a MovieClip in a .swc called Explosion so I couldn’t use that name. Just writing a class like CodeExplosions was a challenge for me. It has so much capability and flexibility that I couldn’t run all the possible combinations of parameters. Especially when I throw in all the possible fillcolors.

17 parameters on every call was UGLY…that’s why I wanted CodeExplosionData. My intent was to specify most of the criteria for CodeExplosion(s) into a Vector…instantiating all of that before gameplay…all that was left were the x and y coordinates.

omg…talk about physical pain…I just spent three months learning Blender.

 
avatar for BobTheCoolGuy BobTheCoolGuy 3757 posts
Flag Post

If all 17 arguments have default values, I’m not necessarily against it. The most important configurations should be in the beginning, and the least in the end. You could perhaps truncate the constructor to 5 or 6 parameters, and simply set the other ones as Ace_Blue suggested.

 
avatar for NineFiveThree NineFiveThree 1370 posts
Flag Post
Originally posted by Mond:

Hey….my first dynamic Class…thanks 953. If I can ever figure out what “implements” means I might be a programmer one day…woo hoo!

First, think about whether it’s a good idea to make that class dynamic.

 
avatar for Ace_Blue Ace_Blue 1091 posts
Flag Post

Considering that it’s fairly likely there will be maybe a handful of different kinds of explosions, the way I would have done it would have been to make all the parameters private, and to have one public function: setup(type:String);. I would also have the authorized types be public, static Strings. This way, say I want a missile explosion. I would add it to my explosion array as:

explosions.push(new Explosion());
explosions[explosions.length].setup(Explosion.MISSILE);

and in the Explosion class:

public static const MISSILE:String = "Missile explosion";
public static const CRATE:String = "Empty crate explosion";
etc...

public  function setup(type:String):void
{
    if (type == MISSILE) setupMissile();
    if (type == CRATE) setupCrate();
    if (type == PANTIES) setupPanties();
etc...
}

private function setupMissile():void
{
    type  = 0;
    alpha = 1;
    segments = 12;
and so on...
}

Now creating a new explosion takes only one parameter, the kind of explosion I want. By keeping the x and y variables inside Explosion public I can place my explosion wherever I want, have it drift with the wind and fall with gravity, not to mention burn the face of the careless player who started it. It’s all encapsulated and nice and easy to use, but most importantly, it doesn’t require me to set up 17 different parameters every time.

Bonus points if you make a Dictionary with the various kinds as keys associated to an Array of parameters for each kind of explosion, so you don’t even have to have the extra functions, you just assign each variable to its corresponding index in the Array (after having checked that ‘type’ does indeed correspond to a key in you Dictionary, of course).

 
avatar for Mond Mond 749 posts
Flag Post

Well…the default values were just so I could concentrate on getting the CodeExplosions Class to work without having to specify all the parameters. I could just write addChild(new CodeExplosion()); for testing purposes.

But some of what you say is true…I find that too many sectors in the explosions will slow my computer down during gameplay. So some of the parameters may not change by much.

 
avatar for BobJanova BobJanova 858 posts
Flag Post

Passing 17 parameters is bad not for code performance reasons, but because it shows poor encapsulation and over-connection of responsibilities between the calling method and the called one. Packing the 17 parameters up into an object does nothing to fix that and adds a small extra layer of obfuscation on top.

Edit regarding Ace_Blue’s suggestion: I would have a class hierarchy of explosions:

class Explosion {
 protected var segments:Int;
 protected var alpha:Number;
 // etc

 protected Explosion() {} // if you can do this in AS3, I forget
}

class MissileExplosion extends Explosion {
 public MissileExplosion(){
  segments = 12;
  alpha = 1;
 }
}

Switching behaviour through polymorphism and inheritance is almost always better than switching on a type variable.

 
avatar for Mond Mond 749 posts
Flag Post

This forum is great. I learn something new every time I come here. Keep it comin’ ya’ll…..

@953..you’re right..I don’t need that Class at all. But I thought I was consolidating the data together in one place. I would only have to make changes in one place…and that was a good thing. It would even be backwards compatible to code already written since CodeExplosions could pick & choose which data to use from the Array. It was sort of like the …rest… parameter.

But I might be committed at this point because I typed up a Code Explosion WorkSheet and made 20 copies.

 
avatar for NineFiveThree NineFiveThree 1370 posts
Flag Post
Originally posted by Mond:

@953..you’re right..I don’t need that Class at all.

The question was not if the class was obsolete, but the dynamic keyword.
It’S quite pointless to create a class that just holds data and type all that data to certain datatypes to match the other class that is going to receive it and make it dynamic.

 
avatar for Ace_Blue Ace_Blue 1091 posts
Flag Post
Originally posted by BobJanova:

Switching behaviour through polymorphism and inheritance is almost always better than switching on a type variable.

That’s absolutely true, but as Popek used to say about playing the violin: “You can play it the gypsy way, or you can play it the right way. I play the gypsy way; I don’t have a choice.”

I use type variables; I don’t have a choice.