0 votes

The below code works for some moves but in some point the "new_empty" becomes null and balls stop change position with mouse click.

func valid_move(node):

for pos in all_positions():
    if pos.get_meta("occupied") == false:
        empty_pos = get_position2d(node.global_position)
        if "Red" in pos.name:
            reparenting(node, $RedZone/RedBalls)
        elif "Blue" in pos.name:
            reparenting(node, $BlueZone/BlueBalls)
        elif "Green" in pos.name:
            reparenting(node, $GreenBalls)
        elif "Center" in pos.name:
            reparenting(node, $GreenBalls)
        node.global_position = pos.global_position
        pos.set_meta("occupied", true)
empty_pos.set_meta("occupied", false)

func reparenting(child, new_parent):
    var old_parent = child.get_parent()
    var pos = child.global_position
    child.global_position = pos

func get_position2d(pos):
    var pos2d
    for i in range(all_positions().size()):
        if pos == all_positions()[i].global_position:
            pos2d = all_positions()[i]
    return pos2d    

I cannot find why this position became null. I'm using position2d to place the balls which aren't move, but I have 2 platforms which rotated on mouse click 45 degrees. At first I had all positions in MainScene, but I had problems with reparent and the order of nodes(sometimes balls were bellow the platforms), so I have now 8 positions in the one platform, 8 in the other and 9 in the MainScene.
After this change all balls are and go to the correct empty(1 at a time) position2d position. But after some moves the empty position become null. How to debug this to find how this position becomes null? All positions are static and the balls spawned to these positions in _ready.

Godot version 3.2.3 stable
in Engine by (219 points)
edited by

1 Answer

0 votes

This is a bit complicated and I am not sure if I get it.

newempty is an inside function variable. Every time You run valid_move function You introduce this variable as null, than iterate through all positions and newempty is set during this iteration. So the reason nothing happens after click and newempty is still null must be that all of Your positions meta become "ocupied" at some point.

The problem propably lies in line : setmeta("occupied", false) . Try to print it.
Other than that, maybe there is misconception in movement. What is the code for Input of click ? Are all balls moved
valid() in the same time ?

by (2,402 points)

I replaced newempty with emptypos which I declared it outside the function. It didn't make any difference though. I also tried to print the emptypos.name and the "occupied" meta after set it to false.
Those don't help because I get the correct positions and "occupied" value(false) until the empty
pos to become null. Then I get error for trying to setmeta in a nil instance(because emptypos became null). Seems that something happens with the positioning but I don't see any wrong positioning visually, until I get the null crash.
The on click code has nothing except the valid_move() method.
The balls don't move together. Every time the clicked ball moves.

Here is the input function:

func _ready():
    for child in all_balls():
        child.connect("input_event", self, "_on_Ball_input_event", [child] )
func _on_Ball_input_event(viewport, event, shape_idx, node):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT and not event.is_echo() and event.is_pressed():

After some more debuging I found that the problem starts in line which I set the emptypos. There I use a function to get the Position2D on that node's position. So I added a print statement in this function and I found that in some point(when I get the error) the node' s position doesn't match with any of the positions. I also printed the position which doesn't match.
I don't know if this is accurate, but I get that position and from the editor on mainScene I added a sprite(just for test) and I give it the non matching position. I found that the position isn't the same with the Position2d position. I checked 2 of them and the first was 4 pixels right from the Position2d and the second was about 2 pixels right and up
So, seems that at some point the ball' s global
position isn't the same with the position2d in which is moved. But, because I print the positions also, until then the old and new position are exactly the same.

Seems that the problem with shifting positions comes from the circular platforms when rotating. I have set the center property on but again the rotation isn't pefect and because the position2d are children of them after some rotations the positions of them change a bit.
The problem is that I don't know how to get perfect rotations. I tried to correct the textures and reselect the areas from atlas picture and it's better now but still not perfect rotation, so the errors occure still.

After many other things I tried and couldn't get get rid of the error, I thought that maybe this was to complicated and need to find a simpler way.
So, Instead of use the Position2D positions, I created a sprite with a transparent texture and use this as the empty spot.
Then I just swap the clicked ball position with the empty(transparent) sprite position:

func valid_move(node):
    var nodepos = node.global_position
    var node_parent = node.get_parent()
    var hole_parent = hole.get_parent()
    node.global_position = hole.global_position
    reparenting(node, hole_parent)
    hole.global_position = nodepos
    reparenting(hole, node_parent)

And this works fine. Now just need to find a way to actually define the valid moves.

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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.