How to drag and drop instances of a movieclip - actionscript-3

I have a movieclip (star) in my library and i set it's class linkage name "star". Then i use my code to call it on stage.I want to create multiple instances of star in the same position and all be draggable but unfortunately I manage to create two instances of that movieclip and only one is draggable.I need some help with my code. Thank you.
var stars:Array = [];
var star:Star = new Star();
this.addChild(star);
stars.push(star);
star.x=550;
star.y=490;
for(var i=0; i<stars.length; ++i)
{
trace(stars);
star.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
star.addEventListener(MouseEvent.MOUSE_UP, releaseToDrop);
}
function clickToDrag(e:MouseEvent):void
{
e.target.startDrag();
var star:Star = new Star();
this.addChild(star);
stars.push(star);
star.x=550;
star.y=490;
}
function releaseToDrop(e:MouseEvent):void
{
e.target.stopDrag();
if (star.hitTestObject(target))
{
trace("Collision detected!");
e.target.removeEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
}
else
{
trace("No collision.");
}
}

You are adding listener to only one star. Add it to all stars like so,
var totalStars:int = 20;
for(var i=0; i<totalStars; i++)
{
var star:Star = new Star();
this.addChild(star);
star.x=550;
star.y=490;
star.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
star.addEventListener(MouseEvent.MOUSE_UP, releaseToDrop);
stars.push(star);
}

Related

Making a reset placed objects button in Flash (as3)

I have a drag and drop project where everytime I click on a movieclip a clone is made that can be dragged. I would like to know how to make a button that can reset/remove the clones when the button is pressed.
This is what I got so far:
import flash.display.MovieClip;
var latestClone:MovieClip;
plus.addEventListener(MouseEvent.MOUSE_DOWN, onPlusPressed);
function onPlusPressed(event:MouseEvent):void
{
latestClone = new Plus();
latestClone.x = event.stageX;
latestClone.y = event.stageY;
addChild(latestClone);
latestClone.startDrag();
latestClone.addEventListener(MouseEvent.MOUSE_DOWN, latestClone.startDrag);
}
stage.addEventListener(MouseEvent.MOUSE_UP, onStageReleased);
function onStageReleased(event:MouseEvent):void
{
if(latestClone != null){
latestClone.stopDrag();
}
}
Add all of your clones in an array, and loop over the array and do a removeChild on each item in the array. So:
var items:Array = new Array();
....
addChild(latestClone);
items.push(latestClone);
....
var resetButton:SimpleButton = new SimpleButton();
//set your button properties here
resetButton.addEventListener(MouseEvent.CLICK, onResetClicked);
addChild(resetButton);
function onResetClicked(e:MouseEvent):void
{
reset();
}
function reset():void
{
for (var i:uint = 0; i < items.length; i ++)
{
removeChild(items[i]);
items[i] = null;
}
items = new Array();
}
Hope this helps.
just declare container variable like so:
var clone_container:Sprite = new Sprite();
put all clones inside,than u can clear it up very easely:
while(clone_container.numChildren > 0){
clone_container.removeChildAt(0);
}
that's all..
I found the solution to my question by testing several possibilities with the code that was posted + searching other questions.
This is the code that worked:
import flash.display.MovieClip;
import flash.events.MouseEvent;
var latestClone:MovieClip;
plus.addEventListener(MouseEvent.MOUSE_DOWN, onPlusPressed);
function onPlusPressed(event:MouseEvent):void
{
latestClone = new Plus();
latestClone.x = event.stageX;
latestClone.y = event.stageY;
addChild(latestClone);
latestClone.startDrag();
latestClone.addEventListener(MouseEvent.MOUSE_DOWN,onClonedPlusPressed);
}
function onClonedPlusPressed(event:MouseEvent):void{
latestClone = MovieClip(event.currentTarget);
latestClone.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, onStageReleased);
function onStageReleased(event:MouseEvent):void
{
if(latestClone != null){
latestClone.stopDrag();
items.push(latestClone);
}
}
resetButton.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{
}
var items:Array = new Array();
resetButton.addEventListener(MouseEvent.CLICK, onResetClicked);
addChild(resetButton);
function onResetClicked(e:MouseEvent):void
{
reset();
}
function reset():void
{
for (var i:uint = 0; i < items.length; i ++)
{ items[i].removeEventListener(MouseEvent.MOUSE_DOWN,onClonedPlusPressed);
if(items[i].parent) items[i].parent.removeChild(items[i]);
items[i] = null;
}
items = new Array()
}
you most add an array and push object into this,
your solution:
import flash.display.MovieClip;
import flash.events.Event;
var latestClone:MovieClip;
plus.addEventListener(MouseEvent.MOUSE_DOWN, onPlusPressed);
var plusArray:Array = new Array();
resetbtn.addEventListener(MouseEvent.CLICK,resetFunc);
function resetFunc(e:Event)
{
for (var i=0; i<plusArray.length; i++)
{
removeChild(plusArray[i]);
}
plusArray = new Array()
}
function onPlusPressed(event:MouseEvent):void
{
latestClone = new Plus();
latestClone.x = event.stageX;
latestClone.y = event.stageY;
plusArray.push(latestClone);
addChild(plusArray[plusArray.length-1]);
plusArray[plusArray.length - 1].startDrag();
plusArray[plusArray.length - 1].addEventListener(MouseEvent.MOUSE_DOWN, plusArray[plusArray.length-1].startDrag);
}
stage.addEventListener(MouseEvent.MOUSE_UP, onStageReleased);
function onStageReleased(event:MouseEvent):void
{
if (latestClone != null)
{
latestClone.stopDrag();
}
}
Good luck

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!

Action Script 3: Adding an gotoAndStop Animation

So the other day I found a tutorial on how to create a pattern lock screen in action script. To do so I had to create a class, I have a good grasp on how the class is working. But I want to add an animation so when the user goes over the dots in the pattern and animation plays. But I have no idea how to do something like this through the class. Here is the code I used in my class.
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.Strong;
public class Main extends Sprite
{
private var dots:Array = []; // Stores the in stage movieclips
private var pattern:Array = []; //The pattern entered by the user
private var pass:Array = [1,4,7,8,5,2,5]; //The correct pattern to proceed
public function Main():void
{
dots = [one,two,three,four,five,six,seven,eight,nine]; //add the clips in stage
addListeners();
}
private function addListeners():void //adds the listeners to each dot
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_DOWN, initiatePattern);
dots[i].addEventListener(MouseEvent.MOUSE_UP, stopPattern);
}
}
/* Adds a mouse over listener and uses it to add the number of the dot to the pattern */
private function initiatePattern(e:MouseEvent):void
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_OVER, addPattern);
}
pattern.push(dots.indexOf(e.target) + 1); //adds the array index number of the clip plus one, because arrays are 0 based
}
private function addPattern(e:MouseEvent):void
{
pattern.push(dots.indexOf(e.target) + 1); //adds the pattern on mouse over
}
private function stopPattern(e:MouseEvent):void //stops storing the pattern on mouse up
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].removeEventListener(MouseEvent.MOUSE_OVER, addPattern);
}
checkPattern();
}
private function checkPattern():void //compares the patterns
{
var pLength:int = pass.length;
var correct:int = 0;
for (var i:int = 0; i < pLength; i++) //compares each number entered in the user array to the pass array
{
if (pass[i] == pattern[i])
{
correct++;
}
}
if (correct == pLength) //if the arrays match
{
//Hides Sign In
MovieClip(root).LockScreen.visible = false;
MovieClip(root).RTID.visible = false;
MovieClip(root).SignIn.visible = false;
//Turns On Main Menu
MovieClip(root).gamemenu_mc.visible = true;
MovieClip(root).biggamesmenu_mc.visible = true;
MovieClip(root).totaltextmenu_mc.visible = true;
MovieClip(root).tmenu_mc.visible = true;
MovieClip(root).smenu_mc.visible = true;
MovieClip(root).optionsmenu_mc.visible = true;
}
pattern = []; //clears the user array
}
}
}
Easiest way I can think to do this is:
inside your dot movie clip, put a stop() action on the first frame
create your animation on the dot timeline and on the last frame of the animation put another stop().
In your mouse over function, tell the dot to play.
private function addPattern(e:MouseEvent):void
{
var dot:MovieClip = MovieClip(e.currentTarget);
if(dot.currentFrame < 2) dot.play(); //play only if on the first frame
pattern.push(dots.indexOf(dot) + 1); //adds the pattern on mouse over
}
Reset the dots animation
private function stopPattern(e:MouseEvent):void //stops storing the pattern on mouse up
{
for (var i:int = 0; i < dots.length; i++)
{
dots[i].removeEventListener(MouseEvent.MOUSE_OVER, addPattern);
dots[i].gotoAndStop(1); //go back to the first frame
}
checkPattern();
}
Alternatively, if you're just want something simple like a layer of the dot fading in/out or the size of the dot increasing, you could just use a tweening library and tween the appropriate property on mouse over.
If you wanted to draw lines to connect the dots, you could do this:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.Strong;
import flash.display.Shape;
public class Main extends Sprite
{
private var lineContainer:Shape = new Shape();
private var dots:Array = []; // Stores the in stage movieclips
private var pattern:Array = []; //The pattern entered by the user //don't make life hard, just store the object itself instead of the index
private var pass:Array;
public function Main():void
{
dots = [one,two,three,four,five,six,seven,eight,nine]; //add the clips in stage
pass = [one,four,seven,eight,five,two,five]; //The correct pattern to proceed
addChildAt(lineContainer, this.getChildIndex(one)); //the line container right behind the first dot.
addListeners();
}
private function addListeners():void //adds the listeners to each dot
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_DOWN, initiatePattern);
dots[i].addEventListener(MouseEvent.MOUSE_UP, stopPattern); //you could attach this to `this` instead of each dot, same result
}
}
/* Adds a mouse over listener and uses it to add the number of the dot to the pattern */
private function initiatePattern(e:MouseEvent):void
{
pattern = []; //reset array
lineContainer.graphics.clear(); //clear lines
for (var i:int = 0; i < dots.length; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_OVER, addPattern);
}
addPattern(e); //trigger the mouse over for this element
}
private function addPattern(e:MouseEvent):void
{
//if (pattern.indexOf(e.currentTarget) == -1) { //wrap in this if statemnt if only wanted a dot to be selected once (like Android)
pattern.push(e.currentTarget); //adds the pattern on mouse over
drawLines();
var dot:MovieClip = MovieClip(e.currentTarget);
if(dot.currentFrame < 2) dot.play(); //play only if on the first frame
//}
}
private function drawLines():void {
lineContainer.graphics.clear(); //clear the current lines
lineContainer.graphics.lineStyle(5, 0xFF0000); //thickness (5px) and color (red) of the lines
if (pattern.length > 1) { //don't draw if there aren't at least two dots in the pattern
lineContainer.graphics.moveTo(pattern[0].x + pattern[0].width * .5, pattern[0].y + pattern[0].height * .5); //move to first
for (var i:int = 1; i < pattern.length; i++) {
lineContainer.graphics.lineTo(pattern[i].x + pattern[i].width * .5, pattern[i].y + pattern[i].height * .5); //draw a line to the current dot
}
}
lineContainer.graphics.endFill();
}
private function stopPattern(e:MouseEvent):void //stops storing the pattern on mouse up
{
for (var i:int = 0; i < dots.length; i++)
{
dots[i].removeEventListener(MouseEvent.MOUSE_OVER, addPattern);
dots[i].gotoAndStop(1); //go back to the first frame
}
checkPattern();
}
private function checkPattern():void //compares the patterns
{
var pLength:int = pass.length;
var correct:int = 0;
for (var i:int = 0; i < pLength; i++) //compares each number entered in the user array to the pass array
{
if (pass[i] == pattern[i])
{
correct++;
}
}
if (correct == pLength) //if the arrays match
{
//Hides Sign In
MovieClip(root).LockScreen.visible = false;
MovieClip(root).RTID.visible = false;
MovieClip(root).SignIn.visible = false;
//Turns On Main Menu
MovieClip(root).gamemenu_mc.visible = true;
MovieClip(root).biggamesmenu_mc.visible = true;
MovieClip(root).totaltextmenu_mc.visible = true;
MovieClip(root).tmenu_mc.visible = true;
MovieClip(root).smenu_mc.visible = true;
MovieClip(root).optionsmenu_mc.visible = true;
}
pattern = []; //clears the user array
lineContainer.graphics.clear(); //clear the lines
}
}
}

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.

Add an array of Movie Clips to a filter ActionScript 3

i stored 8 mc's in an array an i put them on the stage.
now I want to apply to these mc's a blur effect.
My problem is that i don't know how to apply for every mc the blur effect by clicking on it.
So for example I have all the mc's on the stage and if I click on one of them the clicked one should have the blur effect and so on.
How to apply the filter to the mc's?
Thank you for you time
You can loop through the mc's array and add event listeners on each of them:
var mcArrayLength:int = mcArray.length();
for (var i:int = 0; i < mcArrayLength; i++) {
var mc:MovieClip = mcArray[i] as MovieClip;
mc.addEventListener(MouseEvent.CLICK, onMcClick);
}
and the event handler:
function onMcClick(e:MouseEvent):void
{
var clickedMc:MovieClip = e.currentTarget as MovieClip;
clickedMc.filters = [myBlurFilter];
}
of course, if you wanted to have only one blurred mc at a time, you should keep a reference to it and remove blur once another mc is clicked:
var currentlyClickedMc:MovieClip;
function onMcClick(e:MouseEvent):void
{
var clickedMc:MovieClip = e.currentTarget as MovieClip;
clickedMc.filters = [myBlurFilter];
if (currentlyClickedMc) currentlyClickedMc.filters = [];
currentlyClickedMc = clickedMc;
}
something like this (untested) should work:
package
{
//Imports
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
//Class
public function ClickToBlur
{
//Variables
private var clickableObjects:Array;
//Constructor
public function ClickToBlur(clickableObjects:Array)
{
this.clickableObjects = clickableObjects;
init();
}
//Initialize
private function init():void
{
for each (var object:Object in clickableObjects)
{
object.addEventListener(MouseEvent.CLICK, clickMouseEventHandler);
}
}
//Click Mouse Event Handler
private function clickMouseEventHandler(evt:MouseEvent):void
{
if (evt.currentTarget.filters == [])
{
evt.currentTarget.filters = [new BlurFilter()];
}
else
{
evt.currentTarget.filters = [];
}
}
//Dispose
public function dispose():void
{
for each (var object:Object in clickableObjects)
{
object.removeEventListener(MouseEvent.CLICK, clickMouseEventHandler);
}
}
}
}
just pass your array to a new instance of the class
var ctb:Object = new ClickToBlur(myArrayOfObjects);
and clean up when your done:
ctb.dispose();
since they're all Movie Clips, you should use a Vector instead of an Array.