0
votes

I am trying to create a drag and drop game.

I used an array and it works with drag and drop, but doesn't work with the IF function.

Instead, it shows me this error:

"TypeError: Error #1010: A term is undefined and has no properties. at Test_game_fla::MainTimeline/drop()[Test_game_fla.MainTimeline::frame1:38]"

Here is my code:

var s = 0;          
score.text = s;

var mixed:Array = new Array;

mixed.push(orange);
mixed.push(cheese);
mixed.push(lobbio);
mixed.push(meat);
mixed.push(fish);

for (var i:uint = 0; i < mixed.length; i++) {

mixed[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
mixed[i].addEventListener(MouseEvent.MOUSE_UP, drop);


function drag(e)
{
e.target.startDrag();
}

function drop(e)
{
e.target.stopDrag();

if( (cheese.y > 50 && cheese.y < 150) && (cheese.x > 480 && cheese.x < 570) )
{
    cheese.x = -50;
    cheese.y = -50;
    s = s + 10;
    score.text = s;
}

if( (mixed[i].y > 50 && mixed[i].y < 150) && (mixed[i].x > 480 && mixed[i].x 
< 570) )
{
    mixed[i].y = -50;
    mixed[i].x = -50;
    s = s + 10;
    score.text = s;
}


}

}
3
Just curious, why do you have two if statements, you added cheese to mixed array? - User 987

3 Answers

1
votes

To explain what your actual problem is, it's the use of inline functions.

Inside your for loop, you define some functions (those are referred to as inline functions, and as mentioned in VC.One's answer, this is not a good practice - please follow their other advice as well).

Since those functions are defined inside the for loop block, every iteration you are actually creating a whole new function/object. When you create those functions, the ones called drop are referencing your iterator (i). BUT, those functions are not actually called until you MOUSE_UP. This mouse up trigger will happen long after the for loop has finished. At which point i will have a value of 5. Why 5? (as it only iterates from 0 - 4), because after every iteration i is incremented, so it will end up 1 higher than the last iteration.

Since there is no element at position 5 in your mixed array, you get the error.

To rectify the situation, follow the code example from the other answers (which break those functions out of the for loop)

Instead of referencing i, use the event's currentTarget property (which is a reference to the object that you attached the listener to).

Sprite(e.currentTarget).y
1
votes

U can fix it like this.

var s = 0;          
score.text = s;

var mixed:Array = new Array;

mixed.push(orange);
mixed.push(cheese);
mixed.push(lobbio);
mixed.push(meat);
mixed.push(fish);

for (var i:uint = 0; i < mixed.length; i++) {
    mixed[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
    mixed[i].addEventListener(MouseEvent.MOUSE_UP, drop);
}


function drag(e)
{
    e.currentTarget.startDrag();
}

function drop(e)
{
    var mix:Sprite = Sprite(e.currentTarget);
    mix.stopDrag();


    if( (cheese.y > 50 && cheese.y < 150) && (cheese.x > 480 && cheese.x < 570) )
    {
        cheese.x = -50;
        cheese.y = -50;
        s = s + 10;
        score.text = s;
    }
    //Error in mixed[i] ; at last i = mixed.length mixed[i] is null. 
    //Event has a property "currentTarget" this can get u select target
    if( (mix.y > 50 && mix.y < 150) && mix.x > 480 && mix.x < 570) )
    {
        mix.y = -50;
        mix.x = -50;
        s = s + 10;
        score.text = s;
    }

}
1
votes

Some things to fix :

(1) Give your variables a data type. Saying var s = 0; suggests that s is a numerical variable, right? Well score.text expects a String not Number so you must use casting to convert. Try :

var s : int  = 0; //define a numerical variable
score.text = String(s); //cast number into String type (for usage as text)

(2) Don't put your functions inside a For-loop!!! Don't even put functions inside other functions (unless you know what an Anonymous Function is, and you can justify needing it).

(3) You can shorten some code typing by :

  • Incrementing? Use s += 10 to avoid longer s = s + 10;. Can also be -=, /= etc.
  • If setting same value to multiple variables just chain like so: cheese.x = cheese.y = -50;

(4) Don't try to access mixed[i] by mixed.length. Since length is 5 at some point the compiler sees an instruction like : mixed[5].addEventListener...

However an array starts at zero for first item so you should understand the fifth item is really at mixed[4].addEventListener....

That other mixed[5].something (same as : mixed[mixed.length].something) does not exist.

PS : I would have thought that setting i < mixed.length would have protected against going over the array size, since if i must be smaller than .length then i == 5 could never happen.


Anyways... This code below is untested (no AS3 compiler here) but try the following :

var s : int = 0;          
score.text = String(s);

var mixed:Array = new Array;

mixed.push(orange); mixed.push(cheese);
mixed.push(lobbio); mixed.push(meat); mixed.push(fish);

for (var i:uint = 0; i <= (mixed.length-1); i++) 
{
    mixed[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
    mixed[i].addEventListener(MouseEvent.MOUSE_UP, drop);

} //end "For" loop

function drag(e) : void { e.target.startDrag(); }

function drop(e) : void
{
    e.target.stopDrag();

    if( (cheese.y > 50 && cheese.y < 150) && (cheese.x > 480 && cheese.x < 570) )
    {
        cheese.x = cheese.y = -50;
        s += 10; //# achieves same thing as... s = s + 10;
        score.text = String(s);
    }

    if( (Sprite(e.currentTarget).y > 50 && Sprite(e.currentTarget).y < 150) && (Sprite(e.currentTarget).x > 480 && Sprite(e.currentTarget).x < 570) )
    {
        Sprite(e.currentTarget).x = Sprite(e.currentTarget).y = -50;
        s += 10;
        score.text = String(s);
    }
} //end Function "drop"