Odin y Raylib: desarrollo de juegos 2D sin motor como alternativa ligera a Godot

Odin tiene una ventaja poco conocida: Raylib viene incluido de serie. En el directorio vendor del compilador hay bindings completos para Raylib, la librería de gráficos, audio e input para juegos 2D y 3D. No hace falta instalar nada extra ni gestionar dependencias: descarga Odin, escribe código, compila.

Este artículo cubre el camino desde el primer programa hasta un juego 2D básico con física simple, y explica por qué la combinación Odin + Raylib se ha convertido en una alternativa real a Godot con GDScript o Unity con C# para quien prefiere control sobre abstracción.

Por qué Raylib en lugar de un motor

Godot, Unity o Bevy hacen mucho por ti: gestión de escenas, editor visual, física integrada, audio con efectos, animaciones, exportación multiplataforma. A cambio, trabajas dentro de sus abstracciones y asumes su complejidad.

Raylib es lo contrario: una librería que dibuja cosas, procesa input y reproduce audio. Sin editor, sin escenas, sin sistemas de componentes. El juego es un programa que llama a funciones. Esto es más trabajo, pero también control total: sabes exactamente qué hace tu juego y por qué.

Odin encaja perfectamente en esa filosofía. Es un lenguaje que compila a código nativo, sin runtime ni GC, con un modelo de memoria manual pero ergonómico.

Configuración inicial

Con Odin instalado, crear un proyecto es tan sencillo como un directorio con un fichero:

mkdir mi-juego
cd mi-juego
# crear main.odin

El programa mínimo con Raylib en Odin:

package main

import rl "vendor:raylib"

main :: proc() {
    rl.InitWindow(800, 600, "Mi Juego")
    defer rl.CloseWindow()

    for !rl.WindowShouldClose() {
        rl.BeginDrawing()
        rl.ClearBackground(rl.DARKBLUE)
        rl.DrawText("Hola, Odin + Raylib", 250, 270, 30, rl.WHITE)
        rl.EndDrawing()
    }
}

Compilar y ejecutar:

odin run . -file

Un personaje con movimiento y gravedad

El siguiente paso natural es añadir un sprite que se mueva. Odin no tiene un sistema de física, así que lo implementamos nosotros. Aquí la estructura básica de un personaje con gravedad y salto:

package main

import rl "vendor:raylib"

Player :: struct {
    pos:      rl.Vector2,
    vel:      rl.Vector2,
    on_floor: bool,
}

GRAVITY :: f32(800.0)
JUMP_FORCE :: f32(-400.0)
SPEED :: f32(200.0)

update_player :: proc(p: ^Player, dt: f32) {
    // Gravedad
    p.vel.y += GRAVITY * dt

    // Movimiento horizontal
    p.vel.x = 0
    if rl.IsKeyDown(.LEFT)  { p.vel.x = -SPEED }
    if rl.IsKeyDown(.RIGHT) { p.vel.x =  SPEED }

    // Salto
    if rl.IsKeyPressed(.SPACE) && p.on_floor {
        p.vel.y = JUMP_FORCE
        p.on_floor = false
    }

    // Actualizar posición
    p.pos += p.vel * dt

    // Suelo simple
    if p.pos.y >= 500 {
        p.pos.y = 500
        p.vel.y = 0
        p.on_floor = true
    }
}

SOA para muchos sprites

Una de las características distintivas de Odin es el soporte nativo para Structure of Arrays (SOA). En lugar de un array de structs (la forma habitual), puedes tener un struct de arrays. Para juegos con muchos enemigos o partículas, esto mejora el rendimiento de caché considerablemente:

// Array de structs (AOS) - normal
Enemies_AOS :: [100]Enemy

// Struct de arrays (SOA) - mejor para caché
Enemies_SOA :: #soa [100]Enemy

Cuando iteras para actualizar posiciones, accedes a enemies.pos[i] en lugar de enemies[i].pos. Los datos de posición de todos los enemigos están contiguos en memoria, lo que mejora la localidad de caché en bucles de actualización masivos.

Recursos para seguir

El tutorial de Karl Zylinski en zylinski.se es la referencia principal para Odin + Raylib: cubre desde el setup hasta un juego completo con colisiones, sprites animados y audio. El libro «Understanding the Odin Programming Language» (odinbook.com) profundiza en el lenguaje en sí.

Para entender mejor el lenguaje antes de empezar con juegos, el artículo sobre Odin: el lenguaje que enamora a los que vienen de C da el contexto necesario.

Imagen: Pexels / Rafael Minguet Delgado

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP