instantiate class objects from array values in AS3 - arrays

Am trying to create new instances of classes in a loop where the class instance names have been defined in an array. how Do i turn the array values from string to objects? here's what i have written so far
var tiles2:Array = new Array("e1", "e2", "e3", ...);
for (var i = 0; i < tiles2.length; i++){
if (i == 0){
xPos = 18;
}else if (xPos > 0 && xPos < maxGridWidth){
xPos =+ xPos + objWidth + horGap;
//trace(xPos);
}else{
xPos = 18;
yPos =+ yPos + verGap + objHeight;
}
var this[tiles2[i]] = new tiles2[i];
this[tiles2[i]].name = tiles2[i];
this[tiles2[i]].x = xPos;
this[tiles2[i]].y = yPos;
tileArray[i] = this[tiles2[i]];
addChild(this[tiles2[i]]);
}
This is where I have a problem var mc = new tiles2[i];. the desired output am looking is something like
var e1 = new e1;
e1.name = tiles2[i];
e1.x = xPos;
e1.y = yPos;
tileArray[i] = e1;
addChild(e1);
if you have a better procedure for doing this i will be glad if you can show me

I believe you are looking for this...
// If tiles2[i] is a string that is the name of a class
var type:Class = getDefinitionByName(tiles2[i]) as Class;
var thing = new type();
// If tiles2[i] is a string instance name for an existing object:
var thing:DisplayObject = getChildByName(tiles[i]);
OR, perhaps you just need to change the line in question to this:
//var mc = new tiles2[i]; <-- line in question
//take out the var, and instantiate the proper class
this[tiles2[i]] = new e1();

Related

How do you make buttons that have a specific length?

I'm having difficulty using a customlistrenderer class and homescreen class.
Here's my Homescreen class that contains the function generateData(), which is supposed to display a scroller of 22 buttons.
private function generateData(): void{
var list: List = new List();
list.width = 235;
list.height = 380;
list.name = "HomeScreenList";
this.addChild(list);
var rows:int = 6;
var iterator:int = 0;
var num:int = 22;
var counter:int = 0;
var obj:Object;
var heroName:Array = ["ana", "bastion", "d.va", "genji", "hanzo", "junkrat", "lucio",
"mccree", "mei", "mercy", "pharah", "reaper", "reinhardt", "roadhog", "soldier76", "symmetra",
"torbjorn", "tracer", "widowmaker", "winston", "zarya", "zenyatta"];
var temp:Array = []
obj = new Object();
while(iterator < rows){
obj.name1 = heroName[counter];
obj.image1 = myResource.getImage(heroName[counter]);
obj.name2 = heroName[counter+1];
obj.image2 = myResource.getImage(heroName[counter+1]);
obj.name3 = heroName[counter+2];
obj.image3 = myResource.getImage(heroName[counter+2]);
obj.name4 = heroName[counter+3];
obj.image4 = myResource.getImage(heroName[counter+3]);
temp.push(obj);
counter+4;
iterator++;
}
var collection:ListCollection = new ListCollection(temp);
//assign the renderer
list.itemRendererType = CustomMenuListRenderer;
list.dataProvider = collection;
list.addEventListener(Event.CHANGE, onChange);
this.addChild(list);
list.validate();
}
and the CustomMenuListRenderer class, under the initialize() function
super.initialize();
firstButton = new Button();
this.addChild(firstButton);
firstButton.x = 20;
firstButton.y = 100;
firstButton.scale = 0.60;
secondButton = new Button();
secondButton.x = 92;
secondButton.y = 100;
secondButton.scale = 0.60;
thirdButton = new Button();
thirdButton.x = 163;
thirdButton.y = 100;
thirdButton.scale = 0.60;
fourthButton = new Button();
fourthButton.x = 235;
fourthButton.y = 100;
fourthButton.scale = 0.60;
firstButton.addEventListener(Event.TRIGGERED, onTrigger);
secondButton.addEventListener(Event.TRIGGERED, onTrigger);
thirdButton.addEventListener(Event.TRIGGERED, onTrigger);
fourthButton.addEventListener(Event.TRIGGERED, onTrigger);
The problem is since the loop displays the 4 buttons each loop, an error occurs at the 23rd button(since I only specified 22 buttons but I declared 4 buttons on the CustomMenuListRenderer class) in the 6th row.
My question is how do I fix this issue?
First question, why define num manually and not use heroName.lenght? Is more secure
var heroName:Array = ["ana", "bastion", "d.va", "genji", "hanzo", "junkrat", "lucio",
"mccree", "mei", "mercy", "pharah", "reaper", "reinhardt", "roadhog", "soldier76", "symmetra",
"torbjorn", "tracer", "widowmaker", "winston", "zarya", "zenyatta"];
var num:int = heroName.lenght;
To fix your error, you have to check is heroName index exists before to get it.
Something like :
obj = new Object();
while(iterator < rows){
var objCounter:int = 1;
while(objCounter <= 4 )
{
if( counter < heroName.lenght )
{
obj["name"+objCounter] = heroName[counter];
obj["image"+objCounter] = myResource.getImage(heroName[counter]);
}
objCounter++;
counter++;
}
temp.push(obj);
iterator++;
}

AS3 - Auto refreshing display after updating array

So, basically I'm reinventing the wheel by trying to make a sort of spreadsheet in flash for tracking member growth in a game. In this one section I'm adding member names to an array and then placing the names into dynamically created tiles with text fields attached to display the name.
I have a save button which saves the array, and if I save, close, and reopen, then I can see the members I have added. However, I would like it to refresh the stage as soon as the array is changed to reflect the changes made (update the spreadsheet). I will also be adding and removing other tiles dynamically, but I can extrapolate the solution to this problem to all of those later.
Here's the code I have to add members and create the display:
public var mainArray:Array = new Array;
public var i1:Number = 0;
public var memberBox:MovieClip = new MovieClip();
public var MAX_ROWS = 0;
public var MAX_COLS = 0;
public function Tracker() {
MAX_COLS = mainArray.length - 1;
addBtn.addEventListener(MouseEvent.CLICK, addFun); //atchaed to button on stage
public function addFun($e:MouseEvent):void{
mainArray[i1] = [];
mainArray[i1][0] = addNameTxt.text //attached to textfield on stage
i1++;
loadMembers();
public function loadMembers():void{
var multiDimensionalArray:Array = new Array();
//initalize the arrays
for (var row = 0; row <= MAX_ROWS; row++)
{
var boolArray:Array = new Array();
for (var col = 0; col <= MAX_COLS; col++){
boolArray.push(false);
}
multiDimensionalArray.push(boolArray);
}
//now we can set the values of the array as usual
for (var row = 0; row <= MAX_ROWS; row++)
{
for (var col = 0; col <= MAX_COLS; col++){
multiDimensionalArray.push(1); ;
}
}
//create a column of tiles based on mainArray length with a textfield attached to each
buildLevel(multiDimensionalArray);
}
public function buildLevel(s:Array){
var txtArray:Array = new Array();
memberBox.name = "tileHolder";
for(var i=0; i < MAX_ROWS + 1; i++){
for(var o=0; o < MAX_COLS + 1; o++){
var currentTile:MemberBox = new MemberBox();
currentTile.x = i*150;
currentTile.y = o*25;
currentTile.name = "b"+o;
memberBox.addChild(currentTile);
//currentTile.gotoAndStop(int(s[o][i]));
var memberTxt:TextField=new TextField();
currentTile.addChild(memberTxt);
memberTxt.width = 150;
memberTxt.height = 25;
txtArray[o] = memberTxt;
txtArray[o].text = mainArray[o][0];
}
}
memberBox.x = 60;
memberBox.y = 170;
addChild(memberBox);
}
}
The ideal solution would be to attach event listeners to the Array, however, Arrays don't fire events.
Solution #1: Managed Updates
Rather than allowing any piece of code to modify your array directly, write a function that handles updating your array. This way, you can know when to update the display at the same time.
public var mainArray:Array = new Array;
public var i1:Number = 0;
public var memberBox:MovieClip = new MovieClip();
public var MAX_ROWS = 0;
public var MAX_COLS = 0;
public function Tracker() {
MAX_COLS = mainArray.length - 1;
addBtn.addEventListener(MouseEvent.CLICK, addFun); //attached to button on stage
public function addFun(e:MouseEvent):void {
mainArray[i1] = [];
mainArray[i1][0] = addNameTxt.text //attached to textfield on stage
i1++;
loadMembers();
}
public function loadMembers():void {
var multiDimensionalArray:Array = new Array();
//initalize the arrays
for (var row = 0; row <= MAX_ROWS; row++) {
var boolArray:Array = new Array();
for (var col = 0; col <= MAX_COLS; col++) {
boolArray.push(false);
}
multiDimensionalArray.push(boolArray);
}
//now we can set the values of the array as usual
for (var row = 0; row <= MAX_ROWS; row++) {
for (var col = 0; col <= MAX_COLS; col++) {
multiDimensionalArray.push(1); ;
}
}
//create a column of tiles based on mainArray length with a textfield attached to each
buildLevel(multiDimensionalArray);
}
public function buildLevel(s:Array) {
var txtArray:Array = new Array();
memberBox.name = "tileHolder";
for (var i:int = 0; i < MAX_ROWS + 1; i++) {
for(var o=0; o < MAX_COLS + 1; o++) {
var currentTile:MemberBox = new MemberBox();
currentTile.name = i + "_" + o;
currentTile.x = i*150;
currentTile.y = o*25;
memberBox.addChild(currentTile);
//currentTile.gotoAndStop(int(s[o][i]));
var memberTxt:TextField=new TextField();
currentTile.addChild(memberTxt);
memberTxt.width = 150;
memberTxt.height = 25;
txtArray[o] = memberTxt;
txtArray[o].text = mainArray[o][0];
}
}
memberBox.x = 60;
memberBox.y = 170;
addChild(memberBox);
}
public function modifyArray(row:int, col:int, value:*):void {
// Update our array.
mainArray[row][col] = value;
// Update our tile.
var tile:MemberBox = memberBox.getChildByName(row + "_" + col);
tile.getChildAt(0).text = value;
}
}
When you actually modified your array, you'd do that with your function, rather than a direct mainArray[o][i] approach.
// Instead of this
mainArray[o][i] = "foo";
// You'd do this
modifyArray(o, i, "foo");
Update: I'm not sure how better to explain this, so I've posted working example that you can view. It contains the class, and the document code, the fla, and the swf with working updates to the spreadsheet. Let me know if that resolves the issue: SpreadSheet Test # Dropbox
Solution #2: Poll for Changes
Hold two versions of your array in memory. The first is the one you're actively editing, the second is an untouched duplicate to compare against the first. Every so often (once per second?) you iterate over the entire dataset and look for differences. When one is found, update the duplicate array and the displayed spreadsheet.
Here's an example of how you'd do that:
import flash.utils.*;
var last:Number = flash.utils.getTimer();
this.addEventListener("enterFrame", checkData);
var foo:Array = ["a", "b", "c"];
var fooBackup:Array = [];
function update():void {
var txt:TextField;
for (var i:int = 0; i < foo.length; i++) {
// If we don't have a representation of this index, create one.
if (!this.getChildByName("tile"+i)) {
txt = new TextField();
txt.name = "tile" + i;
txt.text = foo[i];
this[txt.name] = txt;
addChild(txt);
txt.y = i * 20;
}
// Update the data if inconsistent.
txt = this.getChildByName("tile"+i) as TextField;
if (fooBackup.hasOwnProperty(i) == false || foo[i] != fooBackup[i]) {
fooBackup[i] = foo[i]
txt.text = foo[i];
trace("Index " + i + " changed. Updated backup, and display.");
}
}
}
function checkData(e:Event):void {
var now:Number = flash.utils.getTimer();
// If the last time we checked is greater than a second, run the check again.
if (now - last > 1000) {
// Update last checked index;
last += 1000;
// For the sake of argument, let's randomly change an index to a random value.
foo[random(0, foo.length-1)] = random(-1000, 1000);
update();
}
}
function random(low:Number=0, high:Number=1):Number {
/* Returns a random number between the low and high values given. */
return Math.floor(Math.random() * (1+high-low)) + low;
}
Solution #3: Roll your own Array
As outlined by Adobe's Extending the Array class, you can subclass Arrays and from there add your own event dispatches when you add/remove entries. This is the more adventurous solution, and (in my humble opinion) the best as it maintains code consistency, while giving broad and efficient powers.

Trying to access the first instance of an array in Actionscript 3

I am trying to do deat detection in actionscript 3. My idea is to create an array of dots (MovieClips) on the x axis which represents the frequency spectrum, SoundMixer.computeSpectrum(bytes, true, 0); is set to true. How do I access the first dot instance of my array. I then want to check it's highest value on each current frame and and measure it against the last value. I think I need to set a threshold and when the value is within the threshold call that a beat....I'm lost, can anybody point me in the right direction..
Thanks in advance.
var snd: Sound = new Sound();
var req: URLRequest = new URLRequest("mySong.mp3");
snd.load(req);
var channel: SoundChannel;
channel = snd.play();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);
const CHANNEL_LENGTH: int = 256;
const BUFFER_LENGTH: int = 512;
var dot:Dot;
dot.cacheAsBitmap = true;
var myArray:Array = new Array();
var bytes:ByteArray = new ByteArray();
function onEnterFrame(event: Event): void
{
SoundMixer.computeSpectrum(bytes, true, 0);
for (var i:int = 0; i < CHANNEL_LENGTH; i+=8) // channel_length = 256
{
var sampleValue:Number = bytes.readFloat();
dot = new Dot();
dot.x = i * 2;
dot.y = sampleValue * 250; //50 + (i * 30)
addChild(dot);
myArray.push(dot);
}
}
I am not sure what excetly you are going to do.
But if you want to do a sound spectrum visualizer, I think your direction is right.
I follow what you do and get result like this: (http://www.imageupload.co.uk/5M3n) Those dots will dance with the music
just move dot.cacheAsBitmap = true; after dot = new Dot(); or you can remove it.
and in Dot class, don't forget to dispose itself after some time.
But actually I dont need to use myArray at all.
Here is my code:
import flash.events.Event;
var snd: Sound = new Sound();
var req: URLRequest = new URLRequest("mySong.mp3");
snd.load(req);
var channel: SoundChannel;
channel = snd.play();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);
const CHANNEL_LENGTH: int = 256;
const BUFFER_LENGTH: int = 512;
var dot:Dot;
var myArray:Array;
var bytes:ByteArray = new ByteArray();
function onEnterFrame(event: Event): void
{
SoundMixer.computeSpectrum(bytes, true, 0);
myArray = [];
for (var i:int = 0; i < CHANNEL_LENGTH; i+=8) // channel_length = 256
{
var sampleValue:Number = bytes.readFloat();
dot = new Dot();
dot.cacheAsBitmap = true;
dot.x = i * 2;
dot.y = sampleValue * stage.StageHeight;
addChild(dot);
myArray.push(dot);
}
var firstElement:Dot = myArray.length>0?myArray[0]:null;
if(firstElement)
{
handleWithFirstElement(firstElement);
}
}
function onPlaybackComplete(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
function handleWithFirstElement(ele:Dot):void
{
//your code
}
And in Dot class:
flash.utils.setTimeout(this.parent.removeChild, 100, this);
// Run this just after added on Stage

Creating array?

I have this class but i wanna make it 2D dimensional Array. And i do not know how to do it...Everyone tells me to create 2D array so i can easy call it and read array...but i found this way of making items.
Now array or gird that will store this times would be helpful.
Any code to transfer this class to an array would be helpful.
Weapon base is Inheriting 2 additional Classes.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RPG
{
class WeaponList
{
private WeaponBase WoodenSword;
private WeaponBase RustySword;
private WeaponBase IronSword;
private WeaponBase SteelSword;
private WeaponBase BoardSword;
private WeaponBase MythrilSword;
private WeaponBase BloodSword;
private WeaponBase CoralSword;
private WeaponBase AncientSword;
public void CreateWeapon()
{
WoodenSword = new WeaponBase();
WoodenSword.ItemName = "Wooden Sword";
WoodenSword.ItemDescription = "A basic traning sword...can do some damage";
WoodenSword.IsStackable = true;
WoodenSword.Attack = 4;
WoodenSword.WeaponType = WeaponBase.WeaponTypes.Sword;
WoodenSword.ItemID = 1;
WoodenSword.Price = 10;
RustySword = new WeaponBase();
RustySword.ItemName = "Rysty Sword";
RustySword.ItemDescription = "Old rusty sword....still better than wooden one";
RustySword.Attack = 5;
RustySword.IsStackable = true;
RustySword.WeaponType = WeaponBase.WeaponTypes.Sword;
RustySword.ItemID = 2;
RustySword.Price = 50;
IronSword = new WeaponBase();
IronSword.ItemName = "Iron Sword";
IronSword.ItemDescription = "This sword has a broad and sturdy blade, but its iron construction makes it very heavy.";
IronSword.IsStackable = true;
IronSword.Attack = 6;
IronSword.WeaponType = WeaponBase.WeaponTypes.Sword;
IronSword.ItemID = 3;
IronSword.Price = 100;
SteelSword = new WeaponBase();
SteelSword.ItemName = "Steel Sword";
SteelSword.ItemDescription = "Hardend version of iron sword";
SteelSword.IsStackable = true;
SteelSword.Attack = 7;
SteelSword.WeaponType = WeaponBase.WeaponTypes.Sword;
SteelSword.ItemID = 4;
SteelSword.Price = 500;
BoardSword = new WeaponBase();
BoardSword.ItemName = "Borad Sword";
BoardSword.ItemDescription = "This broad-bladed sword is suited for large slashing strokes. It is inexpensive, but not particularly powerful. ";
BoardSword.IsStackable = true;
BoardSword.Attack = 8;
BoardSword.WeaponType = WeaponBase.WeaponTypes.Sword;
BoardSword.ItemID = 5;
BoardSword.Price = 800;
MythrilSword = new WeaponBase();
MythrilSword.ItemName = "Mythril Sword";
MythrilSword.ItemDescription = "A sword forged from the metal known as mythril. Its brilliantly shining blade is incredibly lightweight.";
MythrilSword.IsStackable = true;
MythrilSword.Attack = 10;
MythrilSword.WeaponType = WeaponBase.WeaponTypes.Sword;
MythrilSword.ItemID = 6;
MythrilSword.Price = 1600;
BloodSword = new WeaponBase();
BloodSword.ItemName = "Blood Sword";
BloodSword.ItemDescription = "The blade of this sword is a deep crimson, as if it were drenched in blood. It is cruelly sharp.";
BloodSword.IsStackable = true;
BloodSword.Attack = 8;
BloodSword.WeaponType = WeaponBase.WeaponTypes.Sword;
BloodSword.ItemID = 7;
BloodSword.Price = 1400;
BloodSword.specialAttack = "Drains Foe's HP";
CoralSword = new WeaponBase();
CoralSword.ItemName = "Coral Sword";
CoralSword.ItemDescription = "The handle of this single-edged sword has been decorated with intricate coral piecework.";
CoralSword.IsStackable = true;
CoralSword.Attack = 11;
CoralSword.WeaponType = WeaponBase.WeaponTypes.Sword;
CoralSword.ItemID = 8;
CoralSword.Price = 2200;
CoralSword.specialAttack = "Element: Thunder";
AncientSword = new WeaponBase();
AncientSword.ItemName = "Ancient Sword";
AncientSword.ItemDescription = "A sword constructed using ancient techniques that have long since perished from the world.";
AncientSword.IsStackable = true;
AncientSword.Attack = 11;
AncientSword.WeaponType = WeaponBase.WeaponTypes.Sword;
AncientSword.ItemID = 9;
AncientSword.Price = 3300;
}
}
}
Well I'm not sure what you're exactly doing, but making a 2D Array is quite simple:
int[,] MyArray = new int[3,4];
// Access like this:
MyArray[0,0] = 1;
MyArray[0,1] = 2;
MyArray[0,2] = 3;
// Etc...
// To Populate using a For Loop:
int i = 0;
for(int x=0; x < 3; x++)
for(int y=0; y < 4; y++)
{
i++;
MyArray[x, y] = i;
}
And that's how you make a 2D Array.
Edit:
Making it for a class is a similar process:
MyClass[,] MyArray = new MyClass[3,4];
// Access like this:
MyClass[0,0] = new MyClass();
MyClass[0,1] = new MyClass();
MyClass[0,2] = new MyClass();
// Etc...
// To Populate using a For Loop:
for(int x=0; x < 3; x++)
for(int y=0; y < 4; y++)
{
MyClass[x, y] = new MyClass();
}
As you can see making a 2D Array for a class is pretty much the same.
I suggest this way (vb-pseudo code).
Class WeaponBase
ItemName
ItemDescription
IsStackable
...
End Class
Class Weapons
inherits list (of WeaponBass)
Sub CreateWeapon
' here i will read data from XML or JSON instead of this below
w = new WeaponBase();
w.ItemName = "Wooden Sword";
w.ItemDescription = "A basic traning sword...can do some damage";
w.IsStackable = true;
add(w)
w = new WeaponBase();
w.ItemName = "Metal Sword";
w.ItemDescription = "A basic traning sword...can do some damage";
w.IsStackable = true;
add(w)
End Sub
Sub CreateNewItem(_name, _desc, _stackable)
w = new WeaponBase();
w.ItemName = _name;
w.ItemDescription = _desc;
w.IsStackable = _stackable;
add(w)
End Sub
End Class
and now you have a list of weapons that you can easily access and do whatevery you wish.

as3 how to remove graphics from removed nape bodies

i have attached multiple instances of a moviecCip to multiple nape bodies and have a reset button to restore them to their original position. when the reset function is called the bodies are reset and have the mc attached to them. the problem is the original mc are still on the stage frozen in the position thy were when reset was called.
private var brickGraphic:MovieClip = new Brick();
private var brickArray:Array;
private function setUp():void
{
var brickType:CbType = new CbType();
var w:int = stage.stageWidth;
var h:int = stage.stageHeight;
var ag:int = stage.stageHeight - 58;// height ofarea above ground
brickArray = new Array ;
//wall
for (var i:int = 0; i < 10; i++)
{
var brick:Body = new Body(BodyType.DYNAMIC);
var brickShape:Polygon = new Polygon(Polygon.box(10,25));
var brickGraphic:MovieClip = new Brick();
brickGraphic.width = 10;
brickGraphic.height = 25;
addChild(brickGraphic);
brickGraphic.cacheAsBitmap = true;
brick.shapes.add(brickShape);
brick.position.setxy(450, ((ag ) - 30 * (i + 0.5)));
brick.angularVel = 0;
brick.shapes.at(0).material.elasticity = .5;
brick.shapes.at(0).material.density = 150;
brick.cbTypes.add(brickType);
brick.space = space;
brickGraphic.stop();
brick.userData.sprite = brickGraphic;
brick.userData.sprite.x = brick.position.x;
brick.userData.sprite.y = brick.position.y;
this.brickArray.push(brick);
}
}
private function reset():void
{
space.clear();
setUp();
}
any help would be greatly appreciated
Add a statement that will remove that linked MovieClip from those nape bodies into your reset() function. I expect this is what you need:
private function reset():void
{
if (contains(brick.userData.sprite)) removeChild(brick.userData.sprite);
space.clear();
setUp();
}

Resources