1
\$\begingroup\$

I'm fairly new to Godot, but I've been programming games for a bit. I understand GDScript, but using it fully still escapes me. So i'm still learning/struggling.

Anyway, I'm working on a sokoban style puzzle game (grid based movement) and I want blocks that have moved next each other to 'combine' and move together. Kinda like legos. I'm currently using raycast2D to detect collision between sprites, and it has been successful, but I receive an error when the sprite being moved collides with a wall (object in tilemap).

This is the error: Invalid get index 'position' (on base: 'Node').

To track the position i'm essentially grabbing colliding sprite and saving it once in a variable. Then I match the collided sprites position to that of the one that is in 'control' or allowed to move, but again I receive the error when the control sprite reaches a collision.

The idea behind control is that ill have multiple instances of a sprite and have the ability to shuffle control between the various sprites in a scene.

Here is the sprite script:

extends Sprite

# if the sprite is currently in control, can be rotated with space
export var Control = false

# make the raycast available to use in the player script
onready var ray = $Area2D/RayCast2D
onready var rayUP = $Area2D/rayUP
onready var rayDOWN = $Area2D/rayDOWN
onready var rayLEFT = $Area2D/rayLEFT
onready var rayRIGHT = $Area2D/rayRIGHT

# detect collision only once with these flags
var colUP = false
var colDOWN = false
var colLEFT = false
var colRIGHT = false

var UColSprite
var DColSprite
var LColSprite
var RColSprite

var speed = 600 # large speed value to determine how fast the sprite will move
var tile_size = 64 # size in pixels of the tiles on the grid

var last_position = position # last idle position to keep track of
var target_position = position # new position to be moved to
var movedir = Vector2(0, 0) # the move direction 

# init function
func _ready():
    # snap the player to a grid position if misplaced
    # and update its position trackers to the snapped vector2
    position = position.snapped(Vector2(tile_size, tile_size))
    last_position = position
    target_position = position

# set move direction based on player input
func get_movedir():
    # collect the input and store it
    var LEFT = Input.is_action_pressed("ui_left")
    var RIGHT = Input.is_action_pressed("ui_right")
    var UP = Input.is_action_pressed("ui_up")
    var DOWN = Input.is_action_pressed("ui_down")

    # process the movement based on each vector
    movedir.x = -int(LEFT) + int(RIGHT) # is negative one if moving left and vice versa, if both then zero
    movedir.y = -int(UP) + int(DOWN) # same up with y

    # prevent diagonal movement
    if movedir.x !=0 && movedir.y != 0:
        movedir = Vector2.ZERO # no value

    # set the end of the ray cast to the edge of the player sprite
    if movedir != Vector2.ZERO:
        ray.cast_to = movedir * tile_size / 2

# process movement every frame
func _process(delta):

    if Control == true:
        # idle
        if position == target_position:
            get_movedir()
            last_position = position # save the players current position
            target_position += movedir * tile_size # if movement, then calculate new target position


        # moving
        else:

            # make sure not to move the player if they will collide with a wall
            if ray.is_colliding():
                target_position = last_position # set the player back to there original location
            else:
                # update the position
                position += speed * movedir * delta

                # prevent the player from moving past the target
                var distance = (position - last_position).abs().length() # how far they moved frem the idle position

                # track the distance
                if distance > tile_size - speed * delta:
                    # subtract speed * delta so there's no break/pause in movement
                    position = target_position
    else:
        # if the sprite is not being controlled, collect a collision if the controlled sprite moved next to it6

        if rayUP.is_colliding():
            if colUP == false:
                colUP = true
                UColSprite = rayUP.get_collider().get_parent()
            position = UColSprite.position - Vector2(0, 64)


        if rayDOWN.is_colliding():
            if colDOWN == false:
                colDOWN = true
                DColSprite = rayDOWN.get_collider().get_parent()
            position = DColSprite.position + Vector2(0, 64)

        if rayLEFT.is_colliding():
            if colLEFT == false:
                colLEFT = true
                LColSprite = rayLEFT.get_collider().get_parent()
            position = LColSprite.position + Vector2(64, 0)

        if rayRIGHT.is_colliding():
            if colRIGHT == false:
                colRIGHT = true
                RColSprite = rayRIGHT.get_collider().get_parent()
            position = RColSprite.position - Vector2(64, 0)
\$\endgroup\$
0
\$\begingroup\$

Tilemap Collision

Invalid get index 'position' (on base: 'Node')

The Error

The above means that the collider's(The Tilemap) get_parent() is likely the root Node in your scene.

This error message indicates that the method(position) cannot be found in the node(Node) that you are trying to detect.

Raycaster

When your Raycast detects the Tilemap, it tries to get_parent() and finds the root Node, which has no position method.

A solution I may have is to alter the collision mask of your Sprite's Raycaster so that it will only collide with objects on a certain layer.Then placing the Tilemap on a separate layer should solve it if I'm right.

Good Luck!

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks! I figured it out based on your response. The Tilemap within my level scene tree was reporting collision to the root of the scene, which like you said has no "position". I just had to turn collision with bodies off within the raycast2D nodes that I have attached to my sprite to stop the error from occurring! \$\endgroup\$ – Shawn Benson Mar 31 at 16:53
  • \$\begingroup\$ @ShawnBenson That's great! This is my first successful answer on Gamedev. Good Luck! \$\endgroup\$ – Kennichi Nitta Mar 31 at 22:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.