0 votes

Hi all. This HAS to be beginners mistake. :-(

I am calling a function like so:

slide_ice_shelf("up")

This is the function:

func slide_ice_shelf(placement):
    var speed       = 800  
    var start       = iceShelfSprite.get_pos()
    print (placement)
    if placement == "up":
        var end = Vector2(150,0)
    else:
        var end = Vector2(150,500)
    var distance    = start.distance_to(end)
    var time        = distance / speed

The line var distance = start.distance_to(end)
gives the error Parser Error: Identifier not found: end

I check the progress with the print statement just above the if and it prints as "up" if I replace var distance = start.distance_to(end) with a temp bit of data like var distance = start.distance_to(Vector2(100,100)

I'm a bit stumped. Is it me? It must be me. :-)

asked Dec 3, 2016 in Engine by Robster (808 points)

As eon says, your VAR is declared inside your IF statement. It's scope is local to the IF block, after the IF exits, the variable is cleaned up. So move the declaration of end outside of the IF block to change it's scope.

I'm obviously quite new to programming. It was a great lesson. Thank you for the advice.

I see. You're welcome. ^_^

If that's the case, I would offer that it's worth investigating how program stacks work.

It can be very clarifying to be familiar with the order of how instructions (functions) and memory (variables) are added, processed, and then removed. It reveals the effect of scoping.

1 Answer

+2 votes
Best answer

The scope of a variable is where you declared it.

speed, start, distance and time, are declared in slide_ice_shelf, and accesible in there.

end is declared inside the if (and another in else), when if ends, the variable is lost (same for else).

What you have to do is to declare the variable where you want to be accesible, the class, a function, or inside a while/if/for to use mostly as auxiliar variable inside them.

In your case, do a var end on the function scope (outside and before the if) and assign values inside it.

func slide_ice_shelf(placement):
    var speed       = 800  
    var start       = iceShelfSprite.get_pos()
    var end
    print (placement)
    if placement == "up":
        end = Vector2(150,0)
    else:
        end = Vector2(150,500)
    var distance    = start.distance_to(end)
    var time        = distance / speed

If your if has many conditions, you may need to set a initial value to the variable (not this case, else does that) or check if it is null later.

Is a common practice to set all the vars (even uninitialized) at the start of the function/method/block where they will be accesible too, but that depends on your coding style.

answered Dec 3, 2016 by eons (7,786 points)
selected Dec 5, 2016 by Robster

What a great answer, thank you. You know I was looking at it and thinking, surely that variable can't be local to an IF statement?! It seemed just too specific to me, but there it is. Thanks again so much. Always appreciate the help people offer here.

The indentation also tells you about the scope, everything on a level is accesible from there and up (to the right) and lost when closing the block (going left).

In other languages you will see the use of { } for the same purpose.

That's helpful thank you. I am quite a visual person so the indentation really helps me.

I am sorry but I finally got time to look into this today and it's still not working.

Here's my current code:

func slide_ice_shelf(placement):
    var speed       = 600
    var start       = get_node("iceShelfGoup").get_pos()
    var end         = Vector2(0,0)
    if placement == "up":
        var end = Vector2(150,0)
        print (str(end))
    elif placement == "down":
        var end = Vector2(150,500)
        print (str(end))
    print(str(end))
    var distance    = start.distance_to(end)
    var time        = distance / speed

So calling the function as so (from another instance scene) :

get_node("/root/gameLevel").slide_ice_shelf("down")

outputs the following print statements:

(150,500)
(0,0)

So the "down" if is working as you can see by the (150,500) print.
Then it reverts BACK to the initial end declaration's contents. From:

var end  = Vector2(0,0)

To back this up, if I change the initial declaration to say:

var end  = Vector2(1000,1000)

The print output shows as:

(150,500)
(1000,1000)

(and the ice shelf moves)

If I go a step further and remove the assigned values to the initial declaration of end to this:

var speed       = 600
var start       = get_node("iceShelfGoup").get_pos()
var end         

I then get the following error:
Invalid type in function 'distance_to' in base 'Vector2'. Cannot convert argument 1 from Nil to Vector2.
on the following line:

var distance    = start.distance_to(end)

I'm GUESSING it's something obvious but my skills aren't there yet. I've had a good look around as I'm not trying to pester but I'm at my ends. I just can't see it despite it having to be right in front of my eyes.

You are redeclaring a variable, or making a new one with the same name as another, on another block.

 var end         = Vector2(0,0) # <--- variable end declared on function
 if placement == "up":
        var end = Vector2(150,0) # <--- a new variable end declared on if, 
                                                      is not the same one

The second time you don't need to create a new variable end but use the one that already exists (without the var).

Just this:

 var end         = Vector2(0,0) # <--- var end declared on function
 if placement == "up":
       end = Vector2(150,0) # <--- using the previously declared variable

The null error is because you are working over a second variable with the same name on another scope and never assigned a value to the original.

Ok now that's just plain embarrassing. I should have been able to see that. I was declaring a new variable (as you say). I'm a goose. Thank you again for such a great answer. I'm sure many others will learn from it in the future also.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.