actionscript-3: check if movieClip exists - actionscript-3

I have a movieclip created with the following code:
var thumbContainer:MovieClip = new MovieClip();
thumbContainer.name = "thumbContainer";
stage.addChild (thumbContainer);
If the window gets larger/smaller I want everything back in place. So I have an stage Event Listener. Now I want to see if this mc exists to put back in place. I've tried different ways but keep getting an error that does not exist.
1120: Access of undefined property thumbContainer.
if (this.getChildByName("thumbContainer") != null) {
trace("exists")
}
and
if ("thumbContainer" in this) {
trace("exists")
}
or
function hasClipInIt (mc: MovieClip):Boolean {
return mc != null && contains(mc);
}

stage.addChild (thumbContainer);
//...
if (this.getChildByName("thumbContainer") != null)
You are adding the thumbContainer to stage and checking for its existence with this. Change stage to this or this to stage.
That said, an even more appropriate way is to keep a reference to the added movie clip and check for existence with the contains method. It determines whether the specified display object is a child of the DisplayObjectContainer instance or the instance itself. The search includes the entire display list including this DisplayObjectContainer instance, grandchildren, great-grandchildren, and so on.
Hence you can easily check using stage.contains(thumbContainer);

if you are having trouble firing errors, you can always resort to a try catch
try{
/// do something that will blow up...
}catch( e:Error ){
trace( "we had an error but its not fatal now..." );
}

the problem was that 'stage' and 'this' are not the same...that's why I couldn't talk to the mc.
this works:
var thumbContainer:MovieClip = new MovieClip();
thumbContainer.name = "thumbContainer";
addChild (thumbContainer);
if (getChildByName("thumbContainer") != null) {
trace("exists")
}

Related

var mC:mc = new mc is adding the mc immediately?

I am a baffled noob here. I have the following code:
var mC:mc = new mc();
I do NOT instantiate mC at all with an addChild(mC);
But, later in the code, I have a loop using onEnterFrame and in this loop I have the following trace function:
if(mC){
trace("mC is here");
}
This returns "mC is here" in the output window. HUH???
The problem is that I want to use this 'if' statement to removeChild(mC); [I will be adding it in the code later with an addChild(mC); based on certain stuff that happens] but it keeps throwing dang "ERROR child of the caller" messages even with the 'if' condition...
WHAT am I doing wrong? I did not know declaring variables would add them to the stage/display list, I thought you needed an addChild(); statement. Am I smoking something I shouldn't be?
Thanks in advance, ~Frustrated Inc.
When you new up an object it exists in memory, even if you have not added it to the stage. That is why when you check if mC exists, it returns true. You want to check if it exists on the stage. Something like:
var mc:MovieClip = new MovieClip();
mc.name = "test";
if (this.getChildByName("test") != null) {
trace("mc is on stage");
}
I have not used Flash for a long time, so I did not test this code. Hopefully it works.
Complex objects in AS3 (that means anything that is not a string or a number) have a default value of null. WHen evaluated that default value of null equals false:
var mymc:MovieClip;//that MC is NOT instantiated yet so it has a default value of null
if(mymc)
{
//mymc is null so this evaluates to false
//and this statement DOES NOT execute
Now when a complex object is instantiated and exist its value would now evaluates to true
var mymc:MovieClip = new MovieClip();//that MC IS instantiated
if(mymc)
{
//mymc exits so this evaluates to true and this statement EXECUTE
//notice that "!= null" is not necessary
Now your problem has to do with display list. A DisplayObject has a parent property that is null when that object is not added to a display list, and that property point to the parent when that object is added to a display list:
var mc:MovieClip = new MovieClip()
trace(mc.parent);//this is null
addChild(mc);
trace(mc.parent);//this is not null anymore and points to the parent
SO what you mean to do is:
if(mC.parent){//this means mC has a parent and can be removed from it
trace("mC is here");
}
In your code, you just control whether your variable is null or not.
You can use contains method on the display object you are trying to add to.
If you are adding mC to some sprite named container, you can simply check whether it exists in that container with:
if (!container.contains(mC))
container.addChild(mC);
Edit: The safer method to control whether a movieclip is on the stage is to control its stage value.
if (mC.stage) {
mC.parent.removeChild(mC); // this is how you remove, if you simply want to check existence, don't remove it
}
It has to have a stage value if you added the movieclip to the stage or a container that is added to stage.
Hope it is clearer this way.

as3 - addchild with drag and drop

I am trying to add a child instance of an object to the stage, then allow the user to drag and drop this object (in this case, a movie clip) on the stage. However, I am getting the following error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at working_copy_fla::MainTimeline/dragObject()
So, that is my first problem. Then second problem, is I have not found an answer as to how to make a child object (specifically, a movie clip) able to properly be dragged and dropped on the stage.
Here is my code:
// Allow buttons to bring objects to the stage
myButton.addEventListener(MouseEvent.CLICK, addImage);
function addImage(event:MouseEvent):void
{
var myImage:Image_mc = new Image_mc();
stage.addChild(myImage);
// Center the object
myImage.x = 300;
myImage.y = 300;
// Allow the object to be drag and dropped
myImage.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
myImage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
function startDragging(event:MouseEvent):void
{
event.target.x = event.target.parent.mouseX - event.target.mouseX
event.target.y = event.target.parent.mouseY - event.target.mouseY
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject);
}
function dragObject(event:MouseEvent):void
{
event.target.x = event.target.parent.mouseX - event.target.mouseX
event.target.y = event.target.parent.mouseY - event.target.mouseY
}
function stopDragging(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject);
}
EDIT
I figured it out, and the solution was as simple as looking to the sample code in Adobe Flash (using CS6). Here is my code now:
// Allow buttons to bring objects to the stage
myButton.addEventListener(MouseEvent.CLICK, addImage);
function addImage(event:MouseEvent):void
{
var myImage:Image_mc = new Image_mc();
stage.addChild(myImage);
// Center the object
myImage.x = 300;
myImage.y = 300;
// Allow the object to be dragged
myImage.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
}
function clickToDrag(event:MouseEvent):void
{
event.target.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, releaseToDrop);
function releaseToDrop(event:MouseEvent):void
{
event.target.stopDrag();
}
The key here was that I have created universal functions (clickToDrag and releaseToDrop) that will accept input from any object (so I can re-use these functions with other images that I add to the stage). This code works with multiple children on the stage (all can be drag and dropped at any time).
The only problem I am having with it now is that I am getting this error whenever I spawn a child element (by clicking on the myButton button instance):
ReferenceError: Error #1069: Property stopDrag not found on flash.display.SimpleButton and there is no default value.
at working_copy_fla::MainTimeline/releaseToDrop()
This error is not stopping the application from working; everything still runs fine. But I would still like to figure out why this error is occuring. My guess is that whatever is using "stopDrag" (should just be a movie clip) is not capable of that method.
event.target.x = event.target.parent.mouseX - event.target.mouseX
The above code assumes that 'event.target' is the stage, right (because you added the listener to the stage)? So you're trying to change the x/y of the stage? No. The start/stopDragging should make a reference to the object being dragged, available as a private class variable, which is visible to the dragObject method. Also, what is the stage's parent ('event.target.parent.mouseX')? There is no parent to the stage. This is probably what the "null object reference" is refering to.
EDIT
I'm used to Object-Oriented AS3 (highly recommended), but I'm guessing that programming on the 'timeline' the following should work. Declare a variable outside of your functions, something like:
var objectCurrentDragging:DisplayObjectContainer;
Then in your 'addImage' function, use the following code to make objectCurrentDragging reference the object which you want to drag:
objectCurrentDragging = myImage;
Then in the dragObject function, simply reference objectCurrentDragging:
objectCurrentDragging.x = ...
Hope that works out for you.
So I have finally figured it out. The key was not to add an event to the stage, but rather, to add the "releaseToDrop" function to the *MouseEvent.MOUSE_UP* event on the child element in the same function that adds it to the stage. Now I get no more errors, and it works with multiple instances of the child objects (movie clips) on the stage.
Here is the code that works:
// Allow buttons to bring objects to the stage
myButton.addEventListener(MouseEvent.CLICK, addImage);
function addImage(event:MouseEvent):void
{
var myImage:Image_mc = new Image_mc();
stage.addChild(myImage);
// Center the object
myImage.x = 300;
myImage.y = 300;
// Allow the object to be dragged
myImage.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
myImage.addEventListener(MouseEvent.MOUSE_UP, releaseToDrop);
}
function clickToDrag(event:MouseEvent):void
{
event.target.startDrag();
}
function releaseToDrop(event:MouseEvent):void
{
event.target.stopDrag();
}

Can't remove child from the stage - if(stage.contains(child1)){removeChild(child1);} doesn't work

It may sound stupid, but how can I remove a definite child from the stage?
e.g.
function giveMeResult(e:MouseEvent):void
{
if(stage.contains(result))
{removeChild(result);}
addChild(result); // this part works fine, but it adds one over another
}
it adds one result on the top of the previous one.
I want the function "giveMeResult: to remove "result" if is on the stage and add a new one.
UPDATE:*
result is a TextField, and result.txt ="" changes from time to time ...
trace (result.parent); /// gives [object Stage]
trace (result.stage); /// gives[object Stage]
trace (result.parent != null && result.parent == result.stage); // gives true
when
result.parent.removeChild(result);
is written without if statement - gives error TypeError: Error #1009: Cannot access a property or method of a null object reference.
when written inside:
if (result.parent !=null && result.parent == result.stage)
{
result.parent.removeChild(result);
}
nothing happens and new child is added on the top of the previous one.
Thanks to all!!!
The result is simple :)
All I had to do is just change result.txt without even removing it from the stage :)
You need to type stage.removeChild(result); and subsequently stage.addChild(result);
Edit:
Looking at a function similar to yours:
private function func(e:Event) : void {
if(stage.contains(result)) {
stage.removeChild(result);
}
stage.addChild(result);
}
The only way this would add a new instance of the TextField result to the stage, without removing the old one, would be if result has changed. See this flow of execution:
var result : TextField = new TextField();
// An event occurs and func get's called.
// now result will be added to stage.
result = new TextField();
// An event occurs and func get's called again
// This time the stage.contains(..) will return false, since the current result
// is not actually on stage. This will add a second TextField to the stage.
If I am clearly understood what you want, then this code can help you:
if (result.parent != null && result.parent == result.stage)
{
// stage itself contains result
result.parent.removeChild(result);
}
From the docs for DisplayObjectContainer.contains(): "Grandchildren, great-grandchildren, and so on each return true."
So contains means anywhere on the display list, not just direct children. What you want is the parent check Manque pointed out, or simply to remove result from anywhere it might be:
if (result.parent) {result.parent.removeChild(result); }
Though oddly, addChild(result) will automatically remove it from its previous parent - a DisplayObject can only be at one place in the DisplayList at a time, so I'm not sure why you're seeing multiple results...
Is it possible that the "result" you've passed in isn't the result that's already on the stage?
Have you tried?
MovieClip(root).removeChild(result)
[EDIT]
function giveMeResult(e:MouseEvent):void{
if(result.parent != null && result.parent == result.stage){
stage.removeChild(result);
}
stage.addChild(result);
}
All I had to do is just change result.txt without even removing it from the stage

Removing an event listener as well as a sprite at the same time AS3

I’m having trouble removing the an event listener as well as the sprite at the same time. I currently get an error:
TypeError: Error #1009: Cannot access
a property or method of a null object
reference.
And if I comment out removeChild, I have no error but, obviously, the sprite remains on the screen. Any ideas how I can rid myself of that error?
//Bullet extends Sprite Class
bullet:Bullet = new Bullet();
mc.addChild(bullet);
bullet.addEventListener(Event.ENTER_FRAME, shoot);
function shoot(e:Event):void {
var shot:Bullet = e.currentTarget as Bullet;
//check shot is outside the frame
if (shot.x < 0 - shot.width || shot.x > stage.stageWidth || shot.y > 525)
{
//trying to remove the thing and it's listener
e.currentTarget.removeEventListener(e.type,arguments.callee);
e.currentTarget.parent.removeChild(shot);
}
else
{
shot.setInMotion();
}
}
Apart from a missing var before bullet:Bullet, I don't see anything wrong in the example code. You should set a breakpoint right after:
var shot:Bullet = e.currentTarget as Bullet;
And figure out why shot is null. I suspect there is something amiss in a piece of code outside of the little bit you're providing as the example. If the code is working with only the removeChild line commented out, it tells me that e.currentTarget is not null, but that it's also not a reference to an instance of type Bullet (i.e. the "as" cast is returning null).
Try reversing these lines
Maybe the reference to e.currentTarget is getting lost through the object references
e.currentTarget.removeEventListener(e.type,arguments.callee);
e.currentTarget.parent.removeChild(shot);
to
e.currentTarget.parent.removeChild(shot);
e.currentTarget.removeEventListener(e.type,arguments.callee);

AS3 Display Object Trouble

I'm making a game in AS3. When I add an enemy to the game screen, later on I have to remove it when it dies. But I keep getting this:
[Fault] exception, information=ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
But I clearly add the enemy to the gamescreen. Could this be from passing the enemy through a bunch of functions or something?
This means that you try to remove the MovieClip (or Sprite or so) from a DisplayObjectContainer that is not its parent.
You have to be sure to call the removeChild() Method on the right DisplayObjectContainer.
For instance:
var myChild:MovieClip = new MovieClip();
var holder:MovieClip = new MovieClip();
holder.addChild(myChild);
so when you want to remove the child you have to call the removeChild Method on the holder.
holder.removeChild(myChild);
If you call removeChild() on for instance the stage you will get an error because the stage does not hold myChild as a child of itself.
So double check if you call removeChild on the right container.
PS: Sample code is always easier to debug
When dealing with the timeline, it's difficult sometimes to keep track of an object's scope , in which case you can always call the method from the object's parent property.
child.parent.removeChild( child );
if you're coding in FlashDevelop & for some reason , don't wish to or can't keep track of the parent , you could implement a couple of methods to add and remove your object from the display list, practically delegating adding & removing to the object...
in your object class , you could do the following...
private var container:DisplayObjectContainer;
public function addToDisplayList( container:DisplayObjectContainer ):void
{
this.container = container;
container.addChild( this );
}
public function remove():void
{
if( container != null )
container.removeChild( this );
}
Then you can simply do this:
var child:MovieClip = new MyObject();
child.addToDisplayList( whatever );
//later...
child.remove();