Использование Lua и C++ в разработке видеоигр
Игры
Общая структура
Разделение обязанностей
sol2 (https://github.com/ThePhD/sol2)
Entity-component-system (ECS)
Взаимодействие Lua и C++
Проблемы
Другой подход
Оптимизация скриптов?
Машины состояний
Катсцены
Катсцены
Don’t Starve
Общие плюсы Lua в геймдеве
5.62M

Lua_in_moscow_gamedev

1. Использование Lua и C++ в разработке видеоигр

Дайлидёнок Илья
(Elias Daler)
Lua in Moscow 26 Feb’18

2. Игры

Re:creation
Tomb Painter
2

3. Общая структура

Машины
состояний
Игровые
компоненты
ECS
Ввод
Скриптинг уровней и
паззлы
Катсцены
Реализация машин
состояний
Рендеринг
Графика
Игровой цикл
Звук
Система
катсцен
Менеджер ресурсов
Файловая система,
таймеры и пр.
Lua
Игровая
логика
C++
Движок
3

4. Разделение обязанностей

C++
Lua
Проверка столкновений
(колизии)
Реакция на коллизию
Поиск кратчайшего пути
Принятие решений (AI)
Загрузка и отрисовка уровней
Триггеры на уровнях, условия
завершения уровня и пр.
4

5. sol2 (https://github.com/ThePhD/sol2)

• Регистрация функций
void someCppFunction() {
...
}
lua["someCppFunction"] = someCppFunction;
• Регистрация классов
lua.new_usertype<Widget>("Widget",
"setActive", Widget::setActive,
...);
• Расширение классов
lua.new_usertype<Widget>("Widget",
"extraFunc",
[](Widget& self, int param) {
...
},
...);
5

6. Entity-component-system (ECS)


• Transform
• Graphics
• Collision
C++ (low level)
Transform
Hierarchy
Graphics
Collision
Sound

Transform
Graphics
Collision
AI
Health
Inventory

Lua (специфика игры)
Inventory
Health
Damage
Npc

6

7. Взаимодействие Lua и C++

for (auto& [e1, e2] : getAllEntityPairs()) {
if (collide(e1, e2)) {
e1.luaCollisionCallback(e2);
e2.luaCollisionCallback(e1);
}
}
C++
Lua
function callback(self, other)
self:setAnimation("collision")
...
end
function callback2(self, other)
self:playSound(“boop”)
...
end
7

8. Проблемы

• Медленный C++ → Lua вызов
• Lua функции сложнее изменять без
изменения C++ кода
• Сдерживает писать больше на Lua
• Нужно писать много биндингов C++
функций и классов
8

9. Другой подход

C++
for (auto& [e1, e2] : getAllEntityPairs()) {
if (collided(e1, e2)) {
eventQueue.insert(Event("Collision", e1, e2));
eventQueue.insert(Event("Collision", e2, e1));
}
}
// …
handleEvents(eventQueue) // Lua call
Lua
function handleEvents(eventQueue)
for _, event in ipairs(eventQueue) do
handleEvent(event)
end
end
function onCollision(self, event)
self:setAnimation("collision")
...
end
9

10. Оптимизация скриптов?

• Большую часть времени занимает
рендеринг, проверка коллизии, поиск
кратчайшего пути для AI и пр.
• Lua и так очень быстрый язык! (А для тех,
кому недостаточно – есть LuaJIT)
• В крайнем случае часть кода из скриптов
можно выносить обратно в C++
10

11. Машины состояний

MoveState = {
update = function(entity, dt)
if entity:getVelocity():isZero() then
return "IdleState"
end
end
},
_AnyState = {
[EventType.Damaged] = {
exceptFor = { "DyingState", "DiedState" },
callback = function(entity, event)
local hc = entity.components.health
if hc:getHealth() > 0 then
return “HurtState"
else
return "DyingState"
end
end
}
}
11

12. Катсцены

delay(0.2)
local luna = getEntityByTag('LUNA')
local answer = luna:say('did_you_kill_it',
{'YES', 'NO' })
if answer == 'YES' then
luna:say('you_did_it')
else
luna:say('please_i_m_afraid')
end
12

13. Катсцены

function followPath(e, path)
local numberOfPoints = path:getNumberOfPoints()
local i = 0 -- индекс текущей точки
while true do
e:goTo(path:getPoint(i))
if i < numberOfPoints - 1 then
i = i + 1
else
i = 0
end
end
end
13

14. Don’t Starve

Kevin Forbes on Don't Starve [May 2013]
https://www.youtube.com/watch?v=_aJfFHjMKZw
14

15. Общие плюсы Lua в геймдеве

• Быстрая итерация
• Легче разделять движок и
игровую логику
• Моды
• Прототипирование
• Легче и быстрее пишется код
15

16.

Спасибо за
внимание!
16
English     Русский Rules