Action Script 3.0 Mouse Event in a class package - actionscript-3

am having problem with using mouse click event inside a class, i am an absolute beginner to Action Script.
what i want is that if i click the btn_MClick button it should run the script, but everytime i click it i get error message that btn_MClick is undefined.
btn_MClick is on stage and with the instance name if btn_MClick
public class gunShip1 extends MovieClip
{
var moveCount = 0;
public function gunShip1()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveGunShip1);
stage.addEventListener(KeyboardEvent.KEY_DOWN, ShootGunShip1)
btn_MClick.addEventListener(MouseEvent.MOUSE_DOWN.KEY_DOWN, ShootGunShip1);;
}
function ShootGunShip1(evt: MouseEvent)
{
var s_Bullet:survBullet = new survBullet();
var stagePos:Point = this.localToGlobal (new Point(this.width / 2-10, this.height));;
s_Bullet.x = stagePos.x;
s_Bullet.y = stagePos.y;
parent.addChild(s_Bullet);
//play sound
var gun_sound:ricochetshot = new ricochetshot();
gun_sound.play();
}
}
Please, i have absolutely no idea what to do, and somehow it feels like the whole process is wrong.

Your class gunShip1 does not have the property btn_MClick, the root, or document class does.
Basically what's happening is that you've placed your button on the stage, which makes it an instance that belongs to the root container. At the moment, you're trying to refer to the button as a property of gunShip1.
What you should really do here is have the button click managed separately to gunShip1, and have that separate code invoke methods of gunShip1. For example, you could have this in your document class:
public class Game extends MovieClip
{
private var _ship:gunShip1;
public function Game()
{
_ship = new gunShip1();
// The Document Class will have reference to objects on the stage.
btn_MClick.addEventListener(MouseEvent.CLICK, _click);
}
private function _click(e:MouseEvent):void
{
_ship.shoot();
}
}
And then your updated shoot method in gunShip1:
public function shoot():void
{
var s_Bullet:survBullet = new survBullet();
var stagePos:Point = this.localToGlobal (new Point(this.width / 2 - 10, this.height));
s_Bullet.x = stagePos.x;
s_Bullet.y = stagePos.y;
parent.addChild(s_Bullet);
var gun_sound:ricochetshot = new ricochetshot();
gun_sound.play();
}
The idea is that the gunShip1 should not be responsible for dealing with user input (mouse, keyboard, etc). Instead, that should be a separate class which informs gunShip1 that it should do something.

Related

AS3 : How to identify which button was pressed?

I have a MovieClip with a button inside it named t_bt. I have exported that MovieClip to action script and gave it a class name of e_panel . I created 50 instances of e_panel to stage with this code:
var e_p_y:Number=0;
for ( var i:Number=1;i<=50;i++)
{
var e_p:MovieClip = new e_panel();
e_p.x = 50;
e_p.y = e_p_y;
e_p.t_bt.addEventListener(MouseEvent.MOUSE_UP, f1);
addChild(e_p);
e_p_y = e_p_y+105;
}
now I want identify which button was pressed by user in function f1.
function f1(event:MouseEvent):void
{
//...what should I write here?
}
Every event has a property called currentTarget, which will be a reference to the object you added the event listener to.
So in your case:
function f1(event:MouseEvent):void
{
var t_bt:DisplayObject = event.currentTarget as DisplayObject; //would be the t_bt instance that was clicked (typed as a basic object)
var e_p:MovieClip = DisplayObject(event.currentTarget).parent as MovieClip //would be the e_p of the item clicked
//so if you wanted to do something like make the whole panel half transparent once clicked
e_p.alpha = .5;
//if you wanted to get the index of the button clicked
trace("Button Clicked: ", e_p.parent.getChildIndex(e_p));
}
In contrast, the target property of an event is the actual displayObject that was clicked (which could be the same as currentTarget or a child of the currentTarget)
e_panel clip must have an associated E_Panel class that extends MovieClip and (for example) adds an index property to hold the index of the item.
Then, on f1 you could do:
function f1(event:MouseEvent):void
{
var e_panel:E_Panel = event.currentTarget.parent as E_Panel;
trace(e_panel.index);
}
Remember to set index property upon movie clip creation
Hope it helps
Extra info
Create this a class for E_Panel and link it to movieClip with library properties
public class E_Panel extends MovieClip
{
private var _index:int;
public function E_Panel(index:int)
{
super();
_index = index;
}
public function get index():int {
return _index;
}
}
Then in your code:
var e_p:E_Panel = new e_panel(i); //"i" is the iteration counter
e_p.x = 50;
... //Etc
Try this Code::
var e_p_y:Number=0;
for ( var i:Number=1;i<=50;i++)
{
var e_p:MovieClip= new e_panel();
e_p.x=50;
e_p.y=e_p_y;
e_p.t_bt.addEventListener(MouseEvent.MOUSE_UP, f1);
addChild(e_p);
e_p_y=e_p_y+105;
e_p.name= i+'';
}
Now write this code in f1 function::
function f1(event:MouseEvent):void
{
trace(event.currentTarget.name);
}

want to change the code actionscript2 to actionscript3?

i am newbie to flash.i need to change the below actionscript code to actionscript 3.0 code.
i am currently working on drag and drop. so i want to duplicate the movieclip while dragging i found the code on internet but it is actionscript 2.0 so please convert it to as3. the box is a instance name of a movieclip.
the code blocks are:
var num:Number = 0
box.onPress = function(){
num++
duplicateMovieClip(box ,"box"+num, _root.getNextHighestDepth())
_root["box"+num].startDrag();
}
box.onReleaseOutside = function(){
trace(_root["box"+num])
stopDrag();
}
If you dont want to use seperate .as file, follow this steps:
1- assign AS linkage to box movieClip (in library panel):
2- Select frame 1 on the timeline, and paste this code in the Actions panel:
var boxes:Array=[];
//var box:Box=new Box();
//addChild(box);
box.addEventListener(MouseEvent.MOUSE_DOWN,generateBox);
function generateBox(e:MouseEvent):void{
var newBox:Box=new Box();
newBox.x = e.target.x;
newBox.y = e.target.y;
newBox.startDrag();
newBox.addEventListener(MouseEvent.MOUSE_UP,stopD);
newBox.addEventListener(MouseEvent.MOUSE_DOWN,startD);
boxes.push(newBox);
addChild(newBox);
}
function startD(e:MouseEvent):void{
e.target.startDrag();
}
function stopD(e:MouseEvent):void{
e.target.stopDrag();
}
Unfortunately, there's no duplicateMovieClip analog in AS3, so you'll have to create a Class for your box movieClip template. Let's say it will be called BoxTemplate. (You can google how to create Classes for your library object). Add a Class with this name and add this code (event subscription in the constructor and a private event listener). You'll get something like this:
package
{
public class BoxTemplate
{
public function BoxTemplate()
{
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
private function onMouseUp(e:MouseEvent):void
{
stopDrag();
}
}
Leave your present instance of this symbol on the stage. This is your code in the frame:
import flash.event.MouseEvent
box.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
var newBox:BoxTemplate = new BoxTemplate();
newBox.x = e.target.x;
newBox.y = e.target.y;
addChild(newBox);
newBox.startDrag();
}
It will allow you to infinitely clone your boxes. Of course, you can add all of them in the array to keep the references.

my dynamically added movieclips have a name of "instance XX"

There are a couple things going on here that I dont fully understand. I have created a custom class that extends MovieClip to give some custom properties and create a geometric shape inside of the created MovieClip
package com.hyatt
{
import flash.display.*;
import flash.geom.*;
public class mapPin extends MovieClip
{
public var spirit:String;
public var callName:String;
public var hotelName:String;
public var city:String;
public var s:String;
public var zip:String;
public var country:String;
public var brand:String;
public var featured:Boolean;
public var horizon:Boolean;
private var _mc1:MovieClip = new MovieClip();
public function mapPin(_brand:String)
{
brand = _brand;
switch (_brand)
{
case "Andaz":
pinCircle(0xff0000);
break;
case "Grand Hyatt":
pinCircle(0x0000ff);
break;
case "Hyatt":
pinCircle(0x4600f0);
break;
}
}
private function pinCircle(color:uint):void
{
_mc1.graphics.beginFill(color);
_mc1.graphics.drawCircle(0,0,20);
this.addChild(_mc1);
_mc1.graphics.endFill();
}
}
}
Then I'm adding an couple instances of the mapPin class to a container movieclip on my stage and adding an event listener to that container clip.
var myTest1:mapPin = new mapPin("Andaz");
myTest1.brand = "Andaz";
container_mc.addChild(myTest1);
myTest1.name = "myTest1" //this is added purely for testing the "instance xx", same result
myTest.x = 100;
myTest.y = 100;
var myTest2:mapPin = new mapPin("Hyatt");
container_mc.addChild(myTest2);
myTest2.brand = "Hyatt";
myTest2.x = 400;
myTest2.y = 400;
container_mc.addEventListener(MouseEvent.CLICK, pinClicked);
finally I'm trying to be able to access the properties (the only one set thusfar is "brand") of the mapPin that is clicked.
function pinClicked(e:MouseEvent):void
{
trace(e.target.name); // traces "instance xx" instead of "myTest1"
trace(e.target.brand); // traces "undefined"
}
I can add the mapPin instances, and adjust their x and y though i cannot reference the custom class properties like "brand" and their name becomes a generic instance name. What am I missing? There are going to be upwards of 500 of these items added and I want to be able to pull information from them based upon a users click.
I'd have to see your mapPin class to be sure, but I think that the DisplayObject that is dispatching the event, is a child of mapPin.
To fix this, inside your mapPin class constructor add this line :
mouseChildren = false;
That will specify that children shouldn't receive clicks/dispatch mouse events.
currentTarget is the most recent object to dispatch an event and target is the object that originally dispatched it
It's not. AS3 doc says :
currentTarget :
The object that is actively processing the Event object with an event listener. For example, if a user clicks an OK button, the current target could be the node containing that button or one of its ancestors that has registered an event listener for that event.
target : The event target. This property contains the target node. For example, if a user clicks an OK button, the target node is the display list node containing that button.

TabbedViewNavigator from Actionscript

How can I instantiate a TabViewNavigator from actionscript for the playbook? Currently, I add the necessary spark frameworks and have this piece of code in the Main of my actionscript project:
[SWF(width="1024", height="600", backgroundColor="#ffffff", frameRate="30")]
public class Main extends Sprite
{
private var waitDialog:BaseDialog = new BaseDialog ();
public function Main()
{
super ();
var next:LabelButton = new LabelButton ();
next.label = "Next";
next.addEventListener(MouseEvent.CLICK,showTabs);
this.addChild(next);
}
private function showTabs (event:MouseEvent):void{
var temp:Stage = this.stage;
temp.removeChild(this);
var bar : TabbedViewNavigator = new TabbedViewNavigator();
var tab1:ViewNavigator = new ViewNavigator();
tab1.label = "Test";
bar.addItem(tab1);
temp.addChild(bar);
}
}
When the button is clicked, the button disappears as you would expect but the tab navigator is not added/does not appear. I tried without removing the Main class but that does not work either. What do I need to do to set up a tab interface. I can get similar code working through Flex and MXML but not in actionscript.
temp.removeChild(this); - this is the problem you just remove the movie clip form the stage. There is no sense in this row.

how do I access the main class's stage? + Can I pass functions as arguments like this?

There are two files in my actionscript project named "TestAPP", TestAPP.as and Draggable.as
TestAPP.as:
package {
import flash.display.Sprite;
import flash.display.Stage;
public class TestAPP extends Sprite
{
var _mainStage:Stage;
public function TestAPP()//This is where we test the UI components.
{
var sp:Sprite = new Sprite();
_mainStage = stage;
_mainStage.addChild(sp);
sp.graphics.beginFill(0x00FF00);
sp.graphics.drawCircle(0,0,10);
sp.graphics.endFill();
sp.x = 50;
sp.y = 50;
var draggable1:Draggable = new draggable(sp,_mainStage,limitingfunc);
}
public function limitingfunc(x:Number,y:Number):int{
return 0;
}
}
}
And for the draggable.as:
package
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
public class Draggable
{
private var _limitingFunc:Function;
private var _which:Sprite;
private var _MouseSavedX:Number;
private var _MouseSavedY:Number;
private var _stage:Stage;
public function Draggable(which:Sprite,stage:Stage,limitingfunc:Function)
{
_limitingFunc = limitingfunc;
_which = which;
_stage = stage;
_which.addEventListener(MouseEvent.MOUSE_DOWN,begin_drag);
}
//limiting func: returns 0 when the object is free to move that place.
//returns -1 when the user wants to block X coordinate changes (but maintain Y free)
//returns -2 when the user wants to block Y ...
//returns -3 or less when the user wants to block both X and Y from changing.
//returns
private function Return_0(x:Number = 0,y:Number = 0):int{
return 0;
}
private function begin_drag(ev:MouseEvent):void{
var xTo:Number = _stage.mouseX - _MouseSavedX + _which.x;
var yTo:Number = _stage.mouseY - _MouseSavedY + _which.y;
var limitingFuncReturnValue:int = _limitingFunc(xTo,yTo);
if(limitingFuncReturnValue == 0){//free to move.
_which.x = xTo;
_which.y = yTo;
}
else if(limitingFuncReturnValue == -1){//free to move Y
_which.y = yTo;
}
else if(limitingFuncReturnValue == -2){
_which.y = yTo;
}
//else:do nothing.
}
}
}
In "my actionscript theory", I'm supposed to see a circle that follows the mouse when I click it. (The draggable is not fully implemented) But the circle doesn't even budge :(
...I've been trying to figure out how to access the main class's stage property. I've googled for it, but still no progress.
Please help this helpless newb!!! I'll really appreciate your help:)
Thank you!
You're implementing your 2nd class as "draggable", when you named it (and it has to be named) "Draggable" with an upper case. Change it and see if that works. You seem to be passing in the parent classes stage correctly though.
If TestAPP is your document class. You can access to the stage thru the stage property (like your are doing in your example).
If TestAPP is not the document class, you should listen first to the ADDED_TO_STAGE event and then access to the stage property.
There is no need to add _mainStage property because you already have the stage property.
In order to move objects around, you need to use the ENTER_FRAME event.
You can access the main class' stage property the same way you do it for any DisplayObject on the stage: Use this.stage.
So just this should be enough:
var sp:Sprite = new Sprite();
stage.addChild(sp);
You could then pass the sprite and the main class' stage as a parameter, the way you did - but I would recommend creating a subclass Draggable extends Sprite and instantiate the whole thing using new Draggable() instead.
The new object will automatically have its own reference to stage as soon as it is added to the display list, and limitingFunc could be a member of Draggable, as well.
Also, you can use the startDrag() and stopDrag() methods, no need to implement your own: You can specify a Rectangle as a parameter to startDrag() to limit the permitted movement.
if you need it so much you may:
private static var _instance: TestAPP;
//...
public function TestAPP(){
_instance = this;
//...
}
public static function get instance():TestAPP{
return _instance;
}
public static function set instance(newVal: TestAPP):void{
_instance = newVal;
}
and you'll be able to reference its stage from any class where your TestAPP will be imported just with TestAPP.instance.stage.
but _instance is a property of the class TestAPP itself, not its instances