Простой игровой цикл


Почти во всех играх присутствует базовый игровой цикл,
в котором объекты по очереди передвигаются по игровому полю,
одновременно или последовательно выполняя свои ходы.
Такой цикл достаточно легко сделать с помощью потока
и списка объектов у него на входе

co = coroutine.create(function (list)
    local step = 1
    while true do
        -- call next object to move
        obj = list[step]
        coroutine.yield(obj)
        step = step % #list + 1
    end
    return true
end)

function mklist()
    local x = 1
    return {
        function ()
            print('object 1 moving step '..x)
            x = x + 1
            return x<=3
        end,
        function ()
            print('object 2 moving forever')
            return true
        end
    }
end

function main()
    repeat
        status,obj = coroutine.resume(co,mklist())
        if obj()==false then
            break
        end
    until status==false
end

main()

В данном примере есть три очевидных, но решаемых недостатка:

1. Список объектов зафиксирован в mklist() - если вдруг требуется,
чтобы один объект "выбыл из игры" или "вылез за пределы экрана" -
его можно как-то помечать и не передавать ему следующий ход.

2. В процессе игры могут возникать новые объекты - тогда вместо
фиксированного списка в поток можно передавать замыкание - функцию,
возвращающую актуальный список действующих объектов.

3. В зависимости от числа действующих объектов имеет смысл корректировать
задержку между вызовами. Если, к примеру, движущихся объектов будет
много - задержка должна уменьшаться, а если мало - увеличиваться,
чтобы ход игры был равномерным.

#