Questions about actionscript - arrays

I have a few different question and i have decided to put them in one. So the first question : If i have one and the same code(for example):
buttonsA.buton1a.addEventListener(MouseEvent.MOUSE_DOWN , buton1a_function);
buttonsA.buton2a.addEventListener(MouseEvent.MOUSE_DOWN , buton2a_function);
buttonsA.buton3a.addEventListener(MouseEvent.MOUSE_DOWN , buton3a_function);
buttonsA.buton4a.addEventListener(MouseEvent.MOUSE_DOWN , buton4a_function);
buttonsA.buton5a.addEventListener(MouseEvent.MOUSE_DOWN , buton5a_function);
buttonsA.buton6a.addEventListener(MouseEvent.MOUSE_DOWN , buton6a_function);
buttonsA.buton7a.addEventListener(MouseEvent.MOUSE_DOWN , buton7a_function);
buttonsA.buton8a.addEventListener(MouseEvent.MOUSE_DOWN , buton8a_function);
buttonsA.buton9a.addEventListener(MouseEvent.MOUSE_DOWN , buton9a_function);
buttonsA.buton10a.addEventListener(MouseEvent.MOUSE_DOWN , buton10a_function);
and i want to put it in several places(in different conditions) can i put them in a function a call a function instead a copying a large amout of text (I thought about 'include' from a different file but i want to keep all the information in one file).
The second question is about arrays : In my situation i have an array and i .push() a different numbers in it.But it could be "1,51,11,2,13' or "1,2,3,4,5" so every time place of numbers (and numbers themselves) are different. How can i say to AS3 in function to remove(.splice) exactly the number 5 or 6 (in spite of their place in the array).
The third question is again about the "code" that is upper in the question. Can i maybe with the loop for to make all these 10 addEventListen with a fewer code (i think it should be something like that:)
for(var i:int = 1; i <= 100; i++){
//buttonsA.buton'i'a.addEventListener(MouseEvent.MOUSE_DOWN , buton'i'a_function);
}
Long story short maybe i didn't have to put so much question and maybe my thoughts are not correct, but i think that my questions are easy but i can't solve them. Any decisions and replies are welcomed :) Thanks.

First Question:
Not sure I understand your first question. I'll take a stab at it and say you're wanting the functionality of the button mouse down to be enabled during different contexts of your application state, but you don't want to repeat all the event listeners all the time?
if so, you should make a subclass for all your button to inherit from. It could look something like this:
public class ButtonSubClass extends Sprite { //or simple button, or whatever
public function ButtonSubClass():void {
this.addEventListener(MouseEvent.MOUSE_DOWN,downHandler,false,0,true);
}
private function downHandler(e:MouseEvent):void {
//do something common to all your buttons here
}
}
Then, have all your buttons inherit from this class.
Second Question:
function removeFromArray(elementVal:*):void {
var index:int = array.indexOf(elementVal); //get the index of the first element whose value is the passed parameter;
if(index >= 0){
array.splice(index,1); //remove that element/index from the array.
}
}
Third Question:
If ButtonA is a sprite whose only children are all the buttons you want the listener for, then you can do this:
var i:int = buttonA.numChildren;
while(i--){
buttonsA.getChildAt(i).addEventListener(MouseEvent.MOUSE_DOWN , button_function);
}
function button_function(e:Event):void {
switch(e.currentTarget){
case button1a:
//do something with button 1a
break;
case button2a
//do something with button 2a
break;
}
}
OR, more sloppily and less efficient and not recommended, this:
for(var i:int=1;i<=10;i++){
this["buton" + i.toString() + "a"].addEventListener(MouseEvent.MOUSE_DOWN, this["buton" + i.toString() + "a_function"]);
}

Related

nested for-loops on an array

I'm using SpriteKit and Swift 3 to create a simple game.
I have an array of Rings/Circles:
mRings = [mRingOne, mRingTwo, mRingThree, mRingFour, mRingFive]
each object in the array has a different color, In some point in the game I want to change the color of each ring, but I have 2 condition for this to happen:
1. a ring should not have the color it had one iteration before.
2. each ring should be in a different color from the others.
for the first condition I did this:
func changeRingsColor(){
var previousColor: UIColor?
for ring in mRings {
previousColor = ring.fillColor
repeat{
ring.fillColor = hexStringToUIColor(hex: mColors[Int(arc4random_uniform(UInt32(5)))])
}while(ring.fillColor.isEqual(previousColor))
}
}
and it is working, however, I couldn't figure out a way to answer the second condition.
In Java I would probably do something like this:
for (int i=0; i<mRings.length; i++){
for( int j=1; j<mRings.length; j++){
if (ring[i].fillColor == ring[j].fillColor){
generate another color for 'j' ring.
}
}
}
but nothing I tried worked.
Hope you guys can help me, Thanks in advance!
btw, mColors is an array of 5 different colors, from there I pick the colors.
I'm going to ignore some of the implementation details and focus on the core of the question, which is:
Loop through an array
Within each loop, start a new loop at the current index to the end of the array.
Let me know if I'm misunderstanding the above. But I would do it like this:
for (index, ring) in mRings.enumerated() {
let remainingRings = mRings[index+1..<mRings.count]
for otherRing in remainingRings {
print("Now comparing \(ring) to \(otherRing)")
}
}
First, enumerated() gives you both the current ring, and the index, on each iteration of the first for loop. Then, we slice the array from the current index to the end (remainingRings), and loop through those.
It is possible to rewrite Java code in this way :
let mRings = ["mRingOne", "mRingTwo", "mRingThree", "mRingFour", "mRingFive"]
for (index, item) in mRings.enumerated() {
for item in index + 1..<mRings.count {
}
}
Something like this will work:
func changeRingsColor(){
// extract the previous colors
let colors = rings.map { $0.fillColor }
// the order in which the rings will pass color to each other
let passOrder = mRings.indices.shuffled()
for i in mRings.indices {
let previous = i == 0 ? mRings.count - 1 : i - 1
mRings[passOrder[i]].fillColor = colors[passOrder[previous]]
}
}
Using this implementation of shuffled
How does it work?
Instead of randomly choosing a color for each individual ring, I am randomly generating an order in which the rings will swap the colors (passOrder). Since every ring will pass its color to a different ring in that order, you can be sure no color will stay the same.

Instantiation attempted on a non-constructor

I'm trying to make a bomb catching game (I'm actually using the code from the AS3 Classroom in a Book on arrays). As soon as I changed the word fruit to bomb in the code I got error 1007. With the exception of changing basket_mc to eod_mc and fruit to bomb (I used command-F and replaced with case sensitive on) I haven't changed much. It worked with eod_mc, but doesn't with bomb.
var bombArray:Array = new Array(bomb);
var bombsOnstage:Array = new Array();
var bombsCollected:int = 0;
var bombsLost:int = 0;
for (var i:int = 0; i<20; i++) {
var pickBomb = bombArray[int(Math.random() * bombArray.length)];
var bomb:MovieClip = new pickBomb();
addChild(bomb);
bomb.x = Math.random() * stage.stageWidth-bomb.width;// bomb.width is subtracted from the random x position to elimate the slight possibility that a clip will be placed offstage on the right.
bomb.y = Math.random() * -500;
bomb.speed = Math.random() * 15 + 5;
bombsOnstage.push(bomb);
}
eod_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragEod);
stage.addEventListener(MouseEvent.MOUSE_UP, dragStop);
function dragEod(e:Event):void {
eod_mc.startDrag();
}
function dragStop(e:Event):void {
eod_mc.stopDrag();
}
stage.addEventListener(Event.ENTER_FRAME, catchBomb);
function catchBomb(e:Event):void {
for (var i:int = bombsOnstage.length-1; i > -1; i--) {
var currentBomb:MovieClip = bombsOnstage[i];
currentBomb.y += currentBomb.speed;
if (currentBomb.y > stage.stageHeight - currentBomb.height) {
currentBomb.y = 0 - currentBomb.height;
bombsLost++;
field2_txt.text = "Total Bombs Detonated: " + bombsLost;
}
if (currentBomb.hitTestObject(eod_mc)) {
bombsCollected++;
removeChild(currentBomb);
bombsOnstage.splice(i,1);
field1_txt.text = "Total Bombs Caught: " + bombsCollected;
if (bombsCollected >= 20) {
eod_mc.gotoAndStop(20);
} else if (bombsCollected > 15) {
eod_mc.gotoAndStop(15);
} else if (bombsCollected>10) {
eod_mc.gotoAndStop(10);
} else if (bombsCollected>5) {
eod_mc.gotoAndStop(5);
}
}
}
if (bombsOnstage.length <= 0) {
field1_txt.text = "You Win! You have defused the bombs.";
field2_txt.text = "";
stage.removeEventListener(Event.ENTER_FRAME, catchBomb);
}
if (bombsLost >= 20) {
field1_txt.text = "Sorry you lose. You have lost your foot!";
field2_txt.text = "";
stage.removeEventListener(Event.ENTER_FRAME, catchBomb);
for (var j:int = bombsOnstage.length-1; j > -1; j--) {
currentBomb = bombsOnstage[j];
removeChild(currentBomb);
bombsOnstage.splice(j,1);
}
}
}
Maybe to avoid making your programming life more twisted than it is now...
There are objects and classes in programming, a class is a description of a set of objects, say "table" (or, as it's better to differ in names for classes and variables, "Table", first letter capitalized) is a name of a class. An instance or an object is a structure that belongs to one or more classes, with Object being the topmost, as everything in programming is either an object or a "simple variable", that is, a number, a true/false, a string of characters (these are object types in AS3 too, though, Number, Boolean, String, but these generally not need to be instantiated via new) or probably some other simple type I don't remember right now.
Classes have properties and methods. A property is something that can be requested off any object of the class, say "height" for tables. Properties can be of any type, including nested objects, depending on what your base class is. Say stage in AS3 is a property of any DisplayObject which is used to get the only Stage object there is at runtime[1]. Methods are what any object of a class can be told to do. Say, bombs fall, explode, MovieClips can be told to stop(), etc. You write class code keeping in mind that all of the objects of this class will have to behave exactly like you've written, but since they can differ in properties, you can give them conditional behavior. For example, if a bomb has already exploded, it cannot blow up once more.
A variable, whether a property or a standalone var (if you declare one in a function) is a reference to an object of a given type. Say var i:int refers to some kind of an integer. Simple type vars are containers instead, that is, i=2; will place a 2 in the referred integer, and i=j; will copy the value from j into i, while var theStage:Stage=this.stage will instead create a reference to an existing object, and if that object will change, the reference will give you the changed object instead of its previous state. An array is a collection of variables, reachable by indexes, in AS3 they don't have to be of one type, and a Vector is a typed array.
Next, the lifetime of objects. An object only lives while there's an active reference to it, whether in a property of another alive object, or in a visible variable, or in an event listener (AS3 specific). An object is created via new ClassName(<parameters>), lives while you can reach it somehow, and is destroyed once you have no active links to it and Flash player decides to run garbage collector. Prior to this programmers had to deallocate objects themselves, a rudiment can be seen at BitmapData.dispose(). So, in order to avoid Flash player to run out of free memory, take full control over creation and destruction of links. You don't need to care for simple vars, they are being cared for by Flash player.
A lot of basic functions for interactions has already been implemented in AS3, look for them and examples of how they work in Adobe's manual, navigate through packages in the lower left, most of the interactive stuff is in flash.display package, refer to other packages as necessary.
Hope this will bring you some insight into programming basics.
[1]: There is one stage unless you're doing a load of an SWF, then there could be more, one Stage per one SWF.

AS3: Creating and accessing movieclips from an array

I know there are quite similar questions here, but I haven't found the proper details. What would be helpful is definitely an explanation of the problems, and perhaps a base example, that anyone who searches later may be able to apply. (Not asking that you write it for me, I just find the examples helpful) I don't want to upset anyone and am kind of worried to post in a forum...
I am wondering alternatives to creating a screen based off tiles created from an array. I have been having an issue myself trying to access the movieclips that have been placed on screen, and trying to trace to find a way to reference them hasn't been working.
Anyway, take something basic like an array, and connecting it to movieclips, then how to access the movieclip itself once done. So I have been working on this, and used many different online resources, so I'm sure a lot of this is going to look familiar, just in a much messier way.
This takes the array to make the movieclips appear (Im sure at least one part in here is unnecessary, and I'm thinking I'm doing something wrong here that makes it not work out later) So this works, but feels pretty bulky.
Both are from the same main class file.
function makeWorld (anyMap, tileW, tileH) {
var worldWidth = anyMap[0].length;
var worldHeight = anyMap.length;
var MAP = this.addChild(new mapHolder());
function tiler(MAP, i, j, tileW, tileH, tile)
{
MAP.addChild(tile);
tile.x = (j * tileW);
tile.y = (i * tileH);
}
for (var i = 0; i < worldWidth; ++i) {
for (var j = 0; j < worldHeight; ++j) {
var curTile:int = anyMap[i][j];
if (curTile == 101) {
var tile1 = new tileGround();
tiler (MAP, i, j, tileW, tileH, tile1);
...
else {
var tile3 = new empty();
tiler (MAP, i, j, tileW, tileH, tile3);
}
}}}
Then there is attempting to reference it, where I'm having the issue. I don't know what to call this.MAP.tileGround by, and I have tried many things. I've read it's not such a good idea to reference by name when not very advanced so I wanted to avoid that sort of thing too.
addEventListener (Event.ENTER_FRAME, hits);
function hits (event:Event) {
var tileCatchG:MovieClip = this.MAP.tileGround;
if(tileCatchG.hitTestPoint(this.MAP.Char.x + leftBumpPoint.x, this.MAP.Char.y + leftBumpPoint.y, true)){
leftBumping = true;
} else {
leftBumping = false;
}
...
}
Thank you!
In looking over what you're doing a second time it would appear that you should have a reference to the 2-indexed array that represents the map.
You can create a regular (single indexed) Array at the top of the file like
public var tileArray:Array = [];
Then where you create them push them into the array
var tile1 = new tileGround();
tileArray.push(tile1);
then to reference them all you can just run a simple loop
for each(var tile:MovieClip in tileArray)
{
//Do stuff
if(tile instanceof tileGround)
{
//Do stuff specific to tileGround
}
}

Get an array of specific added children

I'm using the following array to add children to the stage:
for(var i=0;i<6;i++) {
var aCherry=new cCherry()
aCherry.y=10
aCherry.x=10+100*i
stage.addChild(aCherry)
}
Now I want to modify each cherry based on another array. Something like this:
var cherryLetter:Array=[1,0,0,0,0,0]
for(i=0;i<6;++) {
if(cherryLetter[i]) stage.getChildByName("aCherry")[i].y+=90
}
Clearly stage.getChildByName("aCherry")[i] isn't correct, but coming from JavaScript this makes the most sense to me and should accurately portray what I'm trying to achieve for you guys reading this. So, how would I actually do this? This being getting an array of children added to the stage under a certain name or class (so an array of cCherry would work too, if necessary), then using them in a way similar to the above loop.
Here is my recommendation for how the code might look, based on the desire to use getChildByName() to find the instances of your cCherry class. Please note that I've changed the class name to Cherry in the example (which I recommend, since capitalizing class names is AS3 convention). Also, it's good practice to end statements with semi-colons. While it's usually optional, there are cases where omitting the semi-colon can produce very difficult to track down runtime bugs, so I recommend getting int he habit of using them. I also recommend including type in all your variable declarations, as shown with var aCherry:Cherry, for example.
var i:int;
for(i=0; i<6; ++i)
{
var aCherry:Cherry=new Cherry(); // Note, it's my recommendation that you rename cCherry class to Cherry (convention)
aCherry.y=10;
aCherry.x=10+100*i;
aCherry.name = "aCherry" + String(i); // String() cast for clarity only, not necessary
stage.addChild(aCherry);
}
and
var cherryLetter:Array=[1,0,0,0,0,0];
for(i=0; i<6; ++i)
{
var cherry:Cherry = stage.getChildByName("aCherry" + String(i)) as Cherry;
if(cherry && cherryLetter[i]) cherry.y += 90;
}

Flash Resetting array values

I was working on a test project that I will later incorporate into a much larger work that is a simple quiz game. I made an array with my questions:
var questions1:Array=["nitrogen dioxide","sulfur hexafluoride",..."]
and in a second layer I made a button that cycles through the questions randomly.
import flash.events.MouseEvent;
var qno=0;var rnd1;
function change_question(){
rnd1=Math.ceil(Math.random()*questions1.length)-1;
q.text=questions1[rnd1];
if(questions1[rnd1]=="X"){change_question();}
questions1[rnd1]="X";
}
change_question();
next_b.addEventListener(MouseEvent.CLICK, ButtonAction1);
function ButtonAction1(eventObject:MouseEvent){
qno++;change_question();
}
This part works great, because I was following a tutorial. Text appears in a dynamic text box I created as it should. This tutorial taught to change the value of the array to X with every choice and to ignore choose a different question every time it encountered an X
After it cycles through all the questions I basically get an infinite loop in my output section of flash because it can't find any more non-X values. I was hoping someone had information on how to press a button an change the array back to its default settings so that a teacher (because that is who it is for) has a way of resetting the file when they have reached the end of the quiz.
Thanks everyone!
As per my understanding you wanted to randomize your questions and after showing all the entire questions you wanted to reset your questions.
As per your code you get a random question and updating the same array by pushing value 'X'. Rather than doing this what you need to do is to preserve the array only randomize its position. So that you can use the same value once you cover your all questions
I have added code here.
import flash.events.MouseEvent;
var qno=0;var rnd1;
var questions1:Array=["nitrogen dioxide","sulfur hexafluoride","carbon dioxide","carbon monooxide"];
var nAttmeptedCount = 0;
var shuffledLetters:Array;
function change_question()
{
if(qno == questions1.length)
{
qno = 0;
resetQuestion()
}
else
{
q.text = questions1[shuffledLetters[qno]];
qno++;
}
}
function resetQuestion()
{
shuffledLetters = new Array(questions1.length);
for(var i=0;i<shuffledLetters.length;i++)
{
shuffledLetters[i] = i;
}
shuffledLetters.sort(randomize);
}
function randomize ( a : *, b : * ) : int {
return ( Math.random() > .5 ) ? 1 : -1;
}
resetQuestion()
change_question();
next_b.addEventListener(MouseEvent.CLICK, ButtonAction1);
function ButtonAction1(eventObject:MouseEvent){
change_question();
}
In above solution after showing all questions I have reset the questions automatically. you can modify code as per your requirement. If you want to do the reset questions you can put you code qno = 0;resetQuestion() on button click.
hope above solution work for you.

Resources