Voltar para o Blog
Quest Log

Arrays e Listas no GDScript para Jogos

Fileira de caixas numeradas guardando itens de jogo representando um array na tela do editor da Godot

Aprenda arrays no GDScript com exemplos tipados na Godot 4: indices, append, erase, for, sort, shuffle e casos reais como inventario e high scores.

Ferramenta:Godot

Arrays e Listas no GDScript para Jogos

Quase todo jogo lida com grupos de coisas: os inimigos na tela, os itens da mochila, as dez maiores pontuacoes, as balas voando. Guardar cada um numa variavel separada seria loucura. Para isso existem os arrays no GDScript, tambem chamados de listas: uma unica variavel que guarda varios valores em ordem, acessados por um numero de posicao. Se voce ja entende logica de programacao para jogos, o array e o proximo bloco natural, porque ele aparece em toda mecanica que envolve quantidade. Neste texto eu mostro como criar, indexar, percorrer e manipular arrays na Godot 4, sempre com codigo tipado e dentro de uma cena de jogo de verdade.

A ideia e simples: pense numa fileira de caixas numeradas. A primeira caixa e a de numero 0, a segunda e a 1, e assim por diante. Cada caixa guarda um valor, e voce chega ate ele dizendo o numero da caixa. Esse numero e o indice. Listas no GDScript funcionam exatamente assim, e essa contagem que comeca no zero e o primeiro habito que voce precisa gravar.

O que e um array e como criar um tipado

Um array e uma colecao ordenada de valores. Em GDScript voce cria um com colchetes [], e, como em todo o resto do seu codigo, voce declara o tipo. Um array tipado usa a forma Array[Tipo], e isso faz a Godot recusar qualquer valor que nao seja daquele tipo.

# Array vazio, pronto pra receber itens depois
var inimigos: Array[Node] = []

# Array ja com valores iniciais
var vidas: Array[int] = [3, 3, 3]
var itens: Array[String] = ["espada", "pocao", "chave"]
var pontuacoes: Array[float] = [1200.5, 980.0, 750.0]

Repare no ganho de declarar o tipo. Array[int] so aceita numeros inteiros; se voce tentar dar um append de texto ali, a Godot reclama antes mesmo de rodar o jogo. Isso pega uma classe inteira de bugs bobos, tipo um placar que virou texto sem querer. Existe tambem o array cru, sem tipo (var coisas: Array = []), que aceita valores misturados, mas para a maioria dos casos num jogo o tipado deixa tudo mais seguro e mais rapido.

Indexar: pegando e mudando um item pela posicao

Para ler ou escrever um valor, use o indice entre colchetes. Lembre que a contagem comeca no 0:

var itens: Array[String] = ["espada", "pocao", "chave"]

# Ler
print(itens[0])   # "espada"
print(itens[2])   # "chave"

# Alterar o item de uma posicao
itens[1] = "pocao grande"

Um detalhe pratico da Godot 4: indice negativo conta de tras pra frente. Entao itens[-1] te da o ultimo item sem voce precisar calcular o tamanho, e itens[-2] da o penultimo. Isso e muito util quando voce so quer o item mais recente de uma fila.

print(itens[-1])  # "chave", o ultimo

Cuidado com o erro classico: pedir um indice que nao existe. Se o array tem tres itens (posicoes 0, 1 e 2) e voce pede itens[3], o jogo quebra em tempo de execucao. Sempre confira o tamanho antes de acessar uma posicao que pode nao estar la.

size, append e erase: crescer e encolher a lista

Tres operacoes aparecem o tempo todo. size() devolve quantos itens tem no array, append() adiciona um item no fim, e erase() remove um item pelo valor.

var inimigos: Array[String] = []

func spawnar(nome: String) -> void:
    inimigos.append(nome)
    print("Inimigos na tela: ", inimigos.size())

func remover_inimigo(nome: String) -> void:
    inimigos.erase(nome)  # tira a primeira ocorrencia daquele valor

Alem desses, vale conhecer alguns primos: pop_back() remove e devolve o ultimo item (otimo pra pilhas), pop_front() faz o mesmo com o primeiro (util pra filas), remove_at(indice) apaga pela posicao em vez do valor, e clear() esvazia o array inteiro de uma vez. Para saber se a lista esta vazia, is_empty() e mais direto que comparar o size() com zero.

func atualizar_horda() -> void:
    if inimigos.is_empty():
        print("Horda derrotada!")
    else:
        var proximo: String = inimigos.pop_front()
        print("Proximo a agir: ", proximo)

Percorrer com for: o pao com manteiga dos arrays

Ter uma lista so faz sentido quando voce processa todos os itens dela. Isso e trabalho de loop for, e o array combina com ele de forma natural: o for percorre item por item, do primeiro ao ultimo.

var itens: Array[String] = ["espada", "pocao", "chave"]

func listar_inventario() -> void:
    for item in itens:
        print("Item: ", item)

Quando voce precisa tambem da posicao de cada item, itere pelos indices com range(itens.size()):

func mostrar_com_numero() -> void:
    for i in range(itens.size()):
        print(i + 1, ") ", itens[i])
    # 1) espada
    # 2) pocao
    # 3) chave

Uma armadilha comum: nao remova itens do array enquanto voce o percorre com um for. Mexer no tamanho da lista no meio da iteracao bagunca a contagem e alguns itens acabam pulados. Se precisa apagar durante a varredura, um jeito seguro e iterar de tras pra frente com range(itens.size() - 1, -1, -1), assim remover um indice nao afeta os que ainda faltam visitar.

Se montar esses loops ainda te trava, ou se voce se pega copiando codigo de tutorial sem entender por que funciona, saiba que isso e normal no comeco. O que faz a ficha cair e escrever, errar e ver rodar. Um caminho guiado encurta muito esse processo.

Próximo nível
Quer aprender isso na prática?

No CursoGame.Dev você sai dos tutoriais soltos e constrói jogos publicáveis, com trilha progressiva, quests práticas e feedback real.

Conhecer a plataforma
+500 alunos4.9/5Garantia 7 dias

Operacoes uteis: has, find, sort e shuffle

O array traz metodos prontos que resolvem tarefas que apareceriam toda hora num jogo. Vale ter esses quatro na ponta da lingua.

O has() responde se um valor esta no array, otimo para checar posse antes de agir:

var chaves: Array[String] = ["chave_dourada"]

func pode_abrir_porta() -> bool:
    return chaves.has("chave_dourada")

O find() devolve o indice onde um valor esta, ou -1 se ele nao existe. Isso serve tanto para localizar quanto para checar presenca:

var fila: Array[String] = ["goblin", "orc", "slime"]

func posicao_na_fila(nome: String) -> int:
    return fila.find(nome)  # "orc" -> 1, "dragao" -> -1

O sort() ordena o array no lugar, do menor pro maior. Perfeito para um placar. E o shuffle() embaralha, o que serve pra sortear ordem de turno ou embaralhar um baralho de cartas.

var pontuacoes: Array[int] = [1200, 980, 1500, 750]

func ranquear() -> void:
    pontuacoes.sort()          # [750, 980, 1200, 1500]
    pontuacoes.reverse()       # [1500, 1200, 980, 750], maior primeiro

var baralho: Array[int] = [1, 2, 3, 4, 5]

func embaralhar() -> void:
    baralho.shuffle()          # ordem aleatoria a cada partida

Ainda tem o append_array() para juntar duas listas e o slice() para pegar um pedaco, mas com has, find, sort e shuffle voce ja cobre a maioria das mecanicas do dia a dia.

Arrays de arrays: montando uma grade

As vezes voce precisa de linhas e colunas, como um tabuleiro de jogo da velha, um mapa de tiles ou um grid de inventario. Para isso, cada item do array e ele mesmo outro array. E o famoso array bidimensional.

var tabuleiro: Array = [
    ["X", "O", "X"],
    ["O", "X", "O"],
    ["X", "O", "X"]
]

# Acessar: primeiro a linha, depois a coluna
func ler_celula(linha: int, coluna: int) -> String:
    return tabuleiro[linha][coluna]

func varrer_tabuleiro() -> void:
    for linha in tabuleiro:
        for celula in linha:
            print(celula)

Aqui o array externo fica sem o tipo interno porque cada elemento e outro array, mas a ideia de indexar segue igual: tabuleiro[0][2] le a terceira coluna da primeira linha. O for aninhado, um dentro do outro, percorre a grade inteira, linha por linha.

Array ou dicionario: qual escolher

Essa e a duvida certa na hora de guardar dados. A regra pratica e curta. Use array quando voce tem uma lista de coisas do mesmo tipo e a ordem importa, ou quando voce so precisa percorrer tudo: inimigos na tela, waypoints de um caminho, itens de um menu. Use dicionario quando voce quer achar um dado por um nome em vez de uma posicao, como a vida, a mana e o nivel de um personagem.

O sinal de que voce escolheu errado e ficar tentando lembrar qual indice guardava o que. Se voce se pega pensando "a vida era o indice 0 ou o 2?", esse dado pedia um nome, nao um numero, e o lugar dele e num dicionario. Para entender a fundo essa outra estrutura, leia o guia de dicionarios no Godot, que e o par natural deste post. Na pratica, os dois se combinam: e muito comum ter um array de dicionarios, uma lista de inimigos onde cada inimigo e um dicionario com nome, vida e dano.

Casos reais: inventario, fila de inimigos e high scores

Fecho com tres situacoes que voce vai codar cedo ou tarde. Um inventario simples e um array de itens onde voce adiciona ao pegar e remove ao usar:

var inventario: Array[String] = []

func pegar_item(item: String) -> void:
    inventario.append(item)

func usar_item(item: String) -> bool:
    if inventario.has(item):
        inventario.erase(item)
        return true
    return false

Uma fila de inimigos que agem em ordem casa com pop_front(), que sempre pega o proximo da frente e o retira da lista:

var fila: Array[String] = ["goblin", "orc", "slime"]

func proximo_turno() -> void:
    if not fila.is_empty():
        var atual: String = fila.pop_front()
        print("Turno de: ", atual)

E uma tabela de high scores usa append, sort e slice para manter so as cinco maiores pontuacoes:

var high_scores: Array[int] = [1500, 1200, 980, 750, 500]

func registrar_score(novo: int) -> void:
    high_scores.append(novo)
    high_scores.sort()
    high_scores.reverse()                 # maior primeiro
    high_scores = high_scores.slice(0, 5) # mantem so o top 5

Repare como cada exemplo mistura as pecas: um array tipado guarda os dados, os metodos manipulam, e um if decide o que fazer. Para organizar essas acoes em blocos reutilizaveis, revise funcoes no GDScript, e para tomar as decisoes dentro delas vale ver condicionais no GDScript. Array, funcao e condicional trabalham sempre lado a lado.

Por onde seguir

Listas no GDScript sao uma das ferramentas que voce mais vai usar, porque todo jogo trabalha com grupos de coisas. Guarde os habitos que fazem a diferenca: tipe o array com Array[Tipo] para a Godot pegar seus erros cedo, lembre que a contagem comeca no 0, use has e find antes de confiar num item, e nunca remova elementos no meio de um for comum. Com append, erase, size, sort e shuffle na cabeca, voce ja monta inventario, fila e placar sem travar.

O proximo passo e abrir a Godot e testar. Crie um array de tres inimigos e liste com um for. Depois adicione um quarto com append e remova um com erase. Depois monte um placar que ordena com sort. Cada exercicio curto fixa um metodo, e em pouco tempo o array deixa de ser conceito e vira reflexo. A logica nao entra pela leitura, entra pela mao.

Perguntas frequentes

Qual a diferenca entre Array e Array tipado no GDScript?

Um Array cru aceita qualquer coisa misturada dentro dele. Um Array tipado, como Array[int], so aceita o tipo que voce declarou, entao a Godot avisa o erro antes de rodar se um valor errado tentar entrar. Sempre prefira o tipado nos seus jogos.

Como pego o primeiro e o ultimo item de um array?

O primeiro item fica no indice 0, entao inimigos[0]. O ultimo fica em size() - 1, mas o jeito curto e inimigos[-1], porque indice negativo conta de tras pra frente na Godot 4. Metodos como front() e back() fazem a mesma coisa.

Quando uso array e quando uso dicionario no jogo?

Use array quando a ordem importa ou voce so precisa de uma lista de coisas do mesmo tipo, como inimigos na tela. Use dicionario quando quer achar um dado pelo nome, como os stats de um personagem. Os dois se combinam bem no mesmo projeto.