AS3 concat // MovieClip(parent).variable.gotoAndStop(otherVariable); - actionscript-3

Is there any concatenation problem in
MovieClip(parent).robes_position_num_clicked.gotoAndStop(traje1);
When I click on item n°2, trace('robes_position_num_clicked') returns "robes_position2", which is correct & what expected.
var index_clicked:int = myPositions.indexOf(e.target); // = Position num in array
var robes_position_num_clicked ="robes_position"+(index_clicked+1).toString();
trace (robes_position_num_clicked);
var traje1 = MovieClip(parent).robes_position1.currentLabel;
if ( MovieClip(parent).robes_position1.currentLabel==traje1 && MovieClip(parent).robes_position1.currentLabel!=null)
{ /*1*/ MovieClip(parent).robes_position2.gotoAndStop(traje1);
/*2*/ MovieClip(parent).robes_position_num_clicked.gotoAndStop(traje1);
MovieClip(parent).robes_position1.gotoAndStop(1);
}
The first "sentence" /* 1*/ does the expected job,
while sentence /* 2*/ which is supposed to be a synonym, doesn't, and returns an error "One term is undefined and has no property".
Thanks for your lights as we say in french !

You should know that robes_position_num_clicked here is just a String containing the name of your target MovieClip and not the MovieClip itself, so this line :
MovieClip(parent).robes_position_num_clicked.gotoAndStop(traje1);
should give you an error.
So, to access your MovieClip using its name, you can simply use the DisplayObjectContainer.getChildByName() function like this :
MovieClip(parent.getChildByName(robes_position_num_clicked)).gotoAndStop(traje1);
you can also do like this :
MovieClip(parent)[robes_position_num_clicked].gotoAndStop(traje1);
Hope that can help.

robes_position_num_clicked is a string not a MovieClip
"gotoAndStop" should be used with MovieClips not Strings ;
secondly: "robes_position_num_clicked" is defined in the current MovieClip not in the parent MovieCLip so it will be null in the parent MovieClip

Related

Arma 3 - addAction with dynamic variables to specific Object

Playing around with custom composition spawning in Arma 3. I am currently using "LARs Composition Spawn Script" (https://forums.bistudio.com/forums/topic/191902-eden-composition-spawning/) to spawn a custom compostion. Spawning compositions around the map works like a charm.
In the composition there is one object (AI) whith varname "quest_giver". To this specific Object I want to add an Action. My current code is:
// SPAWN RANDOM COMPOSITION ON RANDOM POSITION
_spawned_composition = [ _random_composition, _pos, [0,0,0], random 360 ] call LARS_fnc_spawnComp;
// GET OBJECTS FROM THE SPAWNED COMP BACK (ARRAY)
_objects = [_spawned_composition] call LARs_fnc_getCompObjects;
// TRYING TO ITERATE THROUGH OBJECTS TO FIND "quest_giver"
// AND ADD ACTION TO IT.
{
_type = typeName _x;
if (_type == "GROUP") then {
_units = units _x;
{
_var = missionNamespace getVariable ["name", _x];
_name = typeOf _var;
if (_name == "quest_giver") then {
player globalChat format["%1",_name];
//_speak = _x addAction ["Speak", {hint format ["Hello, it works !"]}];
};
} forEach _units;
};
} forEach _objects;
Error at If(_name == "quest_giver") where _name is an OBJECT but "quest_giver" of course a STRING. So I get Error Generic error in expression.
However, _var = missionNamespace getVariable ["name",_x]; returns "quest_giver". But it as an OBJECT, since typeOf _var returns "OBJECT" not STRING.
I just can't figure out the most simpliest thing here I guess. Any idea, if this would even work in theory ?
What I am trying to achieve
Create various custom compositions, where on Object in it is always the "quest_giver". Works so far.
Choose random comp and spawn it on random position in the world. Works so far.
Add action to the quest giver so player can speak to him. Text Pop up with simple text, content would be a random quest ala bring me 5 x Water Bottles.
I know my way around before and after the add action part but can't figure out how to add action to this specific object. ...
unless I'm mistaken, you seem to be confused about how to get the unit's name?
it might be you want to get a name var from the unit's namespace (if the thing you're using does put it there):
_name = _x getVariable ["name" /*var name*/, "" /*default value*/];
if (_name == "quest_giver") then {
//...
or more likely (if it's about the name set via editor) with the name function:
if ((name _x) == "quest_giver") then {

AS3 event.target and var

I have an editable text field (c) in a movieClip, well 3 movielips like this actually named a1, a2 and a3. Movieclips are already on stage. The path to text field in each MC is mc.a1.c, mc.a2.c and mc.a3.c
The initial value for each textfield is set by XML which is also stored in variables with the same names and the movieclip(a1,a2,a3). If the user updates a textfield a CHANGE event listener triggers checkValue function. If the value is greater than my maxValue I want my function to return the text field to its original value and give the user an error message. So if textfield c in mc.a1.c is updated, I'm currently taking the name of its parent (a1) and then trying to reference the variable with the same name so that textfield c will be returned to the initial value held in var a1 (I'll only know which var to reference once a textfield update has been attempted.. hope that makes sense)
I've tried several things but always end up with the variable name, and not its value in the textfield. So, for now I've reverted to populating the field with 0 until I can find an answer.
example code:
aH.t1 is the predefined max value
function chngTh(event:Event):void{
var thR:String = String(event.target.parent.name.substring(0,1));
if (thR =="a"&&thN>int(aH.t1.text)){
event.target.text = 0; //I want the reference var a(x)and have its value in the text field
aH.errorMsg.text = "The number cannot be greater than 10 so the original value has been restored";
}
}
As you can probably tell my my code, I'm not a developer and I've already looked here in search of but can't seem to get grasp it...Is it me?
reference variable AS3
AS3: Using string as variable
Is what I'm trying to do achiveable in AS3?
Thanks to guidance from dene the solution looks like this:
function chngTh(event:Event):void{
var thR:String = String(event.target.parent.name.substring(0,1));
var thN:int = (event.target.text);
var thov:int = root[event.target.parent.name];
if (thR =="a"&&thN>int(aH.thrsh.t1.text)){
event.target.text = thov;
aH.errorMsg.text = hclbl[12];
}
}
Use event.target in the listener function to reference the text field that changed:
var maxValue = 5;
myTextField.addEventListener(Event.CHANGE, textListener);
function textListener(event:Event)
{
var tf = event.target as TextField;
var currentValue = parseFloat(tf.text);
if (currentValue > maxValue) {
tf.text = getOriginalValue(tf);
}
}
function getOriginalValue(tf:TextField) : Number
{
// Assuming the textfield's parent is named "a" + number (eg. a1, a2 etc.)
// Get the number of the parent by ignoring the character at index 0
var parentName = tf.parent.name;
var parentNumber = parentName.substring(1);
// Now you can use parentNumber to access the associated variable (a1, a2, etc)
// Assuming these variables are defined on the root (main timeline).
var originalValue = root["a" + parentNumber]
// If the variables are stored as Strings, this line is needed to convert it to a Number type
originalValue = parseFloat(originalValue)
return originalValue;
}

Using objects instead of arrays

I've spent nearly 1 week to learn working with objects instead of arrays. I had thought it was easy to call them and created some objects and set their properties. However I can't access them now, I tried this:
function onBoxClick(event:MouseEvent):void {
var str:String = event.currentTarget.name;
trace(str);
str = str.substring(str.indexOf("_") + 1);
trace(getChildByName("copy_" + str)); // trying to trace an object by name
}
My question is if there's a practical way of dealing with objects, otherwise what's the purpose of using them.
Edit: Here's my function that I use to create movieclips and other things:
function addBoxes(isUpdate:Boolean):void {
var copyOne:Object = getReadOnlyValues();
copyOne.name = "copy_" + num;
// Set default mc1 settings
var settings1:Object = copyOne.mc1Settings;
for(var num2:String in settings1) {
copyOne.mc1[num2] = settings1[num2];
}
// Set default mc1text settings
var settings2:Object = copyOne.mc1TextSettings;
for(var num3:String in settings2) {
copyOne.mc1Text[num3] = settings2[num3];
}
copyOne.mc1.x = nextXpos;
copyOne.mc1.name = "captionBox_" + num;
addChild(copyOne.mc1);
copyOne.mc1.addEventListener(MouseEvent.CLICK, onCaptionClick);
copyOne.mc1Text.name = "captionBoxText_" + num;
copyOne.mc1.addChild(copyOne.mc1Text);
// ---------------------------------------------------------------
// Set default mc2 settings
var settings4:Object = copyOne.mc2Settings;
for(var num4:String in settings4) {
copyOne.mc2[num4] = settings4[num4];
}
// Set default mc2text settings
var settings5:Object = copyOne.mc2TextSettings;
for(var num5:String in settings5) {
copyOne.mc2Text[num5] = settings5[num5];
}
copyOne.mc2.x = nextXpos;
copyOne.mc2.y = copyOne.mc1.height;
copyOne.mc2.name = "box2_" + num;
addChild(copyOne.mc2);
copyOne.mc2Text.name = "box2BoxText_" + num;
copyOne.mc2.addChild(copyOne.mc2Text);
copyOne.mc2.addEventListener(MouseEvent.CLICK, onBoxClick);
if (num / subunits is int) {
trace (num);
// createMc("normalBox", true);
}
nextXpos = nextXpos + copyOne.mc2.width;
// traceObj(copyOne);
// traceObj(getReadOnlyValues());
}
I called this function in a loop so I created many movieclips. Now I can't access objects' properties and their childen (e.g textfield).
Objects I have on stage: Movieclips and textfields
Where they come from: The function above
What I'm trying to do with them: Tracing movieclips and textfields (that are holded by objects) to change their children (textfield) text
What happens instead of what I expect: Trace code outputs undefined instead of giving me object type trace(getChildByName("copy_" + str)); // trying to trace an object by name
Is there a practical way of accessing an object whose name is "copy_1" and its property whose name is "box2_1" (movieclip)?
One problem I see is the "copyOne" object has been created within the scope of "addBoxes", so it will no longer exist outside of this function.
Another is you're trying to access an Object via getChildByName, which only addresses displayObjects of the displayObjectContainer you are calling from.
If you want to loosely keep track of variables with things like Objects or MovieClips (which are both dynamic-style objects that let you add properties to them as you wish), just use MovieClips to house your values. The movieClips, being on the stage, will be retained in memory until removed from the displayList (stage).
Also, check out the Dictionary, a sort of key/value based way of storing collections of objects.
Better yet, if you use strongly-typed custom objects (creating your own classes to extend MCs, and adding your own public or private methods and values), there are benefits such as using Vectors (fancy, fast arrays that are compatible with any Object type you choose).
I don't really know if I understood your question or not, but as #ozmachine said in his answer, you can not use getChildByName, instead I think that you can take a look on this, may be it can help :
var container:DisplayObjectContainer = this;
function getReadOnlyValues():Object {
return {
mc1: new box(),
mc1: {
name: 'mc1_',
alpha: 1,
x: 0,
y: 0,
width: 30,
height: 25
},
mc1Text: new TextField(),
mc1Text: {
text: 'test',
x: 0,
y: 0,
selectable: false,
multiline: false,
wordWrap: false
}
}
};
// create 5 objects
for(var i=0; i<5; i++){
container['copy_'+i] = getReadOnlyValues();
var obj:Object = getObjectByName('copy_'+i);
obj.mc1.alpha = 1;
obj.mc1.x = 0;
obj.mc1.y = 50 * i;
obj.mc1.width = 100;
obj.mc1.addChild(obj.mc1Text);
obj.mc1Text.text = 'test_' + i;
addChild(obj.mc1);
}
// get object by name
function getObjectByName(name:String):Object {
return container[name];
}
// change the text of the 4th button
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
var obj:Object = getObjectByName('copy_3');
obj.mc1Text.text = 'new text';
})
Array and Object are both data structures.
Data means some form of information.
Data structure means some form of information being stored in a certain way.
Array and Object are two different ways to store information.
Arrays identify data with integer numbers.
An integer number to identify a single element of an array is called an index
Arrays are ideal to represent a list of similar things that belong to each other.
var names:Array = ["John", "Paul", "George", "Ringo"];
This often means that the elements of an array are of the same type, like in the example above.
But they don't have to:
var numbers:Array = [42, "twenty-five", "XIIV"];
For the above examples it's easy to answer the questions "What are the names of the four beatles?", "What different representations of numbers did you stumble upon during your trip through the historic town?". Other questions are harder or impossible to answer. "What Roman numerals did you stumble upon in the historic town?"
Objects identify data with names.
A name to identify a single element of an object is called a property
Objects are ideal to represent a list of dissimilar things that belong to each other.
var paula:Object = {age:37, name:"Paula", hairColor:0x123456};
This often means that the elements of an object are of different type, like in the example above.
But they don't have to:
var car:Object = {manufacturer:"Porsche", color:"red", sound:"wroooooom", soundOfDriver:"weeeeeeeeeeee"};
Considering this, let's take a look at your code and see how it applies.
The big picture is that you have a function addBoxes that you call multiple times. As one function should have one purpose, this function will do something similar every time it is executed. Uh-Oh: "similar". Whatever the result of this function is, it should go into an array. Each call to that function would be an element of the array. You can see this clearly on your use of "num" to identify whatever is happening in your current run of the function.
What data is present in your function?
copyOne
mc1
mc1Text
mc2
mc2Text
copyOne is a troublemaker here and what causes your confusion. It's trying to do everything at once and therefore you are not able to think clearly about when to use a Array and when Object. One would call it a god object. And that's not a good object to have around.
Your choice for variable names is very bad.
You choose super generic names like "mcX" only to later add a name property to it that describes what it truly is.
But even that doesn't hold true for whatever "Box2" is supposed to be.
Choose names so that it'S easy to understand what something in your code is.
It looks like you created all or parts of this structure jsut for this question and therefore lacked meaningful names.
I highly recommend that you do not learn by such made up projects. But from the real world.
I will therefore impose the following goal:
mc1 and mc1Text represent a caption
mc2 and mc2Text represent a content
With all this, I ask again:
What data is present in your function?
captionBox
captionText
contentBox
contentText
Both caption and content consist of a box and a text.
These are different things, so caption and content are each an object with properties "box" and "text"
One could think that due to this similarity, they both should go into an array.
But I beg to differ. A caption and a text are not the same thing. You deal with captions and texts differently. Walking on the streets you might catch a big caption in the news quickly, but not a lengthy text. That's why each of them should be a property of the object that's created in the function.
Here's somewhat of a conclusion:
var allBoxes:Array = []; // array to store the similar results of every function call
function createBoxes():void
{
var boxes:Object = {};
//the box consists of caption & content, both bying of the same type, but are containing different data
boxes.caption = {box:{}, text:{}}; //caption
boxes.content = {box:{}, text:{}}; //content
allBoxes.push(boxes);
}
This is it. That's how and why I would model your data with objects and arrays.
But it doesn't end here. My conclusion lacks a lot of the code you posted.
While the above is mostly language independent, the missing code is specific to Actionscript and not just on how to model data. It's as follows...
As3 is object oriented.
This is good, because the above conclusion has a lot of objects in it.
To define how some object is/does/moves/farts/etc, one creates classes.
The following changes take place (for reasons out of the scope of this answer):
createBoxes (formerly known as addBoxes) calls the constructor of
a class "CaptionAndContent" that extends Sprite.
There's no more need to explicitely create an object "boxes" as the constructor does exactly that.
The caption and content will not have a property "box", because
they can be the box themselves. This is exactly how it's done in the
code of the question. The default settings are set in the constructors of their classes.
Here's reduced snippet of code that hopefully illustrates how the classes could look like.
Each class should be in its own file, with the necessary imports, package block and the additional functionality that you did not specify in your question.
public class CaptionAndContent extends Sprite
{
private var caption:Caption;
private var content:Content;
public function CaptionAndContent(captionText:String = "", contentText:String = "")
{
caption = new Caption(captionText);
addChild(caption);
content = new Content(contentText);
content.y = caption.height;
addChild(content);
}
}
public class ClickableBoxWithText extends Sprite
{
protected var textField:TextField;
public function ClickableBoxWithText(text:String = "")
{
textField = new TextField();
textField.text = text;
addChild(textField);
addEventListener(MouseEvent.CLICK, onClick);
}
protected function onClick(mouseEvent:MouseEvent):void
{
//override this in a sublclass
}
}
public class Caption extends ClickableBoxWithText
{
public function Caption(text:String = "")
{
super(text);
// apply all the default settings of caption here.
}
}
public class Content extends ClickableBoxWithText
{
public function Content(text:String = "")
{
super(text);
// apply all the default settings of content here.
}
}
Using them would look something like this:
var allBoxes:Array = []; // array to store the similar results of every function call
function createBoxes():void
{
var captionAndContent:CaptionAndContent = new CaptionAndContent("This is the caption...", "...for this content");
captionAndContent.x = nextXpos;
addChild(captionAndContent);
allBoxes.push(captionAndContent);
}
Last but not least, the identification problem in the click handler.
Your question already contains the answer:
event.currentTarget
That's the reference to the object that was clicked on.
In my code it would be
mouseEvent.currentTarget
This identifies the object already. It's pointless to look up one of its properties (its name for example) in order to search all the objects for that name, just to identify the same object that you already had to identify (without a name) in order to get the name.
You aren't identifying the objects by name anyway. What differs between the names and what supposedly makes them unique is a number at their end. As pointed out in this answer, this is what's called an index and the thing you are trying to identify with it should go into an array. In my example codes, this is allBoxes.

getting a random element from an array of movieclips(or labels in a timeline) in Flash CC . Actionscript 3

I am making a pretty neat quiz-game in flashCC right now and I definitely need your help.
My skills are more on the design then the programming side. So to many of you this might seem a baby question (and asked many times before) but from all the answers I saw so far, I couldn't get any results for my project.
So here is the thing :
I need the EXACT script for creating an array (with movieclips inside? or instance names of mcs? How does this even work?)
and a method, to pick a random element of this array without repeats until the "game is over".
Paul
The easiest way to pick a random element from an array without repeating is to first sort the array with a "random" function, then pop or shift items out of it until the array is empty.
Let's say you have an array of items which can be filled with either instances or instance names, you've chosen instance names: :
var FirstArray:Array = ["blau", "orange", "green"];
Now, you'll need a random sort function:
// you do not need to modify this function in any way.
// the Array.sort method accepts a function that takes in 2 objects and returns an int
// this function has been written to comply with that
function randomSort(a:Object, b:Object):int
{
return Math.random() > .5 ? -1 : 1;
}
The way a sort function normally works is it compares two objects and returns -1 if the first item precedes the second item, 1 if the opposite is true, and 0 if they are the same.
So what we're doing in the function above is returning -1 or 1 randomly. This should get the array all jumbled up when you call:
FirstArray.sort(randomSort);
Now that the array is randomly sorted, you can begin pulling items from it like so:
if(FirstArray.length) // make sure there's at least one item in there
{
// since you are using instance names, you'll need to use that to grab a reference to the actual instance:
var currentQuizItem:MovieClip = this[FirstArray.pop()];
// if you had filled your array with the actual instances instead, you would just be assigning FirstArray.pop() to currentQuizItem
// every time you call pop on an array, you're removing the last item
// this will ensure that you won't repeat any items
// do what you need to do with your MovieClip here
}
else
{
// if there aren't any items left, the game is over
}
When strung together, the above code should be enough to get you up and running.
You could try something like:
var array:Array = [1, 2, 3, 4, 5];
var shuffledArray:Array = [];
while (array.length > 0)
{
shuffledArray.push(array.splice(Math.round(Math.random() * (array.length - 1)), 1)[0]);
}
trace('shuffledArray: ', shuffledArray, '\nrandom item: ', shuffledArray[0]);

AS3 selecting a Combo Box inside a Movie Clip

I am not sure if there is a better way to do this, and if there is please let me know. But right now, I have a list of combo boxes with names in them.
The combo boxes are stu1, stu2, stu3, ect all the way to 63 and held in the allStudents MovieClip
for(var i = 0; i < allStudents.length; i++)
{
var newTempStudent:ComboBox = allStudents.getChildAt(i);
newTempStudent.dataProvider.addItem({label: fullName, data:fullName});
newTempStudent.getChildAt(i).dataProvider.sortOn("label");
newTempStudent.getChildAt(i).selectedItem = allStudents.getChildAt(i).getItemAt(i);
}
essentially i am trying to:
get all 63 combo boxes to update from the same dataProvider,
sort them alphabetically,
then set the default selected to each student (stu1 should display dataProvider(0), stu2 should display dataProvider(1) as it's default selection)
The error I am getting is:
Scene 1, Layer 'Layer 1', Frame 1, Line 83 1118: Implicit coercion of a value with static type flash.display:DisplayObject to a possibly unrelated type fl.controls:ComboBox.
Now I am assuming I am getting that becasue it is looking is the movie clip which is the display object and executing combobox commands, but I'm not sure how to do this per se.
Originally I was going to do this with a dataGrid, but it became too complicated when I was trying to link the dataGrid to checkBoxes for attendance.
Any and all help is greatly appreciated!
Try this code :
for(var i = 0; i < allStudents.length; i++)
{
var newTempStudent:ComboBox = allStudents.getChildAt(i) as ComboBox;
newTempStudent.dataProvider.addItem({label: fullName, data:fullName});
newTempStudent.getChildAt(i).dataProvider.sortOn("label");
newTempStudent.getChildAt(i).selectedItem = allStudents.getChildAt(i).getItemAt(i) as ComboBox;
}
getChildAt() returns a DisplayObject, so you need to cast it as a ComboBox.