Знаешь это чувство, когда открываешь новый язык программирования и первые 20 минут думаешь: «Ну это же просто»? А потом начинается. Скобки не те, точки с запятой забыл, компилятор орёт на тебя как сосед сверху в 3 часа ночи.
С Lua всё по-другому. Серьёзно. Этот язык настолько лаконичный, что ты можешь выучить его основы за чашку кофе. А за вечер — собрать вполне рабочий мини-проект. Не веришь? Ну давай проверим.

Что вообще такое Lua и зачем оно мне?
Lua (читается «Лу-а», а не «Луа» — но, честно, все говорят как хотят) — это лёгкий скриптовый язык, который родился в Бразилии в 1993 году. Да, он старше большинства JavaScript-фреймворков. И, в отличие от них, до сих пор не deprecated.
Где используется Lua:
Игры — Roblox, World of Warcraft, Garry's Mod, Love2D. Если ты когда-нибудь писал аддон для WoW — ты уже Lua-разработчик, поздравляю.
Nginx и OpenResty — высоконагруженные веб-серверы крутят Lua-скрипты для обработки запросов.
Neovim — если ты из тех, кто настраивает свой редактор дольше, чем пишет код, Lua — твой новый лучший друг.
Встраиваемые системы и IoT — Lua настолько лёгкий, что работает даже там, где Python задыхается.
Короче, Lua — это как швейцарский нож, только без штопора. Компактный, полезный и удивительно мощный.
Шаг 0: Установка (быстрее, чем npm install)
Linux/macOS:
# Ubuntu / Debian
sudo apt install lua5.4
# macOS
brew install luaWindows:
Скачай LuaBinaries с официального сайта или поставь через scoop:
scoop install luaПроверяем:
lua -v
# Lua 5.4.x Copyright (C) ...Готово. Ни Docker, ни виртуальное окружение, ни package.json на 300 строк. Просто работает.
Шаг 1: Hello World и первые основы
Создай файл hello.lua:
print("Hello, World!")
print("Lua проще, чем ты думал")Запусти:
lua hello.luaВот и всё. Без public static void main, без import sys, без use strict. Просто пишешь и запускаешь.
Переменные — без типов, без проблем
local name = "Алексей"
local age = 25
local is_developer = true
print(name .. " — разработчик: " .. tostring(is_developer))Обрати внимание: .. — это конкатенация строк. Не +, не шаблонные строки. Два скромных точки. Lua минималист.
Условия — старая добрая классика
local level = 42
if level >= 100 then
print("Ты легенда!")
elseif level >= 50 then
print("Почти там!")
else
print("Продолжай качаться")
endЗаметь: then и end вместо фигурных скобок. Поначалу непривычно, но через час уже не замечаешь.
Циклы — три вида на все случаи
-- Цикл for (классический)
for i = 1, 5 do
print("Итерация: " .. i)
end
-- Цикл while
local count = 0
while count < 3 do
count = count + 1
print("Счётчик: " .. count)
end
-- Перебор таблицы (о таблицах — ниже)
local fruits = {"яблоко", "банан", "манго"}
for index, fruit in ipairs(fruits) do
print(index .. ". " .. fruit)
endШаг 2: Таблицы — единственная структура данных (и этого достаточно)
В Lua нет массивов, словарей, объектов, множеств, кортежей, деков... Есть таблицы. И они заменяют вообще всё. Это как если бы JavaScript-объект и массив слились в одну сущность:
-- Как массив
local colors = {"красный", "зелёный", "синий"}
print(colors[1]) -- "красный" (индексация с 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
}Индексация с 1 — да, это шок после всех языков с нулевой индексацией. Но ты привыкнешь. Наверное. Когда-нибудь.
Шаг 3: Функции — первоклассные граждане
-- Обычная функция
local function greet(name)
return "Привет, " .. name .. "!"
end
print(greet("мир"))
-- Функция как переменная (анонимная)
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)Множественный возврат значений — одна из тех штук в Lua, которая заставляет вздохнуть: «А почему так не везде?»
Шаг 4: Собираем мини-проект — текстовый квест!
Теория — это хорошо, но мы тут не лекцию читаем. Давай напишем настоящий мини-проект — текстовый RPG-квест. Тебе предстоит исследовать подземелье, сражаться с монстрами и (возможно) выжить.
Создай файл dungeon.lua:
-- === ТЕКСТОВЫЙ КВЕСТ: ПОДЗЕМЕЛЬЕ ===
math.randomseed(os.time())
-- Состояние игрока
local player = {
name = "",
hp = 100,
attack = 15,
potions = 3
}
-- Список монстров
local monsters = {
{name = "Гоблин", hp = 30, attack = 8, xp = 10},
{name = "Скелет", hp = 50, attack = 12, xp = 20},
{name = "Тёмный маг", hp = 40, attack = 18, xp = 25},
{name = "Огр", hp = 80, attack = 10, xp = 30},
}
-- Вспомогательные функции
local function separator()
print(string.rep("-", 40))
end
local function show_status()
separator()
print("HP: " .. player.hp .. " | Зелья: " .. 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("Твой выбор: ")
local choice = tonumber(io.read())
if not choice or choice < 1 or choice > #options then
print("Непонятный выбор, попробуй ещё раз.")
return ask(question, options)
end
return choice
end
-- Система боя
local function battle(monster)
print("\n⚔️ Перед тобой появляется " .. monster.name .. "! (HP: " .. monster.hp .. ")")
local enemy_hp = monster.hp
while enemy_hp > 0 and player.hp > 0 do
show_status()
local action = ask("Что делаешь?", {"Атаковать", "Выпить зелье", "Попробовать сбежать"})
if action == 1 then
local damage = math.random(player.attack - 5, player.attack + 5)
enemy_hp = enemy_hp - damage
print("Ты наносишь " .. 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 .. " бьёт тебя на " .. enemy_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("Ты восстанавливаешь " .. heal .. " HP!")
else
print("У тебя нет зелий! Ход потерян...")
end
local enemy_damage = math.random(monster.attack - 3, monster.attack + 3)
player.hp = player.hp - enemy_damage
print(monster.name .. " бьёт тебя на " .. enemy_damage .. " урона!")
elseif action == 3 then
if math.random(1, 100) <= 40 then
print("Тебе удалось сбежать!")
return false
else
print("Не удалось сбежать!")
local enemy_damage = math.random(monster.attack - 3, monster.attack + 5)
player.hp = player.hp - enemy_damage
print(monster.name .. " бьёт тебя на " .. enemy_damage .. " урона!")
end
end
end
if enemy_hp <= 0 then
print("\n🎉 " .. monster.name .. " повержен!")
if math.random(1, 100) <= 30 then
player.potions = player.potions + 1
print("Ты находишь зелье!")
end
return true
end
return false
end
-- Комнаты подземелья
local function explore_room(room_number)
separator()
print("\n🚪 Комната " .. 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("Ты находишь сундук с сокровищами!")
local bonus = ask("Что берёшь?", {"Зелье здоровья (+1)", "Точильный камень (+3 к атаке)"})
if bonus == 1 then
player.potions = player.potions + 1
print("Зелья: " .. player.potions)
else
player.attack = player.attack + 3
print("Атака теперь: " .. player.attack)
end
return true
elseif event == "trap" then
print("Ловушка! Шипы выстреливают из стены!")
local trap_damage = math.random(5, 15)
player.hp = player.hp - trap_damage
print("Ты получаешь " .. trap_damage .. " урона.")
return true
else
print("Пустая комната. Тишина и пыль.")
if math.random(1, 100) <= 20 then
print("Ты находишь зелье в углу!")
player.potions = player.potions + 1
end
return true
end
end
-- === НАЧАЛО ИГРЫ ===
print("╔══════════════════════════════════════╗")
print("║ ПОДЗЕМЕЛЬЕ: ТЕКСТОВЫЙ КВЕСТ ║")
print("║ Написано на Lua ║")
print("╚══════════════════════════════════════╝")
io.write("Как тебя зовут, искатель приключений? ")
player.name = io.read()
print("\nДобро пожаловать, " .. player.name .. "!")
print("Перед тобой вход в подземелье из 5 комнат.")
print("Пройди их все — и стань легендой.\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("Идёшь дальше?", {"Вперёд!", "Хватит на сегодня"})
if choice == 2 then
print("\nТы решаешь вернуться. Иногда отступить — тоже мудрость.")
break
end
end
end
separator()
separator()
if player.hp <= 0 then
print("\n💀 " .. player.name .. " пал в подземелье...")
print("Комнат пройдено: " .. rooms_cleared .. " из 5")
print("Попробуй ещё раз — подземелье ждёт!")
else
if rooms_cleared == 5 then
print("\n🏆 " .. player.name .. " прошёл всё подземелье!")
print("HP: " .. player.hp .. " | Оставшиеся зелья: " .. player.potions)
print("Ты — настоящая легенда!")
else
print("\n🏠 " .. player.name .. " вернулся из подземелья.")
print("Комнат пройдено: " .. rooms_cleared .. " из 5")
end
end
print("\nСпасибо за игру! 🎮")Запускай:
lua dungeon.luaИ вот ты уже написал полноценный проект на Lua. С боевой системой, рандомом, инвентарём и ветвлением сюжета. Не какой-нибудь калькулятор, а настоящая игра.
Что дальше? Куда расти
Lua — это отличная точка входа, и вот куда можно двигаться:
Love2D — фреймворк для 2D-игр на Lua. Если текстовый квест зашёл, представь, что будет с графикой.
Neovim-плагины — свой плагин для редактора, написанный на Lua, это отдельный вид удовольствия.
OpenResty — встраивай Lua-скрипты прямо в nginx и обрабатывай миллионы запросов.
Roblox — серьёзно, на Roblox зарабатывают реальные деньги, а вся логика пишется на Lua.
Хочешь учиться дальше?
Заходи в Кодик!
Если тебе зашёл такой формат — от теории к практике за один присест — тебе точно понравится Кодик. Это приложение для изучения программирования, где каждый урок — это не просто стена текста, а задачи, которые ты решаешь руками. Python, JavaScript, HTML, CSS и другие технологии — всё с реальной практикой, без воды и занудства.
А ещё у нас есть Telegram-канал, где регулярно выходят полезные посты: разборы концепций, шпаргалки, мини-задачи и мемы для разработчиков. Это отличный способ повторять программирование в удобном формате — по дороге на работу, в обеденный перерыв или когда «ещё пять минуточек» перед сном. Подписывайся, и пусть программирование будет частью каждого дня.
Lua — это язык, который доказывает: чтобы быть мощным, не обязательно быть сложным. За один вечер ты прошёл путь от print("Hello") до текстового RPG-квеста с боевой системой. И при этом не установил ни одной зависимости, не написал ни одного конфига и не сломал ни одного package-lock.json.
Теперь у тебя есть рабочий проект, понимание основ и направление для роста. А это уже больше, чем у 90% людей, которые «собирались начать учить программирование на следующей неделе».
Дерзай. 🚀
