as3 cs5 Odd Error #1009 in drag and drop game - actionscript-3

I'm making a drag-and-drop game.
On the MouseEvent.MOUSE_UP I have an if-statement like so:
function fnUp(event:MouseEvent):void
{
clicked.stopDrag();
if (clicked.dropTarget.parent.parent.name == clicked.currentLabel)
{
var dropped:Card = clicked.dropTarget.parent.parent as Card;
dropped.gotoAndStop(dropped.name);
dropped.bg.gotoAndStop("done");
removeChild(clicked);
}
else
{
clicked.x = clicked.sx;
clicked.y = clicked.sy;
clicked.bg.gotoAndStop("off");
}
clicked = null;
}
"clicked" is an earlier declared var of type Card(); and it's set in the MouseEvent.MOUSE_DOWN like so:
function fnDown(event:MouseEvent):void
{
clicked = event.currentTarget as Card;
clicked.bg.gotoAndStop("on");
clicked.startDrag();
addChild(clicked);
}
I thought that if I build my if-statement like this there wouldn't be an error if the card was dropped anywhere but on one of the three possible target cards. But I still get:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
tldr; I get an error if I drop my card outside one of the 3 possible targets.

On which line you getting an error? You need to check if all of the following objects existing:
if (clicked.dropTarget &&
clicked.dropTarget.parent &&
clicked.dropTarget.parent.parent )
{
then do something...
}

Related

AS3 - Error #1009 and cannot find cause of issue

Using AS3 in Animate CC, I get this error:
Error #1009: Cannot access a property or method of a null object reference.
I have read through all the work-through for this error On Stack Overflow but I still can't figure this one out. Any help would be a blessing.
I have a navigation panel of 96 buttons I'm attempting that when user clicks a movie from the library appears. A couple problems, first the error 1009 and also secondly when a new MovieClip appears the current one needs to go away.
Label for one of the buttons
btn_SAFER_25_1Jan
Label for Movie clip Symbol property
mcSaf_Jan01_25
Label for Name of Movie Symbol Class
Saf_Jan01_25
Code below, each frame of timeline that suppose to load each movie has similar, this one is for Jan 1 25
stop();
var saf_Jan01_25:Saf_Jan01_25=new Saf_Jan01_25;
addChild(saf_Jan01_25);
addChildAt(saf_Jan01_25,0);
saf_Jan01_25.x=394;//sets the x position
saf_Jan01_25.x=344;//sets the y position
saf_Jan01_25.visible = true;
saf_Jan01_100.visible = false;
saf_Jan01_250.visible = false;
saf_Jan01_500.visible = false;
script below is on timeline of for each navigation button
btn_SAFER_25_1Jan.addEventListner(MouseEvent.CLICK, fl_MouseOverHandler2);
btn_SAFER_25_1Jan.enabled = true;
function fl_MouseOverHandler2(eventMouseEvent):void
{
{
gotoAndPlay(2);
}
trace("Click");
}
btn_SAFER_100_1Jan.addEventListner(MouseEvent.CLICK, fl_MouseOverHandler3);
btn_SAFER_100_1Jan.enabled = true;
function fl_MouseOverHandler3(eventMouseEvent):void
{
{
gotoAndPlay(3);
}
trace("Click");
}

typeError: Error #1006: setChildIndex is not a function

Do you know what causes this error?
TypeError: Error #1006: setChildIndex is not a function.
at Function/()[iVision_Game_fla.MainTimeline::frame83:151]
Here's where I think the error occurs...
function dragObject(indx1:int,indx2:int):Function {
return function(event:MouseEvent){
var item:MovieClip=MovieClip(event.currentTarget);
item.startDrag();
var topPos:uint=this.numChildren-1;
var itemSound:Sound = new Sound();
itemSound.load(new URLRequest("sounds/"+dirArray[indx1])+indx2+".mp3"));
if(!activeSound)
{
itemSound.play();
activeSound=true;
}
this.setChildIndex(item, topPos);
}
}
//calling it on another function
var functionOnDrag:Function = dragObject(indexc[count-1],index[count2]);
pb[i].addEventListener(MouseEvent.MOUSE_DOWN,functionOnDrag);
I think scope is the problem here. If the item's parent isn't changing, you can use item.parent.setChildIndex(item, topPos)
Also, before that, topPos:uint = item.parent.numChildren -1;
Update:
To debug further, put a breakpoint on the line of setChildIndex (151). (adding a breakpoint: click to the left of the line number. it will add a little red circle. When code hits this in debug mode it will stop.)
Then go to Debug -> Debug Movie -> Debug
When it stops, open the Debug Panels: Window->Debug Panels->Variables, Window->Debug Panels->Callstack
In the variable panel, you should see all the current variables in the scope. What you are looking for is an issue with the object that setChildIndex is being called on. In this case, the parent of item. You can drill down to see what that is. It should be a DisplayObjectContainer (MovieClip, Sprite, etc...). Item came from event, so i would check event.currentTarget as well. You are basically trying to confirm that at that breakpoint, item exists, it has a parent, and it's parent is a DisplayObjectController. If one of these isn't true, you can track backwards from here why this isn't the case.
TypeError: Error #1006: setChildIndex is not a function
You have created anonymous function, if you want capture this, you could do such construction:
var selfRef:MyClass = this;
Now your handler for the MouseEvent will look:
function dragObject(indx1:int, indx2:int):Function {
return function (event:MouseEvent) {
//Your code
selfRef.setChildIndex(item, topPos);
}
}

Using MovieClip(root) in ActionScript 3

im at frame 3.. i have text field on the stage name scoreTxt.. at frame 3 i added TryClass..
var Try:TryClass = new TryClass();
TryClass has function of updateScore.. this is working fine if im on frame 3. so my code is
public function updateScore(amount:int):void
{
score += amount;
if(score < 0) score = 0;
realNumber = score;
setInterval(updateDisplayedScore, 10);
}
public function updateDisplayedScore():void
{
displayedNumber += Math.round((realNumber-displayedNumber)/5);
if (realNumber - displayedNumber < 5 && realNumber - displayedNumber > -5)
{
displayedNumber = realNumber;
}
addZeros();
}
public function addZeros():void
{
var str:String = displayedNumber.toString();
MovieClip(root).scoreNa.text = str;
}
but then if for example .. the user died or he reaches the required score.. im suppose to go a certain frame using this code..
MovieClip(this.root).gotoAndStop("Main"); this code is on the class..
its reaching the frame "Main" but its pointing errors to this -->
MovieClip(root).scoreTxt.text
that "Main" frame is on frame 4.. which i did not yet added the TryClass.. should i add to all my frames the TryClass? and how is that?
Sorry for the question.. i dont know yet how to perfectly code in the class.. and accessing the timelines and other external class.. Please dont use deeper language of actionscript.. on a beginner way only..
here is the full error message when i go to the frame "Main"
TypeError: Error #1009: Cannot access a property or method of a null object reference.
atTumba/addZeros()[C:\Documents and Settings\Chrissan\Desktop\Game and Docs\Game\Tumba.as:686]
atTumba/updateDisplayedScore()[C:\Documents and Settings\Chrissan\Desktop\Game and Docs\Game\Tumba.as:680]
atFunction/http://adobe.com/AS3/2006/builtin::apply()
atSetIntervalTimer/onTimer()
atflash.utils::Timer/_timerDispatch()
atflash.utils::Timer/tick()
this is the line 686 of Tumba.as - MovieClip(root).scoreNa.text = str;
public function updateDisplayedScore():void
{
displayedNumber += Math.round((realNumber-displayedNumber)/5);
if (realNumber - displayedNumber < 5 && realNumber - displayedNumber > -5)
{
displayedNumber = realNumber;
}
addZeros(); -->> this is the line 680 of Tumba.as
}
about the setInterval sir.. its working fine cause i imported the flash.utils.* ..its working fine on frame 3 which i added the class.. but on "Main" fram. it isnt..
Try using (root as MovieClip) instead of MovieClip(root)
My guess would be that "root" is undefined, because I'm guessing TryClass is not inherited from a MovieClip or other DisplayObject that lives in the existing heirarchy.
To fix it, I'd add a parameter to the class's constructor. Then, I would send it a movieclip that you can access. For instance, if you are instantiating your class from within a movieclip, just send it the "this" for that movie.
public class TryClass {
...
static var myroot:MovieClip = null;
...
public function TryClass(someclip:MovieClip=null) {
...
if (this.myroot == null && someclip != null && someclip.root != undefined) {
this.myroot = someclip.root;
}
...
}
...
}
Then from within a movie clip:
var something = new TryClass(this);
Anyway, this is the technique I'm using for a class that I'm making. For mine, I have it adding an instance of an external movie clip if the class detects that the root does not already have it loaded. In my case, a universal loading-bar called from my loading wrapper class. If a particular movie I put it in already has a custom loading bar, then it won't do anything, but for any I don't have one in yet, it'll add it.

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();
}

actionscript-3: check if movieClip exists

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")
}