Escenas, nodos y recursos en Godot para construir un juego 2D

Capítulo 3

Tiempo estimado de lectura: 8 minutos

+ Ejercicio

Composición por nodos: cómo “se construye” un objeto en Godot

En Godot, un objeto de juego no suele ser una clase monolítica, sino una escena compuesta por nodos. Cada nodo aporta una responsabilidad concreta: transformaciones, render, colisiones, lógica, detección, audio, etc. Esta composición facilita reutilizar piezas, intercambiar componentes y mantener el proyecto escalable.

Nodos clave en 2D y para qué se usan

  • Node2D: base para elementos 2D con posición/rotación/escala. Útil como “contenedor” o raíz cuando no necesitas física.
  • Sprite2D: muestra una textura estática (un PNG, por ejemplo).
  • AnimatedSprite2D: reproduce animaciones basadas en SpriteFrames (ideal para personajes y efectos 2D frame a frame).
  • CollisionShape2D: define la forma de colisión (rectángulo, círculo, cápsula, polígono) para un nodo de física o detección.
  • CharacterBody2D: cuerpo cinemático para personajes controlados por código (movimiento con move_and_slide(), gravedad, saltos).
  • Area2D: zona de detección (triggers): recoger ítems, daño, zonas de interacción, checkpoints.

Recursos: lo que “se enchufa” a los nodos

Los nodos suelen referenciar recursos (assets y configuraciones serializables). Un recurso se puede reutilizar en múltiples escenas y nodos sin duplicar configuración.

Ejemplos de recursos comunes

  • Texturas: asignadas a Sprite2D.texture.
  • Animaciones: en AnimatedSprite2D mediante un recurso SpriteFrames.
  • Fuentes: recursos de fuente para UI (por ejemplo, en Label o RichTextLabel).
  • Audio: AudioStream (WAV/OGG) usado por AudioStreamPlayer o AudioStreamPlayer2D.

Idea práctica: si varios enemigos comparten el mismo set de animaciones, conviene que todos apunten al mismo recurso SpriteFrames. Si un enemigo necesita variantes, puedes duplicar el recurso y modificarlo sin afectar a los demás.

Secuencia práctica: de cero a un objeto jugable reutilizable

La siguiente secuencia te sirve como patrón para construir cualquier elemento 2D: elegir nodos adecuados, añadir visuales, agregar colisiones y convertirlo en una escena reutilizable.

Paso 1: elegir el nodo raíz adecuado

Antes de arrastrar nodos, decide qué comportamiento físico o de detección necesitas:

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

  • ¿Se mueve y colisiona como personaje controlado? Usa CharacterBody2D como raíz.
  • ¿Es un objeto estático solo visual (decoración)? Usa Node2D con Sprite2D (sin colisiones) o con colisión si lo necesitas.
  • ¿Es un trigger (zona de daño, pickup, interacción)? Usa Area2D como raíz.

Regla mental: el nodo raíz suele ser el que define “cómo existe” el objeto en el mundo (física, detección o simple transform).

Paso 2: añadir el componente visual (Sprite2D o AnimatedSprite2D)

Una vez elegido el nodo raíz, añade un nodo visual como hijo:

  • Para imagen fija: añade Sprite2D y asigna Texture.
  • Para animación por frames: añade AnimatedSprite2D y crea/asigna un recurso SpriteFrames.

Consejo: mantén el nodo visual como hijo del nodo raíz para que herede transformaciones. Si necesitas “ajustar” el sprite sin afectar la colisión (por ejemplo, centrarlo), mueve el Sprite2D localmente, no el nodo raíz.

Ejemplo: configurar AnimatedSprite2D con SpriteFrames

  1. Crea un AnimatedSprite2D.
  2. En la propiedad Sprite Frames, crea un nuevo recurso SpriteFrames.
  3. Agrega animaciones (por ejemplo: idle, run, jump), y arrastra los frames correspondientes.
  4. Activa Playing si quieres previsualizar, y define la animación por defecto.

Paso 3: agregar colisiones (CollisionShape2D) de forma correcta

Las colisiones no se dibujan “solas”: se definen con CollisionShape2D como hijo del nodo que colisiona o detecta. El tipo de nodo padre determina el uso:

  • CharacterBody2D + CollisionShape2D: colisión física para movimiento del personaje.
  • Area2D + CollisionShape2D: detección de solapamientos (triggers).

Buenas prácticas al crear la forma:

  • Elige una forma simple (rectángulo/cápsula) para rendimiento y estabilidad.
  • Ajusta la colisión al “volumen jugable”, no al pixel-perfect del sprite. Esto mejora la sensación de control.
  • Evita escalar el CollisionShape2D con escalas raras; es preferible editar el tamaño de la forma (por ejemplo, el RectangleShape2D.extents).

Mini-guía: personaje con CharacterBody2D

Estructura típica:

Player (CharacterBody2D)\n├─ AnimatedSprite2D\n└─ CollisionShape2D

Ejemplo de movimiento básico (conceptual) para ubicar responsabilidades: el CharacterBody2D gestiona velocidad y movimiento; el sprite solo representa el estado.

extends CharacterBody2D\n\n@export var speed := 200.0\n@export var gravity := 900.0\n\nfunc _physics_process(delta):\n    if not is_on_floor():\n        velocity.y += gravity * delta\n\n    var dir := Input.get_axis("ui_left", "ui_right")\n    velocity.x = dir * speed\n\n    move_and_slide()

Nota: este fragmento no “crea” la colisión; asume que ya existe un CollisionShape2D bien configurado como hijo.

Paso 4: usar Area2D para interacción, pickups y daño

Area2D es ideal cuando no quieres empujar físicamente, sino detectar. Estructura típica de un ítem coleccionable:

Coin (Area2D)\n├─ Sprite2D\n└─ CollisionShape2D

Conecta la señal body_entered para reaccionar cuando un cuerpo (por ejemplo, el jugador) entra en el área:

extends Area2D\n\nfunc _on_body_entered(body):\n    if body.name == "Player":\n        queue_free()

En proyectos reales, en lugar de comparar por nombre, suele ser mejor usar grupos (por ejemplo, body.is_in_group("player")) para mantener el código flexible.

Convertir elementos en escenas reutilizables

Una escena en Godot es un árbol de nodos guardado como archivo (.tscn) que puedes instanciar en otras escenas. Convertir un conjunto de nodos en una escena te permite:

  • Reutilizar el mismo objeto (enemigo, moneda, puerta) en múltiples niveles.
  • Editar una sola vez y propagar cambios a todas las instancias.
  • Encapsular lógica y señales dentro de un “módulo” claro.

Guía paso a paso: de nodos sueltos a escena

  1. Crea el árbol de nodos (por ejemplo, Area2D + Sprite2D + CollisionShape2D).
  2. Configura recursos (textura, forma de colisión, animaciones si aplica).
  3. Adjunta el script al nodo raíz (por ejemplo, al Area2D).
  4. Guarda como escena (por ejemplo, Coin.tscn).
  5. Instancia la escena en un nivel: arrástrala desde el FileSystem o instánciala por código.

Instanciar por código (ejemplo)

@export var coin_scene: PackedScene\n\nfunc spawn_coin(pos: Vector2):\n    var coin = coin_scene.instantiate()\n    coin.global_position = pos\n    add_child(coin)

PackedScene es un recurso que representa una escena lista para instanciar. Es una forma limpia de spawnear enemigos, proyectiles o pickups.

Criterios: ¿crear una escena nueva o añadir un nodo dentro de la misma escena?

Esta decisión impacta directamente en la mantenibilidad. Usa estos criterios prácticos:

Crea una escena nueva cuando…

  • Se reutiliza en más de un lugar (monedas, enemigos, puertas, UI widgets repetidos).
  • Tiene lógica propia (scripts, señales, estados) que conviene encapsular.
  • Necesitas variantes (por ejemplo, EnemyBase.tscn y escenas heredadas o duplicadas para tipos distintos).
  • El árbol de nodos crece y empieza a “ensuciar” la escena principal.
  • Requiere pruebas aisladas: abrir la escena del objeto y testearlo sin cargar el nivel completo.

Manténlo como nodo dentro de la misma escena cuando…

  • Es único y no se repetirá (un fondo específico de un nivel, un trigger exclusivo).
  • Es muy simple y no tiene lógica (por ejemplo, un Sprite2D decorativo).
  • Depende fuertemente del contexto del nivel (por ejemplo, un conjunto de plataformas colocadas a mano que no se reutilizarán).

Regla práctica de escalado

Si dudas, empieza como nodos dentro de la escena. En el momento en que lo copies/pegues por segunda vez o le agregues lógica propia, es una señal clara para convertirlo en escena. Godot facilita refactorizar: puedes seleccionar un nodo con sus hijos y guardarlo como escena para reutilizarlo.

Patrones de composición recomendados (plantillas mentales)

Decoración estática

Decoration (Node2D)\n└─ Sprite2D

Objeto interactivo tipo trigger

Trigger (Area2D)\n├─ Sprite2D\n└─ CollisionShape2D

Personaje controlable

Player (CharacterBody2D)\n├─ AnimatedSprite2D\n└─ CollisionShape2D

Separar visual de colisión (cuando necesitas offsets)

Enemy (CharacterBody2D)\n├─ Visual (Node2D)\n│  └─ AnimatedSprite2D\n└─ CollisionShape2D

Este patrón permite mover Visual para ajustar animaciones (por ejemplo, un ataque que se estira) sin romper la colisión base.

Recursos en la práctica: cómo organizarlos para reutilización

Texturas

  • Úsalas en Sprite2D o como frames de SpriteFrames.
  • Si cambias una textura compartida, afectará a todos los nodos que la referencien.

Animaciones (SpriteFrames)

  • Un solo recurso SpriteFrames puede contener múltiples animaciones.
  • Si varios personajes comparten animaciones, apunta al mismo SpriteFrames para consistencia.

Fuentes

  • Define una fuente como recurso y reutilízala en toda la UI para coherencia visual.
  • Si necesitas tamaños distintos, puedes crear variaciones (o configurar overrides por nodo según tu flujo).

Audio

  • Un AudioStream (recurso) se asigna a un reproductor (AudioStreamPlayer2D para sonido posicional).
  • Reutiliza el mismo recurso de audio para múltiples instancias (por ejemplo, el mismo sonido de moneda).
NecesidadNodo típicoRecurso asociado
Imagen fijaSprite2DTexture2D
Animación por framesAnimatedSprite2DSpriteFrames
Colisión físicaCharacterBody2DShape2D (en CollisionShape2D)
Detección/triggerArea2DShape2D (en CollisionShape2D)
Sonido 2DAudioStreamPlayer2DAudioStream

Ahora responde el ejercicio sobre el contenido:

Al crear una moneda coleccionable que solo necesita detectar cuando el jugador la toca (sin empujar ni aplicar física), ¿qué estructura de nodos es la más adecuada?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

Para un pickup que solo debe detectar al jugador, se usa Area2D como raíz y un CollisionShape2D como hijo para definir la zona de solapamiento. El sprite es el componente visual.

Siguiente capítulo

Fundamentos de GDScript para la lógica de juego en Godot

Arrow Right Icon
Portada de libro electrónico gratuitaGodot desde Cero: Crea tu Primer Juego 2D con GDScript
25%

Godot desde Cero: Crea tu Primer Juego 2D con GDScript

Nuevo curso

12 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.