Add moveclips on stage when elements of an array are clicked in as3 - actionscript-3

I have an array with six buttons called "sostaletters" and an array with six elements called "addedletters". What I want is every time a button is been clicked a new movieclip from the array "addedletters" to be added on stage. For example if the third element of the array "sostaletters" is been clicked then the third element of the array "addedletters" to be added on stage. How i can do that?
This is what i have done for my array "sostaletters"
var sostaletters:Array = [a7,a17,a24,a1,a18]
for each (var letter:MovieClip in sostaletters) {
letter.buttonMode = true;
letter.isClicked = false;
letter.addEventListener(MouseEvent.CLICK, kanoklick2);
function kanoklick2(event:MouseEvent):void
{
event.target.alpha = 0.5;
if(event.currentTarget.isClicked == false){
clickCount2 ++;
event.currentTarget.isClicked = true;
sostaletters[i].x = positionsArray[i].xPos;
sostaletters[i].y = positionsArray[i].yPos;
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
if(clickCount2 == sostaletters.length){
addChild(welldoneman);
myTimer.start();
if (contains(kremmala)) {
removeChild(kremmala)
}
for (var i:int= 0; i< wrongletters.length; i++)
{
wrongletters[i].removeEventListener(MouseEvent.CLICK, kanoklick);
}
for (var o:int= 0; o< sostaletters.length; o++)
{
sostaletters[o].removeEventListener(MouseEvent.CLICK, kanoklick2);
}
trace("All buttons have been clicked");
}
}
}

Neal Davis has already gave a right answer. But I shall make a code review for more clarity. See my comments in the code.
var sostaletters:Array = [a7,a17,a24,a1,a18]
// "sostaletters" is an Array. So it is better to use iteration by index
for each (var letter:MovieClip in sostaletters) {
letter.buttonMode = true;
letter.isClicked = false;
letter.addEventListener(MouseEvent.CLICK, kanoklick2);
// You will create "kanoklick2" function at each iteration.
// Move this declaration from this loop
function kanoklick2(event:MouseEvent):void {
event.target.alpha = 0.5;
// There is no need to compare a boolean property with "false" or "true"
// You can write "if(event.currentTarget.isClicked)"
if(event.currentTarget.isClicked == false) {
clickCount2 ++;
event.currentTarget.isClicked = true;
// You declare an "i" variable below.
// So the compiler will not fire en error.
// But you will not get an index of the current letter.
sostaletters[i].x = positionsArray[i].xPos;
sostaletters[i].y = positionsArray[i].yPos;
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
// If number of "sostaletters" are not changed
// you can save its value in a variable for an example "sostalettersNum"
if (clickCount2 == sostaletters.length) {
addChild(welldoneman);
myTimer.start();
if (contains(kremmala)) {
removeChild(kremmala)
}
// You declare an "i" variable. And use it above to get a current letter.
// But an "i" will not contain its index.
// It will be equal to "wrongletters.length"
for (var i:int= 0; i

Related

AS3 novice struggles

var animal:String ="Cat";
var isFish:Boolean;
isFish = isItAFish(animal);
trace(isFish);
function isItAFish (animal:String):Boolean {
var fishArray:Array = new Array("haddock", "Trout", "Salmon", "Cod");
for(var i:int = 0; i < fishArray.length; i++){
if (fishArray[i] == animal){
return true;
break;
}
}
return false;
}
I just need help explaining this code guys and girls. The "isFish = isItAFish (animal); trace(isFish); is where I'm confused from.
//animal is a string that contains the value "Cat"
var animal:String ="Cat";
//isFish is a boolean that will be used as a flag
var isFish:Boolean;
//isFish value will be changed from the outcome of the function isItAFish with the animal value.
isFish = isItAFish(animal);
trace(isFish);
//This function requires 1 string parameter and returns a boolean.
function isItAFish (animal:String):Boolean
{
//fishArray is a list of all your possible fishes.
var fishArray:Array = new Array("haddock", "Trout", "Salmon", "Cod");
/*
We iterate the array to see if animal ("Cat") is inside the fishArray possible values.
This loop will run exactly the number of times of the array's content. In this case, 4 times.
*/
for(var i:int = 0; i < fishArray.length; i++)
{
/*
We are comparing the values of the fishArray against animal ("Cat").
fishArray[i] holds the value of the current loop count.
For example, the first loop will be fishArray[0] which is "haddock".
The 4th loop will contain the value "Cod".
*/
if (fishArray[i] == animal)
{
//If we find a match, we return 'true' and stop the loop.
return true;
break;
}
}
//IF the loop ends without any matches we return 'false'.
return false;
}

Adding multiple instances of the same object to the stage

I'm making a "spit" card game and I'm trying to be able to have 3 cards on the stage at once to be able to drag to the pile. So my question is how do I have multiple instances of the same object on the stage, but be able to assign each card different frames, etc. Here is the code to understand the context of it.
"cardArray" has 53 frames, 52 of which have a card face, 53rd is a "deck" picture.
//variables, constants
var cardDeck:Array = new Array();
var timer:Timer = new Timer(2000);
var j:int = 0;
var card:MovieClip = new CardArray();
var cardInDeck:Boolean;
const deckSize:int = 52;
//events:
card.addEventListener(MouseEvent.MOUSE_DOWN,fDown);
card.addEventListener(MouseEvent.MOUSE_UP,fUp);
startRandomise();
//This is where the unshuffled "deck" is created - values loaded into the array.
function createDeck():void
{
var i:int;
for(i =0; i<deckSize; i++)
{
cardDeck[i] = i+1;
}
}
function randomizeDeck( a : *, b : * ):int
{
return (Math.random()>.5) ? 1 : -1;
}
//Grab the value from the (presumably) current frame of the card
function convertCard(cardNo:int):int
{
var deckPos:int;
if (cardNo <= deckSize/4)
{
deckPos = cardNo;
}
else if (cardNo > deckSize/4 && cardNo <= deckSize/2)
{
deckPos = cardNo -13;
}
else if (cardNo > deckSize/2 && cardNo <=deckSize*3/4)
{
deckPos = cardNo -deckSize/2;
}
else if (cardNo >39)
{
deckPos = cardNo -39;
}
return deckPos;
}
btn.addEventListener(MouseEvent.MOUSE_UP,showArray);
function showArray(event:MouseEvent):void
{
if(j<deckSize /2)
{
addChild(card);
card.gotoAndStop(cardDeck[j]);
trace(cardDeck[j]+","+deckCompare[j]);
j++;
}
if(cardInDeck)
{
card.x = 200;
card.y = 200;
cardInDeck+false;
}
}
function fDown(evt:MouseEvent)
{
card.startDrag();
}
function fUp(evt:MouseEvent)
{
stopDrag();
if(card.hitTestObject(deck))
{
trace("deck: "+convertCard(deck.currentFrame));
trace("card: "+convertCard(card.currentFrame));
if(convertCard(card.currentFrame) == convertCard(deck.currentFrame)+1 || convertCard(card.currentFrame) == convertCard(deck.currentFrame)-1 || convertCard(card.currentFrame) == 13 && convertCard(deck.currentFrame) == 1 || convertCard(card.currentFrame) == 1 && convertCard(deck.currentFrame) == 13 || convertCard(deck.currentFrame) == 14)
{
deck.gotoAndStop(card.currentFrame);
removeChild(card);
cardInDeck=true;
}
else
{
card.x = 200;
card.y = 200;
}
}
else
{
card.x = 200;
card.y = 200;
}
}
function startRandomise():void
{
createDeck();
cardDeck.sort(randomizeDeck);
cardDeck.sort(randomizeDeck);
trace("random: "+cardDeck);
trace("deckCompare: "+deckCompare);
card.x = 200;
card.y = 200;
deck.gotoAndStop(53);
}
To have multiple cards, you need to instantiate more than one card. I don't know anything about the card game spit and don't understand the purpose of many of your functions, but you'll want to do something along these lines:
Create a function that generates (instantiates) a new card:
function createCard(faceFrame):MovieClip {
var tmpCard:MovieClip = new CardArray(); //this creates a new instance of a card
tmpCard.addEventListener(MouseEvent.MOUSE_DOWN, cardMouseDown); //make the card call the mouse down function when that event is triggered
tmpCard.gotoAndStop(faceFrame); //assign the card it's face (frame)
addChild(tmpCard); //add the card to the screen
return tmpCard;
}
Then, in your mouse down handler (I renamed it to be more clear what is is), you can do the following to card that was mouse downed:
function cardMouseDown(evt:MouseEvent) {
//the events currentTarget property is reference to the item that you attached the listener to, so in this case the card who triggered the mouse down
card = evt.currentTarget as MovieClip; //assign the current clicked card to the global card variable (so we can access it in the mouse up function)
card.startDrag();
//add the mouse up listener on the stage, since there are cases where you can drag so fast that the mouse isn't over the item it's dragging (and then if you were to release the mouse at that moment it wouldn't dispatch the event)
stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
}
Then your mouse up function would look something like this:
function stageMouseUp(evt:MouseEvent) {
//remove the mouse up listener from the stage
stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
card.stopDrag();
if(card.hitTestObject(deck))
{
......//rest if the code
Seems like you would want to generate a new card in the showArray function you have? So something like this:
function showArray(event:MouseEvent):void
{
var newCard:MovieClip = createCard(cardDeck[j]);
j++
newCard.y = newCard.x = 200;
trace(cardDeck[j]+","+deckCompare[j]);
}
As an aside, you should consider calling your Card object something more sensible, like Card instead of CardArray, as it's not an array...

How can i check by actionscript 3 if every items of an array had hitTestObject the items of the second array

I have this code for a drag and drop game.
How can i check by actionscript 3 if every item of an array had hitTestObject the items of the second array so something else can happens for example show a well done message.
var hitArray:Array = new Array(hitTarget1,hitTarget2,hitTarget3,hitTarget4,hitTarget5);
var dropArray:Array = new Array(drop1,drop2,drop3,drop4,drop5);
var positionsArray:Array = new Array();
for (var i:int = 0; i < dropArray.length; i++) {
dropArray[i].buttonMode = true;
dropArray[i].addEventListener(MouseEvent.MOUSE_DOWN, mdown);
dropArray[i].addEventListener(MouseEvent.MOUSE_UP, mUp);
positionsArray.push({xPos:dropArray[i].x, yPos:dropArray[i].y});
}
function mdown(e:MouseEvent):void {
e.currentTarget.startDrag();
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
function mUp(e:MouseEvent):void {
var dropIndex:int = dropArray.indexOf(e.currentTarget);
var target:MovieClip = e.currentTarget as MovieClip;
target.stopDrag();
if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
playSound(sosto);
}else{
target.x = positionsArray[dropIndex].xPos;
target.y = positionsArray[dropIndex].yPos;
}
}
reset.addEventListener(MouseEvent.CLICK, backObjects);
function backObjects(e:MouseEvent):void{
for(var i:int = 0; i < dropArray.length; i++){
if(dropArray[i].x == hitArray[i].x && dropArray[i].y == hitArray[i].y){
dropArray[i].x = positionsArray[i].xPos;
dropArray[i].y = positionsArray[i].yPos;
}
}
}
function playSound(SoundName:Class):void{
var sound = new SoundName();
var channel:SoundChannel = sound.play();
}
playSound(sosto);
Let's create a function to tell us if every "hitTarget" and its corresponding "drop" are touching each other.
function allCorrect():Boolean {
//for each item in the hitArray, we repeat the action
//we assume that length of hitArray and dropArray are the same
for (var i=0;i<hitArray.length;i++) {
//if the corresponding target and drop do not hit each other, return false
if (!(hitArray[i].hitTestObject(dropArray[i])) {
return false
//if we return false, this function will continue no further
}
}
//We have cycled through all of the items in the arrays, and none of the
//hitTestObjects have been false, so we return true
return true
}
We want to test if everything is correct when we update the positions of our "drops". So, in your mUp function, add this line to the bottom
if (allCorrect()) {
//display "youz a cool cat, bro"
//remove all of your event listeners to improve performance
}
hope this answers your question!
Try adding this line:
stage.addEventListener(Event.ENTER_FRAME, loop);
Where "loop" is a function that contains the rest of your code, which looks something like...
function loop (e:Event):void
{
//Your Code
}
Good luck!

How to generate random number and use It few times?

So I need to generate random number and use It few times, problem is that It generating on EnterFrame function.
This function generate number 0-5:
function pn():Number {
var pn:Number = Math.round(Math.random()*5);
return pn;
}
Here I check if character not jumping and stage.addEventListener(Event.ENTER_FRAME, jump);
if(!mainJumping){
mainJumping = true;
stage.addEventListener(Event.ENTER_FRAME, jump)
}
And here is jump function where I need to use random generated number:
function jump(e) {
if ( i < 50) {
i++;
item[1][pn()].y -=1
} else {
item[1][pn()].y += 1;
if (item[1][pn()].y == 0){
stage.removeEventListener(Event.ENTER_FRAME, jump)
}
}
Problem is that in jump function every time IF is checked It generates new number. I need to make that number will be generated and not changed till this part:
if (item[1][pn()].y == 0){
stage.removeEventListener(Event.ENTER_FRAME, jump)
}
After this It can generate new number. Have you ideas? Thank you.
// Create a variable higher up the scope chain to store the number
var random = 0;
// Assuming this is in a function at the same level as the jump function
//function() ???? {
if(!mainJumping){
mainJumping = true;
random = pn(); // Generate new random number when jump begins
stage.addEventListener(Event.ENTER_FRAME, jump)
}
//}
function jump(e) {
var item = item[1][random]; // Grab the random item
if ( i < 50) {
i++;
item.y -=1
} else {
item.y += 1;
if (item.y == 0){
stage.removeEventListener(Event.ENTER_FRAME, jump)
}
}
}
Create an instance variable called myRandomNumber. In the getter for it, if it is null, call pn() to populate it.
Something like this:
In your class, define the variable:
private var _myRandomNumber:int = 0;
And in your getter:
public function get myRandomNumber():int {
if (_myRandomNumber == 0) {
_myRandomNumber = pn();
}
return _myRandomNumber;
}
Now, when you call myRandomNumber, you'll get a "random number" :)

Flash remove child from timer

I have 25 objects of movie clip class named drone, and when i click it, after 2 seconds I want the object to disappear. I also have 25 timers named countdown. Here is what i do:
function clickHandler (event:MouseEvent):void{
event.currentTarget.hp--;
if(event.currentTarget.hp <= 0)
{
for(var i:int = 0;i<25;i++)
{
if(event.currentTarget == _drone[i])
{
countdown[i].start(); //start timer
}
}
}
}
Here is my timer:
for(var i:int = 0;i<25;i++)
{
countdown[i] = new Timer(2000);
countdown[i].addEventListener(TimerEvent.TIMER,timerHandler);
}
function timerHandler(e:TimerEvent):void {
//remove the drone I clicked
//I also dont know which drone i'm clicking
}
What should I do in the timerHandler to remove the object I clicked?
You can use Dictionary. Use the timer as key and movielcip as value.
import flash.utils.Dictionary;
var dict:Dictionary = new Dictionary();
function clickHandler (event:MouseEvent):void{
event.currentTarget.hp--;
if(event.currentTarget.hp <= 0)
{
for(var i:int = 0;i<25;i++)
{
if(event.currentTarget == _drone[i])
{
dict[countdown[i]] = _drone[i];//set the target mc here
countdown[i].start(); //start timer
break;
}
}
}
}
function timerHandler(e:TimerEvent):void {
var mc:MovieClip = dict[e.target] as MovieClip;//get the object been clicked
if (mc && mc.parent) {
mc.parent.removeChild(mc);//remove it
}
}
With minimal changes, set up an array to track the drones:
var arrayToRemove:Array = new Array();
and then in the click handler store drones to be removed in there:
arrayToRemove.push(event.currentTarget);
and in the timerHandler just remove the first element of the array:
removeChild(arrayToRemove.shift());
Since every delay is the same the order of the events and removals will be preserved. Although, it would probably be better to generalize the code using the above example and store all drones and timers in an arrays, so you can have any number of them.