Videojuego
Save the Valley
Juego sandbox 2D construido desde cero en C++ con una arquitectura de motor propia. Generación procedural de un mundo infinito, sistema de combate con varias armas, IA enemiga con máquinas de estados y renderizado optimizado por chunks, todo sin un motor de juego.
El problema
El objetivo nunca fue publicar un producto pulido, sino entender qué abstrae realmente un motor de juego. La mayoría de desarrolladores usa Unity o Unreal y nunca toca directamente un bucle de renderizado, un sistema de entidades o un pipeline de colisiones. Quería construir esas piezas yo mismo en C++ para formarme un modelo mental real de los sistemas de bajo nivel que de otro modo daría por sentados.
Decisiones clave
Sin motor de juego: C++ puro con SFML como única dependencia
SFML se encarga de la ventana, los eventos de entrada y el renderizado de texturas, y de nada más. No hay grafo de escena, ni motor de físicas, ni pipeline de assets. Escribir a mano el bucle de actualización de entidades, la partición espacial y el sistema de cámara me obligó a pensar en presupuestos de rendimiento y en la disposición de la memoria de una forma que un motor habría ocultado por completo.
Mundo dividido en chunks en lugar de cargar el mapa completo
Un mundo infinito no cabe entero en memoria. El mundo se divide en chunks de tamaño fijo y solo están activos los cercanos al jugador. Cuando el jugador cruza un umbral, los chunks que quedan atrás se serializan y descargan, y los que están por delante se cargan o se generan. Así el uso de memoria se mantiene constante sin importar cuánto avance el jugador.
Máquina de estados finita para la IA enemiga en lugar de árboles de comportamiento
Empecé a prototipar con una librería de árboles de comportamiento, pero era excesiva para tres estados: Idle, Wandering y Hunting. Una FSM con transiciones explícitas se leía en un solo archivo, era fácil de depurar imprimiendo el estado actual y lo bastante rápida como para que cientos de enemigos corrieran sin afectar el tiempo de frame. La complejidad solo se justifica cuando el problema la exige.
Ruido Simplex en lugar de Perlin para generar el terreno
El ruido Perlin produce artefactos visibles alineados con los ejes en ciertas frecuencias, y el terreno empieza a verse cuadriculado. El ruido Simplex es invariante a la rotación y tiene un gradiente más isotrópico, lo que da contornos de terreno más naturales sin posprocesado. El costo computacional es similar.
Resultado
El proyecto me llevó tres meses de tardes y fines de semana. Al final tenía un mundo infinito funcional, un sistema de combate con tres armas y una IA enemiga que perseguía al jugador entre chunks. Sobre todo, gané una comprensión concreta de los pipelines de renderizado, la partición espacial y la arquitectura del bucle de juego, que aplico en cada proyecto con sistemas en tiempo real.
Funcionalidades
Mundo procedural
- Chunks infinitos con carga y descarga dinámica
- Varios biomas con generación de terreno propia
- Autotiling para transiciones suaves entre tipos de casilla
- Objetos con colisión: árboles, rocas, estructuras
Sistema de combate
- Espada, hacha y martillo con hitboxes dinámicas
- Vida, daño y frames de invulnerabilidad temporal
- Animaciones de ataque, daño y muerte
IA enemiga
- Máquina de estados: Idle → Wandering → Hunting
- Detección del jugador por rango
- Persecución esquivando obstáculos
Renderizado
- Renderizado por chunks (solo se dibujan los visibles)
- Por capas: terreno / objetos / entidades
- Cámara suave + modo de depuración de colisiones
Demo
Generación del mundo
Combate