Invalid get index '(x, y)' (on base: 'Array').

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By R0dL0d

Sooo. i did a questin 4 days ago, it solve my problem, but it creted another problem…
i’m doing a game like candy-crush, for a school project. got it in a totorial in youtube but i video is kinda old (4 years ago) and i think some codes are wrong or something, now i’m trying to do a ice piece.

The problem is when i match any 3 pieces in the grid. got this error of invalid index ‘(x, y)’ (x and y are number of the grid. is a random number).

the code that is gettin the error:

func _on_Grid_damage_ice(board_position : Vector2):
	*if ice_pieces[board_position] != null:*
		ice_pieces[board_position].take_damage(1)
		if ice_pieces[board_position].health <= 0:
			ice_pieces[board_position] = null

The error mark the second line with the error. but i think is all the func have a problem.

i have separeted codes to the grid and this code

this is the main code:

extends Node2D

#state machine
enum {wait, move}
var state

# Grid Variaveis
export (int) var width;
export (int) var height;
export (int) var x_start;
export (int) var y_start;
export (int) var offset;
export (int) var y_offset;

# obstacle Stuff
export (PoolVector2Array) var empty_spaces
export (PoolVector2Array) var ice_spaces

#obstacle signals
signal damage_ice
signal make_ice

#The piece array
var possible_pieces = [
preload("res://Cenario peças/banana.tscn"),
preload("res://Cenario peças/dragao.tscn"),
preload("res://Cenario peças/melancia.tscn"),
preload("res://Cenario peças/tomato.tscn"),
preload("res://Cenario peças/maça.tscn"),
preload("res://Cenario peças/uva.tscn")	
];

# the current  pieces in the scene
var all_pieces =[];

#swap back variable
var piece_one = null
var piece_two = null
var last_place = Vector2(0,0)
var last_direction = Vector2(0, 0)
var move_checked = false
# Touch variable
var first_touch  = Vector2(0, 0);
var final_touch  = Vector2(0, 0);
var controlling = false;

func _ready():
	state = move
	randomize();
	all_pieces  = make_2d_array();
	spawn_pieces();
	spawn_ice();
	print(possible_pieces)
	
func restricted_fill(place):
	#check thepty pieces
	if is_in_array(empty_spaces, place):
		return true
	return false	
	
			
	
func is_in_array(array, item):
	for i in array.size():
		if array[i] == item:
			return true
	return false			
	
func make_2d_array():
	var array = [];
	for i in width:
		   array.append([]);
		   for j in height:
			   array[i].append(null)
	return array;
	
func spawn_pieces():
	for i in width:
		for j in height:
			if !restricted_fill(Vector2(i, j)):
			#choose a random number and store it
				var rand = floor(rand_range(0, possible_pieces.size()));
				var piece = possible_pieces[rand].instance();
				var loops = 0
				while(match_at(i, j, piece.color) && loops < 100):
					rand = floor(rand_range(0, possible_pieces.size()));
					loops += 1;
					piece = possible_pieces[rand].instance();
			#instance that piece from the array
				add_child(piece);
				piece.position = grid_to_pixel(i, j);
				all_pieces[i][j] = piece;
				print (possible_pieces[rand])

func spawn_ice():
	for i in ice_spaces.size():
		emit_signal("make_ice", ice_spaces[i])
	

func match_at(i, j, color):
	
	if i > 1:
		if all_pieces[i - 1][j] != null && all_pieces[i - 2][j] != null:
			if all_pieces[i - 1][j].color == color && all_pieces[i - 2][j].color == color:
				return true;
	if j > 1:
		if all_pieces[i][j - 1] != null && all_pieces[i][j - 2] != null:
			if all_pieces[i][j - 1].color == color && all_pieces[i][j - 2].color == color:
				return true;
				
	
func grid_to_pixel(column, row):
	var new_x = x_start + offset * column;
	var new_y = y_start + -offset * row;
	return Vector2(new_x, new_y);
	
func pixel_to_grid(pixel_x, pixel_y):
	var new_x = round((pixel_x - x_start) / offset);
	var new_y = round((pixel_y - y_start) / -offset);
	return Vector2(new_x, new_y);
	pass;	
	
func is_in_grid(grid_position):
	if grid_position.x >= 0 && grid_position.x < width:
		if grid_position.y >= 0 && grid_position.y < height:
			return true;
	return false;			
	
func touch_input():
	
	if Input.is_action_just_pressed("ui_touch"):		
		if is_in_grid(pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y)):
			first_touch = pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y);
			controlling = true
	if Input.is_action_just_released("ui_touch"):
		if is_in_grid(pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y)) && controlling:
			controlling = false;
			final_touch= pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y)
			touch_difference(first_touch, final_touch);

func swap_pieces(column, row, direction):			
	var first_piece = all_pieces[column][row];
	var other_piece = all_pieces[column + direction.x][row + direction.y];
	if first_piece != null && other_piece != null:
		store_info(first_piece, other_piece, Vector2(column, row), direction)
		state = wait
		all_pieces[column][row] = other_piece;
		all_pieces[column + direction.x][row + direction.y] = first_piece;
		first_piece.move(grid_to_pixel(column + direction.x, row + direction.y));
		other_piece.move(grid_to_pixel(column, row));
		if !move_checked:
			find_matches()
	
func store_info(first_piece, other_piece, place, direction):
	piece_one = first_piece
	piece_two = other_piece
	last_place = place
	last_direction = direction
	pass
func swap_back():
	#LOL
	if piece_one != null && piece_two != null:
		swap_pieces(last_place.x, last_place.y, last_direction)
	state = move
	move_checked = false
	pass
			
func touch_difference(grid_1, grid_2):
	var difference = grid_2 - grid_1;
	if abs(difference.x) > abs(difference.y):
		if difference.x > 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(1, 0));
		elif difference.x < 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(-1, 0));
	elif abs(difference.y) > abs(difference.x):
		if difference.y > 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(0, 1));
		elif difference.y < 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(0, -1));
		pass;
	
func _process(delta):
	if state == move:
		touch_input();
	
	
func find_matches():
	for i in width:
		for j in height:
			if all_pieces[i][j] != null:
				var current_color = all_pieces[i][j].color
				if i > 0 && i < width - 1:
					if !is_piece_null(i - 1, j) && all_pieces[i + 1][j] != null:
						if all_pieces[i - 1][j].color == current_color && all_pieces[i + 1][j].color == current_color:
							match_and_dim(all_pieces[i - 1][j])
							match_and_dim(all_pieces[i][j])
							match_and_dim(all_pieces[i + 1][j])
							all_pieces[i][j].matched = true;
							all_pieces[i][j].dim();
							all_pieces[i + 1][j].matched = true;
							all_pieces[i + 1][j].dim();
				if j > 0 && j < height - 1:
					if all_pieces[i][j - 1] != null && all_pieces[i][j + 1] != null:
						if all_pieces[i][j - 1].color == current_color && all_pieces[i][j + 1].color == current_color:
							match_and_dim(all_pieces[i][j - 1])
							match_and_dim(all_pieces[i][j])
							match_and_dim(all_pieces[i][j + 1])
							all_pieces[i][j].matched = true;
							all_pieces[i][j].dim();
							all_pieces[i][j + 1].matched = true;
							all_pieces[i][j + 1].dim();
	get_parent()	.get_node("destroy_timer").start()	
	
	
func is_piece_null(column, row):
	if all_pieces[column][row] == null:
		return true
	return false	
		
	
func match_and_dim(item):
	item.matched = true
	item.dim()
									

func destroy_matched():
	var was_matched = false
	for i in width:
		for j in height:
			if all_pieces[i][j] != null:
				if all_pieces[i][j].matched:
					emit_signal("damage_ice", Vector2(i,j))
					was_matched = true
					all_pieces[i][j].queue_free()
					all_pieces[i][j] = null
	move_checked = true
	if was_matched:
		get_parent().get_node("Collapse_timer").start()
	else:	
		swap_back()
func collapse_collums():
	for i in width:
		for j in height:
			if all_pieces[i][j] == null && !restricted_fill(Vector2(i, j)):
				for k in range(j + 1, height):
					if all_pieces[i][k] != null:
						all_pieces[i][k].move(grid_to_pixel(i, j))
						all_pieces[i][j] = all_pieces[i][k]
						all_pieces[i][k] = null
						break
	get_parent().get_node("refil_timer").start()						
func refill_columns():
	for i in width:
		for j in height:
			if all_pieces[i][j] == null && !restricted_fill(Vector2(i, j)):
				var rand = floor(rand_range(0, possible_pieces.size()));
				var piece = possible_pieces[rand].instance();
				var loops = 0
				while(match_at(i, j, piece.color) && loops < 100):
					rand = floor(rand_range(0, possible_pieces.size()));
					loops += 1;
					piece = possible_pieces[rand].instance();
				#instance that piece from the array
				add_child(piece);
				piece.position = grid_to_pixel(i, j - y_offset);
				piece.move(grid_to_pixel(i, j));
				all_pieces[i][j] = piece;
	after_refil()

func after_refil():
	for i in width:
		for j in height:
			if all_pieces[i][j] != null:
				if match_at(i, j, all_pieces[i][j].color):
					find_matches()
					get_parent().get_node("destroy_timer").start()
					return
	state = move
	move_checked = false

func _on_destroy_timer_timeout():
	destroy_matched()

func _on_Collapse_timer_timeout():
	collapse_collums()

func _on_refil_timer_timeout():
	refill_columns()
	

and i got a script for the pieces in the grid:

    extends Node2D

export (String) var color;
var move_tween;
var matched = false


func _ready():
	move_tween = get_node("Sprite/move_tween")
	
	pass # Replace with function body.

func move(target):
	move_tween.interpolate_property(self, "position", position, target, .3,
								   Tween.TRANS_BOUNCE, Tween.EASE_OUT);
	move_tween.start();
	pass;

# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#	pass

func dim():
	var sprite = get_node("Sprite")
	sprite.modulate = Color(1, 1, 1, .5);
	pass

By interest the video i’m referring is this link:

any questions is just ask.

:bust_in_silhouette: Reply From: Ninfur

Getting a value from an array like this ice_pieces[board_position], requires the corresponding value to actually exist in the array. Otherwise you’ll get that error.

What I believe you want to do is to use array.get(..), like this:

if ice_pieces.get(board_position) != null:

The get function will return null if the value is not found in the array, while array[key] will cause an error.

Alternatively, make sure your array is initialized properly and the data you are trying to get already exists in it.