{}const=>[]async()letfn</>var
LuaDesarrollo

Lua en una noche: de cero a una misión de RPG de texto en unos pocos pasos

Entendiendo el lenguaje Lua desde cero, sin aburrimiento y con memes. Instalaremos Lua, analizaremos las variables, tablas, funciones y bucles, y al final escribiremos una misión RPG de texto completa con un sistema de combate, trampas e inventario. Todo de una sola vez.

К

Kodik

Autor

10 min de lectura

¿Conoces esa sensación cuando descubres un nuevo lenguaje de programación y durante los primeros 20 minutos piensas: «Vaya, es fácil»? Y luego empieza. Los paréntesis no son los correctos, se te ha olvidado el punto y coma, el compilador te grita como un vecino de arriba a las 3 de la madrugada.

Con Lua todo es diferente. En serio. Este lenguaje es tan conciso que puedes aprender sus conceptos básicos mientras te tomas un café. Y en una noche, puedes armar un miniproyecto completamente funcional. ¿No lo crees? Bueno, vamos a comprobarlo.

¿Qué es Lua y por qué lo necesito?

Lua (se pronuncia «Lu-a», no «Lua», pero, sinceramente, cada uno lo dice como quiere) es un lenguaje de programación ligero que nació en Brasil en 1993. Sí, es más antiguo que la mayoría de los frameworks de JavaScript. Y, a diferencia de ellos, todavía no está deprecated.

Dónde se utiliza Lua:

  • Juegos - Roblox, World of Warcraft, Garry's Mod, Love2D. Si alguna vez has escrito un complemento para WoW, ya eres un desarrollador de Lua, ¡enhorabuena!

  • Nginx y OpenResty — los servidores web de alta carga ejecutan scripts Lua para procesar las solicitudes.

  • Neovim — si eres de los que pasan más tiempo configurando su editor que escribiendo código, Lua es tu nuevo mejor amigo.

  • Sistemas integrados e IoT — Lua es tan ligero que funciona incluso donde Python se ahoga.

En resumen, Lua es como una navaja suiza, solo que sin sacacorchos. Compacto, útil y sorprendentemente potente.

🔥 100.000+ estudiantes ya están con nosotros

¿Cansado de leer teoría?
¡Hora de programar!

Kodik — una app donde aprendes a programar con práctica. Mentor IA, lecciones interactivas, proyectos reales.

🤖 IA 24/7
🎓 Certificados
💰 Gratis
🚀 Empezar
Se unieron hoy

Paso 0: Instalación (más rápido que npm install)

Linux/macOS:

# Ubuntu / Debian
sudo apt install lua5.4

# macOS
brew install lua

Windows:

Descargar LuaBinaries desde sitio web oficial o ponlo a través de scoop:

scoop install lua

Comprobamos:

lua -v
# Lua 5.4.x  Copyright (C) ...

Listo. Ni Docker, ni entorno virtual, ni package.json de 300 líneas. Simplemente funciona.

Paso 1: Hello World y los primeros conceptos básicos

Crea el archivo hello.lua:

print("Hello, World!")
print("Lua is easier than you thought")

Iniciar:

lua hello.lua

Eso es todo. Sin public static void main, sin import sys, sin use strict. Simplemente escribe y ejecuta.

Variables: sin tipos, sin problemas

local name = "Alexey"
local age = 25
local is_developer = true

print(name .. " — developer: " .. tostring(is_developer))

Ten en cuenta: .. es una concatenación de cadenas. No +, no son cadenas de plantilla. Dos puntos modestos. Lua es minimalista.

Condiciones: los clásicos de siempre

local level = 42

if level >= 100 then
    print("You're a legend!")
elseif level >= 50 then
    print("Almost there!")
else
    print("Keep swinging")
end

Nota: then y end en lugar de llaves. Al principio es inusual, pero después de una hora ya no lo notas.

Ciclos: tres tipos para todas las ocasiones

-- Цикл for (классический)
for i = 1, 5 do
    print("Iteration: " .. i)
end

-- Цикл while
local count = 0
while count < 3 do
    count = count + 1
    print("Counter: " .. count)
end

-- Перебор таблицы (о таблицах — ниже)
local fruits = {"apple", "banana", "mango"}
for index, fruit in ipairs(fruits) do
    print(index .. ". " .. fruit)
end

Paso 2: Las tablas son la única estructura de datos (y eso es suficiente)

En Lua no hay matrices, diccionarios, objetos, conjuntos, tuplas, decks... Hay tablas. Y lo reemplazan todo. Es como si un objeto JavaScript y una matriz se fusionaran en una sola entidad:

-- Как массив
local colors = {"Red", "Green", "Blue"}
print(colors[1])  -- "Red" (индексация с 1, да-да)

-- Как словарь
local player = {
    name = "Hero",
    hp = 100,
    level = 1
}
print(player.name)  -- "Hero"
print(player["hp"]) -- 100 (тоже работает)

-- Комбинированный вариант
local config = {
    title = "My Game",
    resolution = {1920, 1080},
    fullscreen = true
}

Indexación desde 1 — Sí, es un shock después de todos los idiomas con indexación cero. Pero te acostumbrarás. Probablemente. Algún día.

Paso 3: Funciones: ciudadanos de primera clase

-- Обычная функция
local function greet(name)
    return "Hi, " .. name .. "!"
end

print(greet("world"))

-- Функция как переменная (анонимная)
local square = function(x)
    return x * x
end

print(square(7))  -- 49

-- Множественный возврат (это Lua-суперсила!)
local function get_player_stats()
    return "Hero", 100, 15
end

local name, hp, attack = get_player_stats()
print(name .. " | HP: " .. hp .. " | ATK: " .. attack)

El retorno múltiple de valores es una de esas cosas en Lua que te hace suspirar: "¿Por qué no es así en todas partes?"

Paso 4: ¡Montamos un miniproyecto: una búsqueda de texto!

La teoría está bien, pero no estamos dando una conferencia aquí. Escribamos un verdadero miniproyecto: una misión RPG de texto. Tienes que explorar una mazmorra, luchar contra monstruos y (tal vez) sobrevivir.

Crea el archivo dungeon.lua:

-- === ТЕКСТОВЫЙ КВЕСТ: ПОДЗЕМЕЛЬЕ ===

math.randomseed(os.time())

-- Состояние игрока
local player = {
    name = "",
    hp = 100,
    attack = 15,
    potions = 3
}

-- Список монстров
local monsters = {
    {name = "Goblin", hp = 30, attack = 8, xp = 10},
    {name = "Skeleton", hp = 50, attack = 12, xp = 20},
    {name = "Dark Mage", hp = 40, attack = 18, xp = 25},
    {name = "Ogr", hp = 80, attack = 10, xp = 30},
}

-- Вспомогательные функции
local function separator()
    print(string.rep("-", 40))
end

local function show_status()
    separator()
    print("HP: " .. player.hp .. " | Potions: " .. player.potions)
    separator()
end

local function ask(question, options)
    print("\n" .. question)
    for i, opt in ipairs(options) do
        print("  " .. i .. ") " .. opt)
    end
    io.write("Your choice: ")
    local choice = tonumber(io.read())
    if not choice or choice < 1 or choice > #options then
        print("Incomprehensible choice, try again.")
        return ask(question, options)
    end
    return choice
end

-- Система боя
local function battle(monster)
    print("\n⚔️  Appears in front of you " .. monster.name .. "! (HP: " .. monster.hp .. ")")

    local enemy_hp = monster.hp

    while enemy_hp > 0 and player.hp > 0 do
        show_status()
        local action = ask("What are you doing?", {"Attack", "Drink the potion", "Try to escape"})

        if action == 1 then
            local damage = math.random(player.attack - 5, player.attack + 5)
            enemy_hp = enemy_hp - damage
            print("You inflict " .. damage .. " damage!")

            if enemy_hp > 0 then
                local enemy_damage = math.random(monster.attack - 3, monster.attack + 3)
                player.hp = player.hp - enemy_damage
                print(monster.name .. " beats you on " .. enemy_damage .. " damage!")
            end

        elseif action == 2 then
            if player.potions > 0 then
                local heal = math.random(20, 35)
                player.hp = player.hp + heal
                player.potions = player.potions - 1
                print("You are restoring " .. heal .. " HP!")
            else
                print("You don't have any potions! You lose a turn...")
            end
            local enemy_damage = math.random(monster.attack - 3, monster.attack + 3)
            player.hp = player.hp - enemy_damage
            print(monster.name .. " beats you on " .. enemy_damage .. " damage!")

        elseif action == 3 then
            if math.random(1, 100) <= 40 then
                print("You managed to escape!")
                return false
            else
                print("Couldn't escape!")
                local enemy_damage = math.random(monster.attack - 3, monster.attack + 5)
                player.hp = player.hp - enemy_damage
                print(monster.name .. " beats you on " .. enemy_damage .. " damage!")
            end
        end
    end

    if enemy_hp <= 0 then
        print("\n🎉 " .. monster.name .. " defeated!")
        if math.random(1, 100) <= 30 then
            player.potions = player.potions + 1
            print("You find a potion!")
        end
        return true
    end

    return false
end

-- Комнаты подземелья
local function explore_room(room_number)
    separator()
    print("\n🚪 Room " .. room_number)

    local events = {"monster", "monster", "treasure", "trap", "empty"}
    local event = events[math.random(1, #events)]

    if event == "monster" then
        local monster = monsters[math.random(1, #monsters)]
        return battle(monster)

    elseif event == "treasure" then
        print("You find a treasure chest!")
        local bonus = ask("What are you taking?", {"Health Potion (+1)", "Grinding stone (+3 to attack)"})
        if bonus == 1 then
            player.potions = player.potions + 1
            print("Potions: " .. player.potions)
        else
            player.attack = player.attack + 3
            print("Attack now: " .. player.attack)
        end
        return true

    elseif event == "trap" then
        print("Trap! Thorns shoot out of the wall!")
        local trap_damage = math.random(5, 15)
        player.hp = player.hp - trap_damage
        print("You get " .. trap_damage .. " damage.")
        return true

    else
        print("An empty room. Silence and dust.")
        if math.random(1, 100) <= 20 then
            print("You find a potion in the corner!")
            player.potions = player.potions + 1
        end
        return true
    end
end

-- === НАЧАЛО ИГРЫ ===

print("╔══════════════════════════════════════╗")
print("║     DUNGEON: TEXT QUEST     ║")
print("║         Written in Lua              ║")
print("╚══════════════════════════════════════╝")

io.write("What's your name, adventurer? ")
player.name = io.read()
print("\nWelcome, " .. player.name .. "!")
print("You are facing the entrance to a dungeon with 5 rooms.")
print("Go through them all and become a legend.\n")

local rooms_cleared = 0

for room = 1, 5 do
    if player.hp <= 0 then
        break
    end

    explore_room(room)

    if player.hp <= 0 then
        break
    end

    rooms_cleared = rooms_cleared + 1

    if room < 5 then
        show_status()
        local choice = ask("Going further?", {"Go ahead!", "Enough for today"})
        if choice == 2 then
            print("\nYou decide to return. Sometimes retreating is also wise.")
            break
        end
    end
end

separator()
separator()

if player.hp <= 0 then
    print("\n💀 " .. player.name .. " fell into the dungeon...")
    print("Rooms passed: " .. rooms_cleared .. " of 5")
    print("Try again — the dungeon is waiting!")
else
    if rooms_cleared == 5 then
        print("\n🏆 " .. player.name .. " completed the entire dungeon!")
        print("HP: " .. player.hp .. " | Remaining potions: " .. player.potions)
        print("You are a true legend!")
    else
        print("\n🏠 " .. player.name .. " returned from the dungeon.")
        print("Rooms passed: " .. rooms_cleared .. " of 5")
    end
end

print("\nThank you for playing! 🎮")

Iniciar:

lua dungeon.lua

Y ahora ya has escrito un proyecto completo en Lua. Con un sistema de combate, aleatoriedad, inventario y ramificación de la trama. No es una calculadora, sino un juego real.

¿Qué sigue? ¿Dónde crecer?

Lua es un excelente punto de entrada, y aquí es donde puedes moverte:

  • Love2D — marco para juegos 2D en Lua. Si te ha gustado la búsqueda de texto, imagina lo que pasará con los gráficos.

  • Complementos de Neovim — tu propio plugin para el editor, escrito en Lua, es un placer aparte.

  • OpenResty — integra scripts Lua directamente en nginx y procesa millones de solicitudes.

  • Roblox — en serio, en Roblox se gana dinero real, y toda la lógica está escrita en Lua.

¿Quieres seguir estudiando?
¡Entra en Kodik!

Si te gusta este formato, de la teoría a la práctica de una sola vez, seguro que te gustará Kodik. Esta aplicación para aprender programación, donde cada lección no es solo una pared de texto, sino tareas que resuelves con tus manos. Python, JavaScript, HTML, CSS y otras tecnologías, todo con práctica real, sin palabrería ni aburrimiento.

Y también tenemos Canal de Telegram, donde se publican regularmente publicaciones útiles: análisis de conceptos, hojas de trucos, minitareas y memes para desarrolladores. Es una forma excelente de repasar la programación en un formato cómodo: de camino al trabajo, durante la pausa del almuerzo o cuando te quedan «cinco minutitos más» antes de acostarte. Suscríbete y deja que la programación forme parte de tu día a día.

Lua es un lenguaje que demuestra que para ser poderoso no es necesario ser complejo. En una noche, pasaste de print("Hello") a una misión de RPG de texto con un sistema de combate. Y al mismo tiempo, no instalaste una sola dependencia, no escribiste una sola configuración y no rompiste un solo package-lock.json.

Ahora tienes un proyecto de trabajo, una comprensión de los conceptos básicos y una dirección para el crecimiento. Y esto ya es más que el 90% de las personas que «iban a empezar a aprender programación la próxima semana».

¡Atrévete! 🚀

🎯Deja de postergar

¿Te gustó el artículo?
¡Hora de practicar!

En Kodik no solo lees — escribes código de inmediato. Teoría + práctica = habilidades reales.

Práctica instantánea
🧠IA explica código
🏆Certificado

Sin registro • Sin tarjeta