Change a variable on click actionscript - actionscript-3

I would like to know how I could change a variable on click using actionscript.
I have :
private var test:int = 0;
public function thisIsTest():void{
test = test + 1;
}
<mx:Image left="10" bottom="10" source="#Embed(source='Assets/blabla.png')" click="thisIsTest()" buttonMode="true"/>
I would like to add 1 to the variable test each time I click on the button 'blabla'.
The problem is that it only works once.
Thank you for your help

The simplest method would be to use a MouseEvent listener. You attach the listener to whatever you want to be clicked and tell the listener which function to execute when an event is triggered:
var test:int = 0;
image.addEventListener(MouseEvent.CLICK, thisIsTest);
// Will 'listen' for mouse clicks on image and execute thisIsTest when a click happens
public function thisIsTest(e:MouseEvent):void
{
test = test + 1;
trace(test);
}
// Output on subsequent clicks
// 1
// 2
// 3
// 4
This does mean the image you want to attach the listener to needs to be a display object, like a sprite or movieclip, but this shouldn't be a problem if you're using Flash.
EDIT: Further actions noted in comments.
Import an image into Flash and use it to generate a Sprite or Movieclip and give it an Actionscript link id (like a class name):
// Add the image to the stage
var img:myImage = new myImage();
addChild(img);
// Assign the mouse event listener to the image
img.addEventListener(MouseEvent.CLICK, thisIsTest);

Related

How to load a swf and interact with it?

I have tried SWFLoader, but the problem is the loaded content is MovieClip and I don't know how to interact with it, and the MovieClip#numChildren is zero.
And by the way, I can't pass the flashvars to the swf.
Firstly, you should know that there is no exact answer to your question as it depends on your loaded SWF (you know it or not, its display list, ...) but I'll put a simple example to explain things and you have to adapt it to your case.
For this example, let's say that we have a very simple SWF (the loaded SWF) which contain a TextField (called txt_url) and a button (a MovieClip, called btn_go).
The btn_go button will open the URL entered in the txt_url TextField.
For our second SWF (the loader), we will use a Loader object to load our first one (which is in this case will be the Loader.content) and then we will set the URL (the txt_url text) and trigger the click event on the btn_go button.
So here is an example of the code of our loader.swf :
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, on_SWFLoad);
loader.load(new URLRequest('loaded.swf'));
addChild(loader);
function on_SWFLoad(e:Event): void
{
// get our loaded SWF
var loaded_swf:DisplayObjectContainer = DisplayObjectContainer(loader.content);
// because we know our target objects, we can use "getChildByName()"
// set the URL
TextField(loaded_swf.getChildByName('txt_url')).text = 'http://www.example.com';
// open the URL in the browser by triggering the click event on the "btn_go" button
MovieClip(loaded_swf.getChildByName('btn_go')).dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
This example will directly set and open the URL in the browser after loading the SWF, of course we can execute that action after clicking a button or something else but it's just a simple example to show you how you can do ...
Now, the problem is when we don't know anything about the loaded SWF and its children (names, depths, ...), in this case we should do more effort to do what we want : we should traverse the entire display list of the loaded SWF to identify the target objects.
Returning to our example and let's say that we only know that there are a TextField and a button in the stage, so our code can be like this for example :
function on_SWFLoad(e:Event): void
{
var loaded_swf:DisplayObjectContainer = DisplayObjectContainer(loader.content);
var num_children:int = loaded_swf.numChildren;
for(var i:int = 0; i < num_children; i++)
{
var child:DisplayObject = loaded_swf.getChildAt(i);
if(child is TextField)
{
trace(child.name); // gives : txt_url
TextField(child).text = 'http://www.example.com';
}
else
{
if(child.hasEventListener(MouseEvent.CLICK))
{
trace(child.name); // gives : btn_go
child.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
}
}
}
Again, it's a very simple example just to show how we can proceed ...
...
Then about passing values (params) between SWFs, take a look on my answer of this question where you have a little example for that.
For more about Display programming (display list, display object, display object container, ...) take a look here.
Hope that can help.

Unable to reference MovieClip inside Button AS3

I have this annoying issue that I hope someone might be able to help me with.
I have a mute button that I created and I have another movieclip inside of that button. All I want it to do is when I toggle the mute the movieclip inside will go to the according frame.
However, every time I try to call the movieclip inside of the button, this error comes up:
Access of possibly undefined property mcMuteToggle through a reference with static type flash.display:SimpleButton.
The instance name for the movieclip within is "mcMuteToggle".
Why not make movieClips that act like buttons?? Since I dont think actual button (simpleButton) types can deal with sub-MovieClips (especially if they too have code). Even if possible don't do it, I can predict a mess whereby Button does things it shouldn't do depending on what code you have in those MClips.
Try an alternate button method, just for a test... You didnt show any test code to work with so I will make assumptions..
1) Make a shape (rectangle?) and convert to MovieClip (or if all coded, then addchild shape to new MovieClip). Let's assume you called it mc_testBtn.
2) Make that MC clickable by coding mc_testBtn.buttonMode = true;
3) Add your mcMuteToggle inside the mc_testBtn
(or by code: mc_testBtn.addChild(mcMuteToggle);
Now you can try something like..
mc_testBtn.addEventListener (MouseEvent.CLICK, toggle_Mute );
function toggle_Mute (evt:MouseEvent) : void
{
if ( whatever condition )
{
mc_testBtn.mcMuteToggle.gotoAndStop(2); //go frame 2
}
else
{
mc_testBtn.mcMuteToggle.gotoAndStop(1); //go frame 1
}
}
This is likely due to strict mode. You can either disable it in the ActionScript settings dialog, access it with a different syntax myButton['mcMuteToggle'], or make a class for the symbol that includes a property mcMuteToggle.
You can also check to make sure the symbol is actually on the stage and that clip is actually in the button:
if('myButton' in root) {
// ...
}
if('mcMuteToggle' in myButton) {
// ...
}
i think u just overwrite that codes. You u can use something like this:
var soundOpen:Boolean = true;
var mySound:Sound = new Sound(new URLRequest("Whatever your sound is"));
var mySc:SoundChannel = new SoundChannel();
var mySt:SoundTransform = new SoundTransform();
mySc = mySound.play();
mcMuteToggle.addEventListener(MouseEvent.CLICK, muteOpenSound);
function muteOpenSound(e:MouseEvent):void
{
if(soundOpen == true)
{
mcMuteToggle.gotoAndStop(2);
/*on frame 2 u need to hold ur soundClose buton so ppl can see :)*/
soundOpen = false;
mySt.volume = 0;
mySc.soundTransfrom = st;
}
else
{
mcMuteToggle.gotoAndStop(1);
soundOpen = true;
mySt.volume = 1;
mySc.soundTransfrom = st;
}
}
This is working for me everytime. Hope u can use it well ;)

Making multiple objects draggable

I have about 50 symbols that I want to make draggable. Nothing fancy, just the ability to click it and drag it to a different location.
I found as3 code for doing so but when I paste it into my file it gives me errors:
**Error** Scene=Scene 1, layer=Units, frame=1:Line 9: The class or interface 'MouseEvent' could not be loaded.
function mouseDownHandler(evt:MouseEvent):void {
That code is:
// Register mouse event functions
fighter_uk.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
fighter_uk.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
fighter_uk.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
fighter_uk.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
// Define a mouse down handler (user is dragging)
function mouseDownHandler(evt:MouseEvent):void {
var object = evt.target;
// we should limit dragging to the area inside the canvas
object.startDrag();
}
function mouseUpHandler(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
}
I'm using flash pro 8, so I tried finding as2 code but couldn't find it.
Also, is there an 'easy' way to code all 50 objects?
I think you're trying to compile AS3 code with AS2 compiler. Try changing your compilation settings to target AS3.
Also you may need to include the class import at the top of your code:
import flash.events.MouseEvent;
To drag 50 objects, add them all on the same container sprite and add the listener to the container sprite only:
var holder:Sprite = new Sprite();
for ( var i:int = 0, l:int = 50; i < l; i++ ) {
var dragee:YOUR_CUSTOM_OBJECT = new YOUR_CUSTOM_OBJECT();
holder.addChild(dragee);
}
addChild(holder);
holder.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
holder.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
holder.addEventListener(Event.MOUSE_LEAVE, mouseUpHandler);
var currentDragee:YOUR_CUSTOM_OBJECT = null;
function mouseDownHandler(evt:MouseEvent):void {
currentDragee = evt.target as YOUR_CUSTOM_OBJECT;
if ( currentDragee !== null ) {
currentDragee.startDrag();
holder.addChild(currentDragee); // bring current to front position
}
}
function mouseUpHandler(evt:Event):void {
if ( currentDragee !== null ) currentDragee.stopDrag();
currentDragee = null;
}
YOUR_CUSTOM_OBJECT being the object class you need to drag. Hope it helps!
This page seems to have the answers you are looking for (AS2 drag and drop). If you've already seen it, you'll need to explain why it's not good enough for your needs.
If you want to drag/drop multiple instances in AS2, you can still add the code to the movieClip symbol, export it from the library and load the instances up using attachMovie (all 50 of them). If they are all different, then attach the code as necessary to the clips themselves, or to some function elsewhere that will capture all the clicks and decide what was clicked. This is all very doable in AS2.
Remember you can use your onClipEvent(load) function to set up a lot of the initial lifting.
Here's a sample I made in AS2 for making a node tree. It's all draggable (mouse drag) and zoomable (with mouse Wheel). You can add nodes by clicking on the little down arrow in the node box. Each node is listening for the mouse.
You'll want to look at this section for the most part:
// Enable drag on button press
on (press)
{
startDrag(this);
}
// Stop the drag on release of mouse button
on (release)
{
stopDrag();
}
Besides this, I'm not really sure how your setup looks, so I hope this helps get the ball rolling. (Check the link, there's lots of little gems in there).
Flash Professional 8 only supports ActionScript 2 & 1
You can follow this official URL and learn how to do that in ActionScript 2, but I extremely recommend you to work with ActionScript 3.

Turn image array images to buttons AS3

I'm creating an app with a search function. I display the images by loading from the array the one's which match the search criteria. All the images are loaded from the library. I want to be able to click on an image as though it were a button. Once I click I want to goto frame 3 and change a variable integer to say which image was clicked on so that I can display the information about the photo in frame 3. Can I do this using an event listener say
imagesArray[i].addEventListener(MouseEvent.CLICK, imageClick);
function imageClick(event:MouseEvent):void
{
gotoAndStop(3);
current = i;
}
or similar,
Thanks
Yes, but it won't be as easy. First, Bitmaps do not process events, so you can't assign a listener directly to a Bitmap object. Next, there is no "i" available in such a construction, you have to determine that "i" by yourself. To do that, you parse event.target property, which is the object that's been clicked. You wrap each Bitmap object into a separate Sprite object, assign listeners to these sprites, then you parse event.target to get the relevant object reference out of it, grab the index via indexOf() call, and assign it to global current variable.
for (i=0;i<imageArray.length;i++) {
var sp:Sprite=new Sprite();
sp.addChild(imageArray[i]);
// position "sp" correctly here
addChild(sp);
sp.addEventListener(MouseEvent.CLICK, imageClick);
}
function imageClick(e:Event):void {
var content=e.target.getChildAt(0); // the object that was wrapped
var i:int=imageArray.indexOf(content);
if (i==-1) return; // OW, out of array
current=i;
gotoAndStop(3);
}
I'm not so sure that setting "current" to "i" would work as the function wouldn't be running at the same time as the for loop.
I'm assuming that because you're using the [i] that you've added the event listeners in a for loop?
What you could do is:
for (var i:int = 0; i < (howeverManyTimesToRun); i++)
{
imagesArray[i].addEventListener(MouseEvent.CLICK, imageClick);
imagesArray[i].myIndex = i;
}
And then in your function (outside of the for loop)
function imageClick (e:MouseEvent) {
gotoAndStop(3);
current = e.currentTarget.myIndex;
}
Also in your for loop you might want to add
imagesArray[i].buttonMode = true;
To change the mouse cursor to a hand when their mouse goes over your image.

Bubble click event in swf

I try to add a MovieClip to an existent SWF on the fly - inject an small code who do something like:
this.obj = new MovieClip(); // it is inside an object
obj.name = 'FLOOR';
obj.graphics.beginFill(0xFFFFFF, 0);
obj.graphics.drawRect(0,0,self.width, self.height);
obj.graphics.endFill();
obj.buttonMode = true;
self.addChildAt( floorLayerMC , 0); /* self is an reference for the this keyword, reference for the entire swf */
My question is: this SWF has many elements like images and textfields, and some of this elements has no event handler for click. I Need to find a way to "redirect" all of the events to my "FLOOR" element, using something like bubbling the event.
Of course, I can add the FLOOR in top of any elements BUT I have some elements with click handler. I can't ignore all of the elements. So my problem is:
if I click over an MovieClip with click handler, perform the original action.
if I click over an MovieClip without click handler, perform the FLOOR action.
I can't add a event handler in all of the elements.
Any Idea?
Listen for a click on the container movieclip's own stage (the movieclip that contains the FLOOR). In the handler method for the click event, do a hit test using hitTestPoint with the mouseX and MouseY of the container movieclip, and if the mouse is over any clickable objects, ignore the stage click. Store all the objects that are clickable in an array to do that test.
This code is untested but it would go something like this:
var exemptArray:Array = [ btn_mc1, btn_mc2, btn_mc3 ];
containerMC.stage.addEventListener(MouseEvent.CLICK, onClickMyMC);
function onClickMyMC( event:Event ):void
{
for(var i:int = 0; i < exemptArray.length; i++)
{
if( exemptArray[i].hitTestPoint(containerMC.mouseX, containerMC.mouseY) )
{
// do nothing, ignore the stage click ( and let the object with the click respond )
break;
}
else
{
// respond to the stage click
}
}
}
To build the exemptArray without knowing what objects are clickable ahead of time:
( untested but should be close enough to give you an idea ).
var exemptArray:Array = buildExemptArray();
function buildExemptArray():Array
{
var arr:Array = [];
for(var j:int = 0; j < containerMC.numChildren; j++)
{
if( containerMC.getChildAt(i).hasEventListener(MouseEvent.CLICK) )
{
arr.push( containerMC.getChildAt(i) );
}
}
return arr:
}
EDIT TO ANSWER QUESTION IN COMMENTS:
this.addEventListener(MouseEvent.CLICK, onClick) will add a click event to the whole object, children included.
this.stage.addEventListener(MouseEvent.CLICK, onClick) will add a click only to the movieclip's stage, not its children as well.
In as3 all movieclips have a stage property. If you wrote on the main timeline this.stage.addEventListener(MouseEvent.CLICK, onClick); that would be adding a stage click to the whole swf. But, if you wrote something like myMC.stage.addEventListener(MouseEvent.CLICK, onClick); it would only add a click to that movieclip's stage (myMC's stage). Since stage is below the display list, you can capture a click there in any movieclip. If you don't have access to all the objects that have mouse events ahead of time, you could loop through all the container's children and check if they have a mouseEvent with .hasEventListener(MouseEvent.CLICK);, create your exemptArray from that, then use the same logic above to ignore items in the exemptArray.