![]() |
Attention | Topic was automatically imported from the old Question2Answer platform. |
![]() |
Asked By | sugarbrace901 |
Hey all,
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. I moved over from python/pygame for obvious reasons.
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 i’ll 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)