How to select multiple objects on MOUSE_OVER during a MOUSE_DOWN - actionscript-3

Lets say I have 30 objects created in for loop, added to a container.
Objects stop on frame 1. I have added event listeners to the objects as you can see below, and when I click any object inside container, it goes to frame 2 and play.
for (var i:int=0; i < 30; i++)
{
var object = new Object1();
object.gotoAndStop(1);
object.addEventListener(MouseEvent.CLICK, myFunction);
container.addChild(object);
}
private function myFunction(e:MouseEvent):void
{
e.currentTarget.gotoAndPlay(2);
}
So I have to click each object to send it on frame 2,
I also tried ROLL_OVER, everything is same but CLICK is changed to ROLL_OVER inside for loop.
What I want is to click, and then mouse over object so they go to frame 2 and play.
The problem is that I need to use MOUSE_DOWN event, I have tried to set MOUSE_DOWN instead of CLICK or ROLL_OVER, but it does not work. If I want to send objects to frame 2 (using MOUSE_DOWN), I need to click each of them, there is no difference between MOUSE_DOWN and CLICK in this case.
As someone who does not know much about mouse events, I'm wondering why roll over and click works, but mouse_down does not?

I think I see what you're trying to do... you want to press the mouse to start drawing over a bunch of sprites, each one goes to frame two when you mouse over it, but only if the mouse button is pressed, right?
try something like this
container.addEventListener(MouseEvent.MOUSE_DOWN, setMouseDown);
container.addEventListener(MouseEvent.MOUSE_UP, setMouseUp);
private var mouseIsDown:Boolean = false;
private var currentSprite:Sprite;
for (var i:int=0; i < 30; i++)
{
var object = new Object1();
object.gotoAndStop(1);
object.addEventListener(MouseEvent.MOUSE_OVER, myFunction);
object.mouseChildren = false;
container.addChild(object);
}
private function setMouseDown(e:MouseEvent){
mouseIsDown = true;
setActive(currentSprite);
}
private function setMouseUp(e:MouseEvent){
mouseIsDown = false;
}
private function myFunction(e:MouseEvent){
currentSprite = e.target;
if(mouseIsDown){
setActive(currentSprite);
}
}
private function setActive(target:Sprite){
target.gotoAndPlay(2);
}

Related

disable a button after click In as3

I am pretty new to as3 and tried searching around for an answer to my question but it seems nothing works. I have an xml loaded file where when the user clicks the correct option (of 4) they get a point scored. I'm trying to disable the button after it has been clicked once but this is not happening. Any help would be greatly appreciated.
Here is the section I have.
function setupButtons():void {
for (var obj:Object in buttons)
{
buttons[obj].addEventListener(MouseEvent.CLICK, checkAnswer);
}
buttons[obj].addEventListener(MouseEvent.MOUSE_UP,disableBtns);
}
function disableBtns(evt:MouseEvent):void {
for (var obj:Object in buttons)
evt.currentTarget.removeEventListener(MouseEvent.MOUSE_UP,disableBtns);
buttons[obj].enabled = false;
}
Here are some comments next to your original code to help explain what is likely happening:
function setupButtons():void {
//you're adding a click listener for every object in `buttons`
for (var obj:Object in buttons)
{
buttons[obj].addEventListener(MouseEvent.CLICK, checkAnswer);
}
//this next line seems out of place,
//it is NOT a part of your for loop above so it will only run once,
//The value of obj will be the LAST item in the for loop above
buttons[obj].addEventListener(MouseEvent.MOUSE_UP,disableBtns);
}
function disableBtns(evt:MouseEvent):void {
//you don't have curly braces on this next for loop line
//this means it's only going to run the line immediately following the loop as part of the loop.
for (var obj:Object in buttons)
//your attempting to remove the same listener over and over again (since this line is in a loop)
evt.currentTarget.removeEventListener(MouseEvent.MOUSE_UP,disableBtns);
//this next line is not part of the loop above.
//I imagine you only want to disable the button that was clicked (evt.currentTarget)
//This will only disable whatever the last value of obj was in the loop above
buttons[obj].enabled = false;
}
Now, here is a simple code refactoring that may help:
//first, just have one click listener for each button, forget the mouse up listener
function setupButtons():void {
for (var obj:Object in buttons){
buttons[obj].addEventListener(MouseEvent.CLICK, btnClick);
}
}
function btnClick(evt:MouseEvent):void {
//If buttons are of the SimpleButton class, you can just disable them
evt.currentTarget.enabled = false;
//OR, if the buttons are not of the SimpleButton class
evt.currentTarget.mouseChildren = false;
evt.currentTarget.mouseEnabled = false;
//OR, just remove the click listener
evt.currentTarget.removeEventListener(MouseEvent.CLICK, btnClick);
//run the checkAnswer function
checkAnswer(evt);
}
To disable all buttons when any 1 is clicked, you could do this:
function btnClick(evt:MouseEvent):void {
for (var obj:Object in buttons){
buttons[obj].removeEventListener(MouseEvent.CLICK, btnClick);
}
//run the checkAnswer function
checkAnswer(evt);
}

Creating a vector array of movie clips AS3

I have several movie clips on the stage of my main .fla named btn1-btn7 which will act as buttons. I have a class file named Functions.as where an event listener is created when a button is clicked. onButtonClicked is just going to a frame on the timeline.
obj.addEventListener(MouseEvent.CLICK, onButtonClicked);
I would like the ability to set the buttonMode, visibility, etc. of all of the buttons simultaneously. I have been looking into this for a few hours and am not able to find any solutions. I am now looking into adding them to a vector (which is a new concept for me), but I am not sure how to go about executing this properly. This is what I have so far.
public var buttons:Vector.<MovieClip > = new Vector.<MovieClip > ();
function addButtons()
{
buttons.push(btn1,btn2,btn3,btn4,btn5,btn6,btn7);
for (var i:int; i<buttons.length; i++)
{
trace(buttons[i].name);
}
}
How would I go about, for example, adding the event listener to all of the objects? I will also be setting the buttonMode to true, and making them all invisible simultaneously. I don't even know if it's possible to accomplish this. Thank you in advance for any suggestions.
I'm going to asume that you use timeline code, and have instances of the buttons already placed on the stage. So, first, create the vector:
var _btns:Vector.<MovieClip> = new Vector.<MovieClip>;
_btns.push(btn1,btn2,btn43....) //add all the buttons
Than, you can init the properties of all the buttons:
var _mc:MovieClip;//helper var
for(var i:int=0,i<_btns.length;i++)
{
_mc = _btns[i];
_mc.visible = false;
_mc.buttonMode = true;
_mc.addEventListener(MouseEvent.CLICK, onClick);
}
Then, the event handler:
function onClick(e:MouseEvent):void
{
for(var i:int=0,i<_btns.length;i++)//reset all the buttons
{
_btns[i].visible = false;
}
_mc = MovieClip(e.eventTarget);
_mc.visible = true; //make visible the clicked one
}
You just need to do what you are doing with the .name property in your example code. You need to loop thru every single button in your array (or vector, if you prefer). Here is an example how to set the property of buttonMode:
function setButtonMode(b:Boolean):void {
for(var i:int=0; i<buttons.length; i++) {
var btn:MovieClip = buttons[i]; //store the current reference in a var for faster access
btn.buttonMode = b;
btn.mouseChildren = !b;
}
}

AS3 / removeChild/addChild by clicking button

I have several movie clips into a frame the size of the stage and I have to switch through a button between those pages.
So if I press button, should all the other frames removeChild and the one where he is called to go addChild.
Edit: I have the actionscript placed in the timeline of the movieClip so the button is not on the stage but I put in the movie clip using action script.
So what DodgerThud showed here is not possible because the button has changed since that is in the movieClip('s).
I think I need to place the same code in every movieClip.
Put all of your MovieClips into a Vector or Array.
When you click the button, you should cycle through the Vector/Array and check if the MovieClip is currently on stage with contains(DisplayObject). If the Movieclip IS currently on the stage, remove it and add another one to the stage, for example, the next one in the Vector/Array.
var vec:Vector.<MovieClip> = new Vector.<MovieClip>
vec[0] = new MovieClip();
vec[1] = new MovieClip(); //example with MovieClips
vec[2] = new MovieClip();
addChild(vec[0]); //add one of the MovieClips to stage
button.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
for(var i:int = 0; i < vec.length; i++) //go through the Vector one by one
{
if(contains(vec[i]) //if the Object at position i in the Vector is on stage
{
removeChild(vec[i]); //remove the Object
var next:int = i; //create a temporary holder
if(next == vec.length) //check if the displayed Object was the last in the list
{
next = 0; //if so, set to 0
}else{
next++; //otherwise, only add 1
}
addChild(vec[next]); //add the next Object to the stage. If the removed Object was the last in the Vector, it'll add the first Object in the Vector to the list
break; //escape the for loop, otherwise it'll always only show the last Object
}
}
}
Something like ...
function tueHandler(e:MouseEvent):void
{
while(numChildren > 0)
removeChildAt(0);
addChild(whatever);
}

ActionScript 3 Tree - Node Value Pop-up After Mouse Hovers for "X" Seconds

I'm fairly new to ActionScript 3 (so I’m sorry if this is a naïve question) and I'm working on an existing project that uses a "Tree" menu. Each node in the tree represents a section in the application. Unfortunately, some of the section names (which are what's displayed in the node’s display value) are fairly long and requires the text to be truncated. As a result, there are times where the section names are cut off. To get around this, we want to give users the ability to see the entire title by moving their mouse cursor over the node for “X” seconds in which case a small pop-up renders the node's label.
Example
public var menuTree:Tree;
public function DoSomething(){
menuTree.addEventListener(ListEvent.ITEM_ROLL_OVER, onListItemRollover, false, 100);
}
private function onListItemRollover(event:ListEvent):void {
//IF MOUSE CURSOR IS STILL OVER NODE FOR "X" SECONDS DISPLAY NODE'S LABEL IN POP-UP
}
Thanks all in advance!
Without knowing more about your setup, I would probably setup something like this:
var timer:Timer;
var currentItem:*
for each (var node:* in menuTree) {
node.addEventListener(MouseEvent.MOUSE_OVER, overHandler);
node.addEventListener(MouseEvent.MOUSE_OUT, outHandler);
}
function overHandler(event:MouseEvent):void {
stopTimer();
currentItem = event.currentTarget;
timer = new Timer(2000, 1);
timer.addEventListener(TimerEvent.TIMER, showPopup);
timer.start();
}
function outHandler(event:MouseEvent):void {
stopTimer();
}
function showPopup(timerEvent:TimerEvent):void {
stopTimer();
//show popup code here
//use currentItem
}
function stopTimer():void {
if (timer) {
timer.stop();
timer.removeEventListener(TimerEvent.TIMER, showPopup);
}
}
So instead of adding the event listener to the menuTree you're going to loop though each item in the tree and add a listener to that item. Then when the user rolls over any given item it starts a timer that after 2 seconds will run a function to show the popup.

ActionScripting Issue: adding/removing children

I have three movie clips all linked to the stage and I want them to behave like a button/ But I am not using a button because I have not found a way to have each part (up, over, down, hit) be animated and not just change when the mouse is in use with it. So far I have been able to have all three appear on my stage and show when I have the mouse over and as well when I click, but I think I'm doing something wrong with removeChild. Each MC should appear one at a time and now all three show up when I hover over and seem to "flash". Here's my code:
var mainMoon:swayingMoon = new swayingMoon();
mainMoon.x = 50;
mainMoon.y = 10;
addChild(mainMoon);
var hoverMoon:glowMoon = new glowMoon();
hoverMoon.x = 50;
hoverMoon.y = 10;
var movieMoon:clickedMoon = new clickedMoon();
movieMoon.x = 50;
movieMoon.y = 10;
mainMoon.addEventListener(MouseEvent.ROLL_OVER, showHoverMoon);
mainMoon.addEventListener(MouseEvent.ROLL_OUT, hideHoverMoon);
hoverMoon.addEventListener(MouseEvent.CLICK, startMovieMoon)
function showHoverMoon(event:MouseEvent):void
{
addChild(hoverMoon);
}
function hideHoverMoon(event:MouseEvent):void
{
removeChild(hoverMoon)
}
function startMovieMoon(event:MouseEvent):void
{
addChild(movieMoon);
}
I don't recommend doing it this way as it can make things needlessly complex. For a single button now, you have 3 times as many movie clips/sprites, add/remove child event handlers, and other variables to check/debug for. Multiply this by however many buttons you have.
Instead, I'd recommend using or extending the SimpleButton{} class or writing your own class to encapsulate the behaviour.
SimpleButton class: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/SimpleButton.html
I think you should encapsulate your three moon states into a separate MovieClip that will control all the moon phase changing by itself. If it's already so, fine. The general principle with such a MovieClip-Button type objects is that the listener is assigned to the parent instance, not the parts of that button.
public class Moon extends Sprite {
private var upState:swayingMoon=new swayingMoon();
private var overState:glowMoon=new glowMoon();
private var downState:clickedMoon=new clickedMoon();
private var areWeClicked:Boolean;
private var areWeOver:Boolean;
public function Moon() {
areWeClicked=false;
areWeOver=false;
addChild(upState);
addEventListener(MouseEvent.ROLL_OVER, showHoverMoon);
addEventListener(MouseEvent.ROLL_OUT, hideHoverMoon);
addEventListener(MouseEvent.CLICK, showClickedMoon);
addEventListener(Event.COMPLETE, hideClickedMoon);
}
private function showHoverMoon(e:MouseEvent):void {
areWeOver=true;
if (areWeClicked) return;
removeChild(upState);
addChild(overState);
}
private function hideHoverMoon(e:MouseEvent):void {
areWeOver=false;
if (areWeClicked) return;
removeChild(overState);
addChild(upState);
}
private function showClickedMoon(e:MouseEvent):void {
if (areWeClicked) {
downState.gotoAndPlay(1);
return;
}
if (overState.parent) removeChild(overState); else removeChild(upState);
addChild(downState);
downState.gotoAndPlay(1); // your clicked moon seems to be a playing MC, so starting it over
areWeClicked=true;
}
private function hideClickedMoon(e:Event):void {
if (e.target!=downState) return; // not our event
if (!areWeClicked) return;
areWeClicked=false;
removeChild(downState);
if (areWeOver) addChild(overState); else addChild(upState);
}
}
Now, your parent class is controlling what happens and when. I was under assumption that your clickedMoon MC will only play once fully, then dispatch an event Event.COMPLETE to itself, so that its parent will get notified and will act.
Originally, your event listener structure prevented you from hiding mainMoon MC, otherwise your other listener will never act, now you are using parent object to listen to events, and can safely remove parts of your moon.
Just for a custom button you are going too much complex way. one movieClip is enough for create the button. First create a movieClip and inside that movieClip's timeline create two more frame for 'hover' and click effect. here is little bit of code to start.
var myButton_btn:CustomButton = new CustomButton();
addChild(myButton_btn);
myButton_btn.x = 100;
myButton_btn.y = 100;
myButton_btn.addEventListener(MouseEvent.ROLL_OVER, onOver);
myButton_btn.addEventListener(MouseEvent.ROLL_OUT, onOut);
myButton_btn.addEventListener(MouseEvent.CLICK, onClick);
function onOver(event:MouseEvent):void {
//trace('over');
event.target.gotoAndStop('hover');
}
function onOut(event:MouseEvent):void {
//trace('normal');
event.target.gotoAndStop('normal');
}
function onClick(event:MouseEvent):void {
//trace('click');
event.target.gotoAndStop('click');
}