LOGOFALPROG Telegram 177
Идём со стороны стейт-машин

Прошлый раздел был нужен лишь для полноты картины и для того, чтобы сказать, что всё вообще не так. В этом разделе мы придём туда же, но другим путём.

Итак, забудьте пока про ужасный и суетливый мир мультипотока. Переместимся на время в спокойное безопасное место. Вы в своём однопоточном приложении. Больше нет никаких состояний гонок, всё выполняется последовательно и предсказуемо.

Вы пишите игру про ваше тотемное животное. Пусть это будет сурикат. Целая колония сурикатов. Все они бегают по Калахари в поисках еды и боевых приключений. Если каждая особь будет обладать маломальскими самостоятельными мозгами (а сурикаты они такие), то классическая имплементация — это, конечно же, стейт-машины. Ну или конечные автоматы, если вам так угодно. То есть вы пишите много-много классов (по одному на каждое возможное состояние машины), и в каждом классе реализуете функцию update(), которая выполняется каждый игровой тик, и возможно приводит к переходу в другие состояния.

Красота? Благодать? В принципе, да. Но не очень. Этот подход, конечно, понравится вашему тимлиду, потому что так ещё деды писали, но всё-таки писать столько служебного кода довольно утомительно. Ведь ежедневная рутина сурикатов так соблазнительно хорошо описывается в терминах одной обычной функции с ветвлениями:

проснуться();
расчистить_вход_в_норку_от_песка();
пока ещё_не_перегрелись_на_солнце {
выбрать_точку_куда_идти();
пока не_дошли {
сделать_шаг_по_маршруту()
если встретили_пищу, то
есть();
если встретили_врага, то
сражаться();
}
}
идти_в_тенёк().

Согласитесь, намного читабельнее и удобнее, чем писать штук 10 классов под это дело. Единственная проблемка в том, что каждая операция здесь потенциально может выполняться больше одного игрового тика (то есть длиться дольше одного кадра; например, из-за анимации), а потому простой функцией здесь не обойтись. Как вы уже догадались, нам просто нужна возможность писать функции с несколькими точками входа. Или, проще говоря, возможность нашпиговать этот код yield()-ами через строчку:

проснуться();
yield расчистить_вход_в_норку_от_песка();
пока ещё_не_перегрелись_на_солнце {
выбрать_точку_куда_идти();
пока не_дошли {
yield сделать_шаг_по_маршруту()
если встретили_пищу, то
yield есть();
если встретили_врага, то
yield сражаться();
}
}
yield идти_в_тенёк().

Такие фаршированные функции называют генераторами. Они могут быть знакомы многим по C#. И по большому счёту это и есть машина состояний, только записанная более удобным синтаксисом; поскольку внутренне это всё разбивается всё равно на несколько маленьких функций от одного yield до другого, а общие переменные выносятся в небольшую структуру, которая передаётся дальше (на манер того, как это происходит с замыканиями). Каждая такая сгенерированная структурка и соответствующая ей функция по сути и образуют наши олдскульные классы состояний конечного автомата.



tgoop.com/logofalprog/177
Create:
Last Update:

Идём со стороны стейт-машин

Прошлый раздел был нужен лишь для полноты картины и для того, чтобы сказать, что всё вообще не так. В этом разделе мы придём туда же, но другим путём.

Итак, забудьте пока про ужасный и суетливый мир мультипотока. Переместимся на время в спокойное безопасное место. Вы в своём однопоточном приложении. Больше нет никаких состояний гонок, всё выполняется последовательно и предсказуемо.

Вы пишите игру про ваше тотемное животное. Пусть это будет сурикат. Целая колония сурикатов. Все они бегают по Калахари в поисках еды и боевых приключений. Если каждая особь будет обладать маломальскими самостоятельными мозгами (а сурикаты они такие), то классическая имплементация — это, конечно же, стейт-машины. Ну или конечные автоматы, если вам так угодно. То есть вы пишите много-много классов (по одному на каждое возможное состояние машины), и в каждом классе реализуете функцию update(), которая выполняется каждый игровой тик, и возможно приводит к переходу в другие состояния.

Красота? Благодать? В принципе, да. Но не очень. Этот подход, конечно, понравится вашему тимлиду, потому что так ещё деды писали, но всё-таки писать столько служебного кода довольно утомительно. Ведь ежедневная рутина сурикатов так соблазнительно хорошо описывается в терминах одной обычной функции с ветвлениями:

проснуться();
расчистить_вход_в_норку_от_песка();
пока ещё_не_перегрелись_на_солнце {
выбрать_точку_куда_идти();
пока не_дошли {
сделать_шаг_по_маршруту()
если встретили_пищу, то
есть();
если встретили_врага, то
сражаться();
}
}
идти_в_тенёк().

Согласитесь, намного читабельнее и удобнее, чем писать штук 10 классов под это дело. Единственная проблемка в том, что каждая операция здесь потенциально может выполняться больше одного игрового тика (то есть длиться дольше одного кадра; например, из-за анимации), а потому простой функцией здесь не обойтись. Как вы уже догадались, нам просто нужна возможность писать функции с несколькими точками входа. Или, проще говоря, возможность нашпиговать этот код yield()-ами через строчку:

проснуться();
yield расчистить_вход_в_норку_от_песка();
пока ещё_не_перегрелись_на_солнце {
выбрать_точку_куда_идти();
пока не_дошли {
yield сделать_шаг_по_маршруту()
если встретили_пищу, то
yield есть();
если встретили_врага, то
yield сражаться();
}
}
yield идти_в_тенёк().

Такие фаршированные функции называют генераторами. Они могут быть знакомы многим по C#. И по большому счёту это и есть машина состояний, только записанная более удобным синтаксисом; поскольку внутренне это всё разбивается всё равно на несколько маленьких функций от одного yield до другого, а общие переменные выносятся в небольшую структуру, которая передаётся дальше (на манер того, как это происходит с замыканиями). Каждая такая сгенерированная структурка и соответствующая ей функция по сути и образуют наши олдскульные классы состояний конечного автомата.

BY Log of Alprog


Share with your friend now:
tgoop.com/logofalprog/177

View MORE
Open in Telegram


Telegram News

Date: |

Telegram iOS app: In the “Chats” tab, click the new message icon in the right upper corner. Select “New Channel.” Select: Settings – Manage Channel – Administrators – Add administrator. From your list of subscribers, select the correct user. A new window will appear on the screen. Check the rights you’re willing to give to your administrator. 2How to set up a Telegram channel? (A step-by-step tutorial) How to create a business channel on Telegram? (Tutorial) Healing through screaming therapy
from us


Telegram Log of Alprog
FROM American