Сценарии персонажей
А теперь о том, для чего игры чаще всего используют сопрограммы: сценарии для персонажей. У каждого персонажа есть своя сопрограмма, которая описывает, что он делает, от начала до конца, ход за ходом. Игра идёт по ходам (на нашей ферме ход — это один день): на каждом ходу она возобновляет сопрограмму каждого персонажа ровно один раз, и каждый персонаж делает один шаг и передаёт управление.
У торговца Гуго маршрут из трёх остановок. У коровы Беллы каждые два дня одно и то же, поэтому её сценарий — бесконечный цикл:
-- Кто что делает на ферме Подсолнух
local function hugo()
print("Гуго на рынке.")
coroutine.yield()
print("Гуго приезжает на ферму Подсолнух.")
coroutine.yield()
print("Гуго уезжает в город.")
end
local function bella()
while true do
print("Белла пасётся на лугу.")
coroutine.yield()
print("Белла отдыхает в сарае.")
coroutine.yield()
end
end
local characters = {coroutine.create(hugo), coroutine.create(bella)}
for day = 1, 4 do
print("День " .. day)
for _, character in ipairs(characters) do
if coroutine.status(character) ~= "dead" then
coroutine.resume(character)
end
end
endОн выводит:
День 1
Гуго на рынке.
Белла пасётся на лугу.
День 2
Гуго приезжает на ферму Подсолнух.
Белла отдыхает в сарае.
День 3
Гуго уезжает в город.
Белла пасётся на лугу.
День 4
Белла отдыхает в сарае.Сопрограммы лежат в списке, поэтому игровому циклу всё равно, сколько в игре персонажей: он даёт ход каждому по очереди, в порядке списка. Персонажи ходят по очереди и никогда не работают одновременно. Каждый выполняется до своего yield, и только после этого ход переходит к следующему. На 4-й день сценарий Гуго уже закончился (dead), поэтому цикл его пропускает.
Зачем здесь сопрограммы? Без них Гуго понадобилась бы переменная, запоминающая его шаг, и каждый день пришлось бы писать if step == 1 then … elseif step == 2 then …, а у каждого персонажа были бы свои такие переменные. Сопрограмма помнит, где остановилась, и свои локальные переменные тоже, поэтому каждый сценарий читается сверху вниз, как рассказ: сначала это, потом пауза, потом то. Сценарий Беллы это показывает: цикл из двух шагов, и больше ничего.
Задание
- 1
Пёс Рекс каждый день приносит Эмме палку и считает их. Напишите для его сценария функцию
rex: локальная переменнаяsticks, которая начинается с0, и бесконечный цикл. В цикле Рекс прибавляет одну палку, выводитРекс приносит палку номер 1.(с текущим номером) и передаёт управление. Создайте сопрограмму изrexи возобновляйте её каждый день, сразу после Гуго. Программа выводит:День 1 Гуго продаёт семена на рынке. Рекс приносит палку номер 1. День 2 Гуго покупает яйца на ферме Подсолнух. Рекс приносит палку номер 2. День 3 Гуго уезжает в город. Рекс приносит палку номер 3. - 2
Сосед, дедушка Джо, заходит поболтать через день: во 2-й, 4-й, 6-й день и так далее. Напишите его сценарий,
grandpaJoe: в бесконечном цикле он сначала даёт дню пройти (простоcoroutine.yield()), потом выводитДедушка Джо заходит поболтать.и снова передаёт управление. Положите три сопрограммы в списокcharactersв порядке Гуго, Рекс, дедушка Джо и в цикле сipairsвозобновляйте каждую, которая неdead. Пусть игра длится четыре дня. Программа выводит:День 1 Гуго продаёт семена на рынке. Рекс приносит палку номер 1. День 2 Гуго покупает яйца на ферме Подсолнух. Рекс приносит палку номер 2. Дедушка Джо заходит поболтать. День 3 Гуго уезжает в город. Рекс приносит палку номер 3. День 4 Рекс приносит палку номер 4. Дедушка Джо заходит поболтать.