Поздравления всем.
Этот пост будет о том, как написать очередную простую игрушку на языке программирования FBD (конечно, такая реализация языка программирования отклоняется от стандартов FBD, но большая часть «специальных возможностей» не используется, поэтому написанную программу можно легко переносится на классический FBD в любой системе), загружаете программу в контроллер и предаетесь воспоминаниям начала 2000-х.
Недавно один из моих коллег заговорил о начале 2000-х, и я почему-то вспомнил наши первые мобильные телефоны Siemens и игру Wappo. В итоге идея написать эту игрушку родилась сама собой с использованием средств проектирования программы Quint 7. Т.
к.
особых усилий и много времени это не потребовало, но вот результат:
На все это дело ушло два полуобеденных перерыва (вместе с распитием кофе) и пара часов вечером рисования картинок в MS Paint.
Постановка задачи
В игре «Ваппо» размер игрового поля составляет 6х6 клеток.В исходной позиции на поле находятся:
- Дом (или выход) — цель игры, чтобы ваш персонаж попал в эту клетку, не попадаясь врагу.
В нашем варианте эта клетка обозначена домом с лужайкой и голубым небом;
- Монстр — враг, стремящийся поймать игрока.
В нашем варианте это помидор;
- Игрок - персонаж игрока, которого нужно доставить в дом.
В нашей версии это сырный человек;
- Стены — это препятствия между клетками, которые не позволяют игроку и монстру проникнуть в соседнюю клетку.
Монстр перемещается на две клетки за ход в сторону персонажа игрока.
При этом приоритет отдается горизонтальному движению.
Если монстр не может двигаться (на его пути стоит стена), то он пропускает ход. Игра считается полной победой, если игроку удалось довести своего персонажа до клетки с домом, и поражением, если монстр своим ходом встал на ту же клетку, где стоит персонаж игрока.
Выполнение
Начнем, как обычно, с технологической программы для контроллера.Вся программа будет состоять из пяти больших блоков:
- Контроль;
- Обработка хода игрока;
- Обработка хода томата;
- Обработка ячеек поля;
- Условия обработки;
Контроль
Общий вид алгоритмов управления игрой:Здесь все просто.
Для управления используются два алгоритма «RuchSelector».
Первый алгоритм используется для запуска и остановки игры, а также для подачи команд на движение человечка.
Селектор работает по принципу «один из n».
Длительность выходного сигнала составляет 1 мс (т.е.
один цикл контроллера).
Первый выход (кнопка «пуск») взводит триггер «Игра идет».
Пока курок взведен, выполняются все остальные команды.
В то же время этот же выход отправляет команду блокам управления перемещением для установки начальной позиции уровня.
Второй вывод сбрасывает все триггеры в игре (включая основной триггер «Игра в процессе») и очищает все элементы памяти.
Для выбора уровня используется второй алгоритм «RuchSelector».
Как видно на картинке, на данный момент реализовано три уровня.
Соответственно, если количество уровней увеличится, то одновременно необходимо будет увеличить модификатор алгоритма.
На выходе второго селектора имеется простая схема, которая проверяет выбранное значение и, если игрок начинает игру без выбора уровня (выходное значение равно нулю), принудительно присваивает первый уровень.
Еще два алгоритма «видимость» и «блокировка» используются для отображения/скрытия некоторых графических элементов, а также для установки блокировки на команды игрока.
Зачем нужна эта блокировка, будет объяснено ниже.
Обработка полевых ячеек
Общий вид макроса «ячейка»Содержание макроса и краткое описание
Макрос имеет 5 входов и 7 выходов:
Входы:
- Стены — это пять логических признаков того, что у ячейки есть стены сверху/справа/снизу/слева, а также признак того, что в этой ячейке есть «дом».
Эти знаки статичны и устанавливаются один раз в начале уровня;
- Позиция — ненужный ввод. Я оставил это только для ясности.
Идея в том, что каждая ячейка должна проверять возможность перехода к соседним ячейкам и выдавать соответствующие блокировки (ban_up/ban_right/ban_down/ban_left).
Но движение блокируется не только тогда, когда между соседними клетками стоит стена, но и когда клетка находится на краю поля.
Например, из клетки с координатами (1;1) движение вверх и влево запрещено (так как там уже нет игрового поля).
В текущей версии для проверки этого условия в макросе используются 4 алгоритма сравнения, которые сравнивают координату ячейки в строке и столбце с 1 и 6 и формируют соответствующие запреты.
Однако внимательные читатели сразу скажут, что алгоритм можно упростить, убрав эти сравнения и назначив крайним от края поля ячейкам «виртуальные стены».
Однако перед нами не стоит задача создания идеального алгоритма, поэтому было решено оставить некоторую избыточность в задаче, получив при этом большую наглядность примера;
- Ход игрока является логическим признаком того, что ход игрока происходит в данный момент. По этому критерию блоки проверяются отдельно для игрока и помидора;
- Сыр — логический знак того, что персонаж игрока находится в этой ячейке;
- Помидор – это логический признак того, что в данной клетке находится злой помидор.
Выходы:
- Prohibition_U/R/B/L – запрет движения в соответствующем направлении;
- Выходной сигнал является основным параметром ячейки.
Используется для отображения состояния ячейки в графической части.
0 — ячейка пуста, 1 — персонаж игрока находится в ячейке, 2 — в ячейке помидор, 3 — в ячейке находится дом.
Этот результат генерируется последовательно тремя алгоритмами выбора (алгоритмы 5, 6 и 7);
- Escaped — логический признак того, что персонаж игрока приземлился на квадрате с домом и уровень пройден;
- GameOver — логический признак того, что помидор догнал персонажа игрока и игра проиграна;
Условия обработки
Сама обработка условий примитивна.Как мы выяснили чуть выше, каждая ячейка формирует знаки запрета движения в определенном направлении, а также знаки победы и поражения в игре.
Затем все эти признаки просто собираются с помощью логического «ИЛИ» для использования в алгоритме обработки хода.
Условия обработки
Несколько слов об остальных алгоритмах (с алгоритмами «ИЛИ» вопросов быть не должно).
Итак, помимо нескольких алгоритмов «или», в обработке используются несколько триггеров и алгоритм «Задержка».
Основным триггером здесь является «Очередь игрока».
Этот триггер активирован в начале игры.
После того как игрок сделает успешный ход, этот триггер сбрасывается и начинается обработка хода Помидора.
Для того, чтобы действия помидора были более-менее понятны, был использован алгоритм трех последовательных задержек по 200 мс каждая.
Как только игрок делает успешный ход, триггер «Ход игрока» сбрасывается и одновременно подается импульс на обратный фронт с задержкой 200 мс.
После отсчета времени Помидор делает первый из двух шагов и снова запускает следующий таймаут на 200 мс.
Затем Помидор делает второй шаг и снова запускает таймаут на 200 мс.
После третьей временной задержки взводится курок «Очередь игрока» и управление передается игроку.
Все вышеперечисленное было сделано лишь для того, чтобы ходы противника не были мгновенными, а последовательно отображались на экране.
Это гораздо приятнее и удобнее, чем видеть мгновенную смену положения.
Во время всех этих задержек устанавливается флаг блокировки, чтобы игрок мог видеть, о чем «думает» компьютер, и не нажимал лишний раз кнопки управления.
По логике все нормально и никакие дополнительные команды не сработают, но это обычно вызывает у человека недоумение: «Как такое возможно? Я нажимаю, а он не реагирует!» От таких ситуаций лучше избавиться.
Обработка хода игрока
Сам блок обработки хода игрока очень прост:Две одинаковые нити для обработки вертикального и горизонтального движения.
Давайте подробнее рассмотрим первый:
- Алгоритмы «И» 69 и 70 проверяют совокупность условий движения вверх и вниз соответственно.
Если взведен первый триггер «Идет игра», взведен второй триггер «Очередь игрока», с третьего поступила команда на ход вверх или с пятого на ход вниз с выхода Селектора управления и блокировки движения нет. в этом направлении, то
- На алгоритмах «Выбор» 71 и 72 в зависимости от сработавшего условия в текущую координату передается либо «+1», либо «-1»;
- Алгоритм «Выбор» 73 проверяет, что мы получили сигнал на начало игры и необходимо установить стартовую позицию.
В противном случае передается ранее сгенерированная команда;
- В алгоритме «Сложение» новое значение добавляется к значению, хранящемуся в контуре обратной связи, и получается новая координата;
- Алгоритм 75 «выбора» проверяет, что поступил сигнал сброса (второй выход селектора управления) и если он поступает, то значение, хранящееся на обратной связи, сбрасывается в ноль;
- С выхода алгоритма «Сложение» новая координата персонажа игрока поступает в блок «Распределение», через который попадает в соответствующую ячейку;
- Алгоритм ИЛИ 85 нужен, чтобы определить, что мы сделали успешный ход. Те.
если все четыре условия на одном из четырех «Есть» выполнены, то игрок сделал успешный (успешный не в смысле «хороший», а в смысле «разрешенный правилами») ход, и настало время для нам нужно сбросить триггер «Ход игрока» и передать ход помидору.
Просто и понятно.
Обработка прогресса помидоров
Здесь даже проще, чем с ходом игрока:- Алгоритм «ИЛИ» 89 (который, кстати, здесь не нужен и оставлен только для наглядности) при сбросе триггера «Ход игрока» получает импульс, задержанный на 200 мс от обратного фронта (запомните эту штуку в блок обработки условий?).
Далее сравниваются текущая координата помидора и текущая координата персонажа игрока.
На основе сравнения формируется команда «+1» или «-1» для перемещения по горизонтали и вертикали.
Далее проверяются условия горизонтального хода (алгоритмы «И» 93 и 94, здесь проверка аналогична обработке хода игрока, с той лишь разницей, что триггер «Ход игрока» должен быть сброшен) и передается команда через аналогичную цепочку выборов алгоритму «Сложение» 101;
- Если условия возможности горизонтального перемещения не выполняются, то этот обратный знак подается в алгоритмы «И» 106 и 107, где проверяются остальные условия возможности вертикального перемещения;
- После совершения хода таймер начинает отсчет еще в течение 200 мс (алгоритм задержки 90), после чего снова проверяется вся логика для второго шага помидора и запускается третий таймер (алгоритм задержки 91) на 200 мс;
- Когда срабатывает третий таймер, активируется триггер «Очередь игрока»;
- Еще одно отличие от схемы обработки хода игрока состоит в том, что здесь используются алгоритмы «Сложение» 98 и 111 для определения направления движения помидора (вверх-вниз или влево-вправо).
Т.
к.
одновременно оба условия в сравнении не могут быть выполнены, то мы можем просто складывать наши команды (одно из слагаемых всегда будет равно нулю), получая на выходе нужное направление движения.
Несколько слов о том, что осталось за кадром
И там осталось немного, всего несколько алгоритмов.
— Алгоритм «Исходная позиция»: Тип алгоритма
В нем указаны координаты стен, дома и начальное положение персонажа игрока и помидоров.
На данный момент таких позиций три (всего три уровня), но просто добавив модификатор в алгоритм и введя новые координаты, можно увеличить количество уровней до трёхсот без каких-либо модификаций основной программы.
— блок раздачи текущих координат персонажа игрока и помидоров: Распределение текущих координат
Здесь тоже все просто.
Соответствующий вектор передается текущему номеру строки, затем разлагается на биты и полученные логические сигналы поступают в свои алгоритмы «Ячейки».
Общий вид технической программы
После того, как все блоки у нас готовы, остается только их расположить (то есть красиво расположить в поле) и программа готова: Итоговая программа.Прикручиваем графическую часть
Эта графическая часть заняла большую часть времени.Пришлось искать картинки в Интернете и рисовать их под свой размер.
Некоторые картинки не сразу удалось найти и оказалось, что их проще и быстрее нарисовать самостоятельно в Paint. Но так или иначе набор картинок был закончен и началась собственно отрисовка игрового процесса, которая заняла минут пять.
Делаем один элемент (клетку).
Добавляем в него анимацию содержимого и стен.
Копируем 35 раз и получаем готовое поле.
Рисуем вокруг него кирпичную стену, добавляем пару надписей и кнопок для управления и готово.
Оригинальный рисунок (игра еще не запущена):
Это похоже на мешанину элементов, в которой ничего не понятно.
Но нужно учитывать то, что при работе программы некоторые элементы будут скрыты в зависимости от условий, и в целом картинка будет простой и понятной.
Запущено:
Здесь вы можете видеть, что после запуска режима просмотра данных с контроллера некоторые элементы стали невидимыми, тем самым устранив тот бардак, который мы получили в режиме рисования.
Мы играем:
Мы теряем:
И мы выигрываем:
Нереализованный
В этом примере мы создали классическую игру, но быстрый поиск на YouTube показал, что в игре есть нечто большее.Сделать это на основе приведенной выше программы несложно, но я этого не делал, чтобы не загромождать базу.
Попробуем навскидку прикинуть, что и как можно реализовать дополнительных возможностей:
- Варианты игры (или уровни) с двумя монстрами.
Без проблем.
В макрос «Ячейка» добавлен еще один логический признак, что в ячейке находится «помидор 2».
К исходной позиции добавляются еще две координаты стартовой позиции «Помидора 2».
Блок обработки перемещения Pomodoro копируется и связывается с этими выходами.
Блок распределения координат также копируется и привязывается к добавленному входу в макросе «Ячейка».
Все.
Примерное время выполнения – десять минут (чтобы все аккуратно разложить).
Вопрос только в том, что делать, если во время игры оба помидора занимают одну и ту же клетку.
И смогут ли они вообще это сделать? Но это вопрос правил игры.
- Варианты игры (или уровни) с ловушками.
Без проблем.
После успешного хода игрока триггер «Ход игрока» сбрасывается, и этот сброс начинает обработку хода Помидора.
Все, что вам нужно сделать, это добавить в макрос «Ячейка» признак того, что в этой ячейке есть ловушка.
При его попадании взводится курок запрета хода и запускается счетчик импульсов для обработки хода помидора.
Пока спусковой крючок взведен, этот сигнал не передается в блок обработки хода (достаточно сложить его вместе с «и» с инвертированным выходом спускового крючка).
Триггер запрета хода сбрасывается, когда счетчик пропущенных ходов достигает заданного количества ходов.
Примерное время выполнения – около десяти минут.
- Телепортационная ячейка.
В некоторых версиях (или уровнях) игры есть два отмеченных квадрата, при ударе по которым персонаж игрока телепортируется на второй квадрат. Опять же, эта функция реализована без проблем.
Нам нужен один логический признак на входе макроса «Ячейка», что в этой ячейке находится «телепорт».
В блок обработки хода игрока добавлен еще один алгоритм «Выбора», который при попадании в эту ячейку телепорта принудительно подставляет координаты связанной с ним ячейки в качестве входных данных алгоритма «Сложение».
Время выполнения – десять минут.
- Количество уровней.
Новые уровни добавляются легко.
Модификатор алгоритма «Селектор» увеличивается и соответственно увеличивается модификатор алгоритма «Начальная_позиция».
Далее вводятся исходные координаты стен, дома, помидора и игрока и все готово.
Время реализации зависит от количества уровней, которые необходимо добавить.
Мне потребовалось всего несколько минут, чтобы добавить два уровня.
Краткое содержание
Программа готова и отлично работает. Основа программы позволяет ее расширять без серьезных изменений.При этом на само «программирование» уходит очень мало времени.
При этом программирование на языке FBD (стандарт языка графического программирования МЭК 61131-3) просто, понятно и не требует глубоких знаний.
Все, что вам нужно, — это освоить элементарную логику и математику на школьном уровне и знать, как работают простые алгоритмы, такие как триггеры и счетчики.
Вот и все.
Надеюсь, это было интересно.
Теги: #ПТК #Квинт 7 #Игрушки своими руками #Ненормальное программирование #Программирование микроконтроллера
-
Лучшая Компания По Дизайну Веб-Сайтов, Индия
19 Oct, 24 -
Экспонометр
19 Oct, 24 -
Как Ux-Писатель Помогает Улучшить Продукт
19 Oct, 24 -
На Pirate Bay Уже Миллион Торрентов
19 Oct, 24