Startdrag is not a function - actionscript-3

this.addEventListener(MouseEvent.MOUSE_DOWN,function(e:MouseEvent){this.startDrag(false,null);});
Hi I was wondering why the above doesnt work? Im trying to drag a sprite around screen.

create a sprite on stage, add instance name box, add code to frame one:
box.addEventListener(MouseEvent.MOUSE_DOWN, startMove);
function startMove(evt:MouseEvent):void {
box.startDrag();
}
box.addEventListener(MouseEvent.MOUSE_UP, stopMove);
function stopMove(e:MouseEvent):void {
box.stopDrag();
}
I think your example doesn't work because of the scope of "this" in the event listener handler.

If you remove this.; it will work. It's a scope issue since you use an anonymous function.
You could use the currentTarget of the event, this allows you to make other boxes draggable too, if you add the same listeners.
Note: It is hard to remove an anonymous function as event listener and could cause memory leaks, so the best way is to use a reference to a named function:
box.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseEvent);
box.addEventListener(MouseEvent.MOUSE_UP, handleMouseEvent);
function handleMouseEvent(event:MouseEvent):void
{
switch(event.type)
{
case MouseEvent.MOUSE_DOWN:
{
DisplayObject(event.currentTarget).startDrag();
break;
}
case MouseEvent.MOUSE_UP:
{
DisplayObject(event.currentTarget).stopDrag();
break;
}
}
}

Related

Can I pass a button into its own MouseEvent function?

I have multiple MovieClip Symbols published with Flash into FlashDevelop (I'll only use 2 in my example). Each have 3 frames for default, hover and click that I'm using as buttons.
private var btnPlay:PlayButton, btnQuit:QuitButton;
btnPlay = new PlayButton();
btnQuit = new QuitButton();
btnPlay.addEventListener(MouseEvent.ROLL_OVER, onRollOverHandler);
btnPlay.addEventListener(MouseEvent.ROLL_OUT, onRollOutHandler);
btnPlay.addEventListener(MouseEvent.MOUSE_DOWN, onPressHandler);
btnPlay.addEventListener(MouseEvent.MOUSE_UP, onReleaseHandler);
btnPlay.buttonMode = true;
btnPlay.useHandCursor = true;
function onRollOverHandler(myEvent:MouseEvent):void {
btnPlay.gotoAndStop(2);
}
function onRollOutHandler(myEvent:MouseEvent):void {
btnPlay.gotoAndStop(1);
}
function onPressHandler(myEvent:MouseEvent):void {
btnPlay.gotoAndStop(3);
}
function onReleaseHandler(myEvent:MouseEvent):void {
btnPlay.gotoAndStop(2);
}
// Same code for btnQuit here, but replace btnPlay with btnQuit
Instead of adding new EventListeners to every button that do practically the same thing like what I'm doing above, is there a way I could just pass in the button itself to the MouseEvent functions something like this? (I realize this might be difficult since all buttons are their own class)
btnPlay.addEventListener(MouseEvent.ROLL_OVER, onRollOverHandler(btnPlay));
btnPlay.addEventListener(MouseEvent.ROLL_OUT, onRollOutHandler(btnPlay));
btnPlay.addEventListener(MouseEvent.MOUSE_DOWN, onPressHandler(btnPlay));
btnPlay.addEventListener(MouseEvent.MOUSE_UP, onReleaseHandler(btnPlay));
function onRollOverHandler(myEvent:MouseEvent, inButton:MovieClip):void {
inButton.gotoAndStop(2);
}
function onRollOutHandler(myEvent:MouseEvent, inButton:MovieClip):void {
inButton.gotoAndStop(1);
}
function onPressHandler(myEvent:MouseEvent, inButton:MovieClip):void {
inButton.gotoAndStop(3);
}
function onReleaseHandler(myEvent:MouseEvent, inButton:MovieClip):void {
inButton.gotoAndStop(2);
}
Maybe I am misunderstanding, but "event.target" provides you a reference to the button that has been clicked. So if you want to do something to the clicked button, you would write:
myEvent.target.gotoAndStop(1);
Or sometimes you might need to use "currentTarget". You'd still need to create listeners for each function but could use one set of handlers.
Simple answer: No. You could go to some trouble to override the MouseEvent class and allow it to send additional parameters, but why bother in this case? You don't seem to be saving any code.
SLIGHT UPDATE:
Here's a possibly-useful simplification of your original code. It saves a few lines-of-code and uses just a single handler function. Obviously, the 'trace' statements could be replaced by various 'gotoAndStop()' statements:
btnPlay.addEventListener(MouseEvent.ROLL_OVER, HandleAll);
btnPlay.addEventListener(MouseEvent.ROLL_OUT, HandleAll);
btnPlay.addEventListener(MouseEvent.MOUSE_DOWN, HandleAll);
btnPlay.addEventListener(MouseEvent.MOUSE_UP, HandleAll);
function HandleAll(e)
{
if (e.type == "rollOver") trace("rollover");
if (e.type == "rollOut") trace("rollout");
if (e.type == "mouseDown") trace("mousedown");
if (e.type == "mouseUp") trace("mouseup");
}

How best to trigger function that is inside a movie clip

I am tying to trigger a function that is inside a Movie Clip
my_mc.addEventListener(MouseEvent.CLICK,myfuntion);
function myfuntion(myEvent:MouseEvent):void
{
MovieClip(this.root).gotoAndStop(44);
tvscreen_mc.function("byby");
}
the byby function is inside tvscreen_mc
function byby(myEvent:MouseEvent):void {
my_player.destroy();
}
Replace
my_mc.addEventListener(MouseEvent.CLICK,myfuntion);
function myfuntion(myEvent:MouseEvent):void
{
MovieClip(this.root).gotoAndStop(44);
tvscreen_mc.function("byby");
}
with
MovieClip(root).my_mc.addEventListener(MouseEvent.CLICK, MovieClip(root).tvscreen_mc.byby);
this will also work, if you're at the root level (which I assume you are, but incase you put it somewhere else):
my_mc.addEventListener(MouseEvent.CLICK, tvscreen_mc.byby);

Removing Event Listener in Deactivate/Activate Event - AS3

I am using the code snippet from Flash Cs6 for my mobile Air app. How do I properly remove the listener? ( I get error 1120: Access of undefined property ocean_slider. ) with the following code. Thanks for your help.
/* Deactivate/Activate Event
Conserve CPU and battery life by suspending expensive processes, such as ENTER_FRAME and TIMER events, when the application is not in focus.
Instructions:
1. Start timers and add event listeners in "fl_Activate".
2. Stop timers and remove event listeners in "fl_Deactivate".
*/
stage.addEventListener(Event.ACTIVATE, fl_Activate);
stage.addEventListener(Event.DEACTIVATE, fl_Deactivate);
function fl_Activate(event:Event):void
{
// Start timers and add event listeners here.
naturepage.sliders.ocean_slider.addEventListener(Event.ENTER_FRAME, ocean_slider);
function ocean_slider(e:Event):void
{
ocean_transform.volume = (naturepage.sliders.ocean_slider.value/100);
ocean_channel.soundTransform = ocean_transform;
}
}
function fl_Deactivate(event:Event):void
{
// Stop timers and remove event listeners here.
naturepage.sliders.ocean_slider.removeEventListener(Event.ENTER_FRAME, ocean_slider);
}
OK. I just changed the code to the following but still have the problem. The listener is definitely getting added because the functions work in my app after publishing without the removeEventListener. But once I add the code to remove the listener, I get the error 1120 when I try to publish.
stage.addEventListener(Event.ACTIVATE, fl_Activate);
stage.addEventListener(Event.DEACTIVATE, fl_Deactivate);
function fl_Activate(event:Event):void
{
addEventListener(Event.ENTER_FRAME,myFunction);
function myFunction(event:Event):void
{
ocean_transform.volume = (naturepage.sliders.ocean_slider.value/100);
ocean_channel.soundTransform = ocean_transform;
}
}
function fl_Deactivate(event:Event):void
{
removeEventListener(Event.ENTER_FRAME,myFunction);
}
It looks like your brackets are off - is that the code you copied and pasted or what you're trying to run. I'll edit the code after you confirm why the brackets are the way they are - specifically the 2 '}' in the ocean_slider function
Regardless, it means that ocean_slider isn't available and hasn't been added to the stage. So if it has, you need to check to make sure you're not calling fl_Deactivate before things are ready. And you also have a function call and stage item with the same name - ocean_slider - I'd change that and see if it works.
ok. I think it's working now. I put the function all the way outside. Thanks for your help and responses.
function myFunction(event:Event):void
{
ocean_transform.volume = (naturepage.sliders.ocean_slider.value/100);
ocean_channel.soundTransform = ocean_transform;
}
stage.addEventListener(Event.ACTIVATE, fl_Activate);
stage.addEventListener(Event.DEACTIVATE, fl_Deactivate);
function fl_Activate(event:Event):void
{
addEventListener(Event.ENTER_FRAME,myFunction);
}
function fl_Deactivate(event:Event):void
{
removeEventListener(Event.ENTER_FRAME,myFunction);
}

Is this the correct way to remove a timer?

I'm not sure if the way I did makes the garbage collector remove the timer. Here are my two functions:
public function newWave() {
var callTimer:Timer = new Timer(800);
callTimer.start();
leftToSpawn = 4;
callTimer.addEventListener(TimerEvent.TIMER,waveCall);
}
public function waveCall(e:TimerEvent) {
leftToSpawn--;
if(leftToSpawn <= 0){
e.target.stop();
e.target.removeEventListener(TimerEvent.TIMER_COMPLETE,waveCall);
}
spawnEnemy();
}
Thanks
To remove an event listener you need to remove it with the exact same signature.
If you do:
.addEventListener(TimerEvent.TIMER,waveCall);
Then you need to use the same event type and function to remove it:
.removeEventListener(TimerEvent.TIMER,waveCall);
Using TimerEvent.TIMER_COMPLETE here will try to remove a listener that doesn't exist, which is silently ignored.
Using target here is ok, for other listener types you may need to use currentTarget, which is always the object the listener got added to. For example in a mouse click event, target could be a child of a MovieClip and without any listeners.
Moreover, timer already has ability to repeat specified number of times and the correct code will be like this:
public function newWave() {
var callTimer:Timer = new Timer(800, 4); //repeat 4 times
callTimer.start();
callTimer.addEventListener(TimerEvent.TIMER,waveCall);
}
public function waveCall(e:TimerEvent) {
spawnEnemy();
}
just change:
e.target.removeEventListener(TimerEvent.TIMER_COMPLETE,waveCall);
to
e.target.removeEventListener(TimerEvent.TIMER,waveCall);

Is there a way for listening for changes in flash.display.DisplayObjectContainer numChildren property?

I want to run some code whenever a DisplayObject is added as a child to a DisplayObjectContainer.
Or to put in other words, to catch the addedToStage event of all DisplayObjects, even ones I don't know about.
Is it possible? and if not, any ideas on how to do something similar?
An 'added' event is dispatched whenever a child display object is added to the display list via addChild() or addChildAt(). In the DisplayObjectContainer class add the listener:
addEventListener(Event.ADDED, onAdded);
and the handler:
private function onAdded(e:Event):void
{
trace('number of children is now ' + numChildren);
}
Using Event.ADDED_TO_STAGE on stage Object and setting useCapture to true.
More info on event here
Example:
function onAdded(e:Event):void{
trace(e.target.toString()); //use target to get the Object added
}
stage.addEventListener(Event.ADDED_TO_STAGE, onAdded, true); // set capture to true
I don't know if there is a built in way to do this.
Alternatives include the obvious,
private var _num_children:Number = 0;
addEventListener(Event.ENTER_FRAME, _checkChildren, false, 0, true);
private function _checkChildren($evt:Event):void {
if (this.numChildren != _num_children) {
_num_children = this.numChildren;
// There was a child (or more) added in the last frame execution
}
}
However, this seems like a more elegant solution...
public function _addChild($do:DisplayObject) {
$do .addEventListener(Event.ADDED_TO_STAGE, _childAdded);
addChild($do );
}
private function _childAdded($evt:Event) {
// do whatever with $evt.target
}
The difference here, is the _childAdded will get fired for each and every child added via _addChild method. This means if you are doing some costly code execution you will be doing it once for each child instance.
If you use the first method, you are only calling the method once per frame, and if 10 images are added on a single frame, then it will only run once.