Перейти к содержимому

Курс

Курс разложен по тому, чем вы заняты: язык, логический процессор, мировой и приёмы поверх инструкций. Внутри — категории и группы из самой игры: группа — инструкция, урок — одна её грань. Группы независимы: за юнитами можно идти сразу в них, а что нужно знать заранее, написано в начале каждой.

просто
Читается с нуля: знать заранее ничего не нужно
средний
Нужны другие уроки — какие именно, написано в начале
сложно
Подводные камни: работающая на вид программа врёт молча. Читать, когда основное уже уложилось

Основы

То, что не про инструкцию, но без чего не читается ни одна из них

  1. Как писать в игреГде живёт программа, из чего собрана строка и что делают кнопки вокруг
  2. Программа — это текстСобирается блоками, а хранится строками — и этим стоит пользоваться
  3. Окно переменныхЕдинственное место, которое говорит правду о том, что программа насчитала
  4. Как работает процессорПрограмма идёт сверху вниз и начинается заново. Строки считаются с нуля, скорость мерится инструкциями за тик
  5. Число, объект и текстВ переменной либо число, либо объект — и от этого зависит, что с ней можно сделать
  6. Пустота: nullЗначения нет — и это тоже значение. Главный источник молчаливых ошибок в mlog
  7. Переменные и именаПеременную не объявляют — её просто называют. Разбираемся, какие имена свободны, а какие уже заняты
  8. Связи и getlinkСвязь — не соседство: блок надо подключить, и только тогда у него появится имя
  9. Когда не работаетОшибок mlog не выдаёт. Значит, искать придётся самому — и есть порядок, в котором это делают

Логический процессор

Ввод и вывод

Read

Одна инструкция и три разных собеседника: ячейка памяти, чужой процессор и обычная строка

  1. Ячейка памятиПамять процессора умирает вместе с правкой программы. Ячейка помнит — и достают из неё по номеру места
  2. Переменные другого процессораЯчейка для обмена нужна не всегда: переменную соседа можно взять прямо у него, назвав её по имени
  3. Символ из строкиСтрока тоже читается по адресу: номер символа вместо номера места, код символа вместо значения

Write

Переменные живут между итерациями, но не переживают правку программы. Память — переживает

  1. Запись в ячейкуОдна строка, три поля — и значение переживает и итерацию, и правку программы, и сам процессор
  2. Объект в ячейкеЯчейка перестала быть массивом чисел. В неё кладут предмет, склад или юнита — и достают их же
  3. Общая памятьПеременные соседа не видны никому. Ячейка видна всем, кто к ней подключён — на этом и строят разделение труда
  4. Переменные соседаЯчейка для обмена нужна не всегда — но за короткий путь платят тем, что переменная меняется без следа в программе

Draw

draw ничего не рисует. Он копит команды в буфере процессора, а показывает их дисплею другая инструкция

  1. Первый рисунокЧетыре строки — и на дисплее появляется прямоугольник. Без последней из них не появляется ничего
  2. Фигуры и линииФигур шесть, и каждая просит свои числа: где-то угол, где-то середина, где-то радиус
  3. Цвет и прозрачностьЦвет — это состояние, а не свойство фигуры: выбрали один раз, и он держится до следующего раза
  4. Текст и картинкиТекст на дисплей попадает из того же буфера, что и в блок сообщений, — но кириллицы в нём не будет
  5. Сдвиг, поворот, масштабПроще не пересчитывать каждую точку, а сдвинуть саму сетку — и рисовать в ней как в первый раз

Print

Текст в mlog не показывают, а накапливают: print пишет в буфер, а показывает его другая инструкция

  1. Текстовый буферСтрока собирается по кусочкам и лежит внутри процессора, пока её не отдадут наружу
  2. Что во что печатаетсяПечатать можно что угодно — и почти всё превращается в текст не так, как ждёшь

Print Char

Один символ за раз — зато любой: стрелка, рамка или иконка меди

    Format

    Шаблон целиком, а не текст кусочками: format вставляет значения в готовую надпись

      Управление блоками

      Draw Flush

      Буфер команд у процессора не резиновый: 256 за раз, а всё лишнее пропадает молча

        Print Flush

        Накопленный текст показывает не print, а printflush — и он же чистит буфер, что бы ни случилось

          У связей есть порядок, и по нему их можно обойти — не зная заранее, что подключено

            Control

            sensor спрашивает, control приказывает. Слушаются только те блоки, с которыми процессор связан

            1. Включить и выключитьЕдинственная команда, которая работает с любым блоком: выключить и включить обратно
            2. Настройка блокаСортировщик, разгрузчик и завод настраиваются предметом — и логика умеет менять эту настройку на ходу
            3. СтрельбаТурель и сама неплохо стреляет. Логика нужна там, где важно, по кому именно

            Radar

            Как блок узнаёт, что рядом кто-то есть: только юниты, только в своей дальности и только лучший из них

            1. Найти юнитаТри условия складываются логическим И, а дальность берётся у блока, из которого смотрят
            2. Сортировка и кешРадар отвечает не «кто есть», а «кто лучший». Причём отвечает не каждый раз заново

            Sensor

            Как процессор узнаёт, что творится вокруг: сколько меди в хранилище, где юнит, цел ли блок

            1. Свойства зданийЗапросить у связанного блока число — сколько внутри, сколько влезет, цел ли он
            2. Предметы и пустой ответСколько в блоке меди — и чем «предмета нет» отличается от «запрос неприменим»
            3. Свойства юнитовПосле ubind у @unit можно запросить то же самое — где он, цел ли, чем занят
            4. Свойство есть не у каждогоПочему @ammo есть только у турели, а @progress — у бура, и чем тип блока отличается от здания

            Операции

            Set

            Самая простая инструкция языка: взять значение и положить его в переменную

            1. Присваивание и копированиеПоложить число, текст или содержимое другой переменной — и чем копия отличается от оригинала
            2. Константы контентаПредмет, жидкость, блок и юнит — такие же значения, как число: их кладут в переменные и передают инструкциям

            Operation

            Всё, что процессор умеет считать: от сложения до синуса и шума

            1. АрифметикаСложить, вычесть, умножить, разделить — и что делать, когда действий два
            2. Целые и точностьКак получить целое число и остаток и чего ждать от дробей
            3. Сравнения и логикаСравнение — это тоже число, и с ним можно работать как с числом
            4. Битовые операцииЧисло как набор битов: маски, сдвиги и почему сдвиг на 64 ничего не меняет
            5. Углы и расстоянияРасстояние до точки, угол на неё и разница между углами — три операции, которые нужны всем
            6. Случайность и шумДве операции про непредсказуемость: одна каждый раз разная, вторая плавная

            Select

            Выбрать одно значение из двух по условию, не уводя выполнение в сторону

            1. Выбор значения без веткиВетка ради одного значения не нужна — но и select нужен не всегда: у сравнения ответ уже есть

            Lookup

            Весь контент игры пронумерован. Lookup превращает номер в объект — и открывает перебор по всему списку

              Pack Color

              Цвет из четырёх чисел неудобно носить с собой. packcolor складывает его в одно — и цвет становится обычным значением

                Unpack Color

                Обратная сторона packcolor: одно число снова становится четырьмя

                  Управление последовательностью

                  Wait

                  Программа крутится шестьдесят раз в секунду, даже когда не нужно. wait — способ этого не делать

                  1. Пауза в секундахПодождать столько-то секунд — и не потратить на ожидание ни одной инструкции
                  2. Ритм программыШестьдесят итераций в секунду нужны редко. Разбираемся, как выбрать ритм и чем его задать

                  Stop

                  Не пауза, а конец работы: после stop процессор не выполняет ничего

                    End

                    Начать итерацию заново — и, вопреки ожиданиям, не отдать при этом тик

                      Jump

                      Проверить условие и пойти не туда, куда пошёл бы обычно: ветвления и циклы

                      1. Условие и ветвлениеОдна проверка — две дороги. Разбираемся, как программа перестаёт быть прямой
                      2. ЦиклыТот же jump, только стрелка смотрит вверх — и программа начинает повторять кусок себя
                      3. Вложенные условия и ранний выходУ jump одно условие и одна цель. Всё остальное — «и», «или», else, выход из цикла — собирается из нескольких переходов

                      Set Rate

                      Процессор работает на своей скорости всегда. setrate — единственный способ её изменить, и меняют её почти всегда вниз

                        Управление единицами

                        Unit Bind

                        Процессор не управляет юнитами вообще. Он управляет одним — тем, который сейчас привязан

                        1. Привязка по типуОдин ubind — один юнит. Следующий даст другого, и так по кругу, пока не кончатся
                        2. Держать одного юнитаПривязываться каждую итерацию незачем. Правильный цикл привязывается редко — только когда прежний юнит больше не годится
                        3. Чужие юниты и командыУправлять чужим юнитом нельзя — ни по типу, ни по объекту. Смотреть на него можно сколько угодно

                        Unit Control

                        Всё, что юнит умеет делать по приказу, делает одна инструкция с разными первыми полями

                        1. Движение и остановкаКоординаты в тайлах, команда живёт десять секунд, а «стоять» не значит «замереть»
                        2. Прибытие: withinЮнит никогда не встанет ровно в точку. Спрашивать надо не «там ли он», а «близко ли»
                        3. Предметы: взять и отдатьЮнит — это переносная ячейка склада: один вид предмета, немного мест и обязательная задержка между рейсами
                        4. Флаг как меткаУ каждого юнита есть число, которое игра никак не использует. Без него два процессора растащат один отряд
                        5. ДобычаКопать умеют не все и не всё, и копают с места — дотянуться до клетки юнит должен сам
                        6. Кто управляет юнитомЮнит слушается того, кто скомандовал последним. Узнать, кто это сейчас, можно двумя свойствами

                        Unit Radar

                        Тот же радар, только смотрит не от здания, а от вашего юнита — и его дальностью

                          Unit Locate

                          Радар ищет юнитов, а ulocate — места: клетку с рудой, ближайшую турель врага, подбитое своё здание

                          1. Где лежит рудаКоординаты руды не выписывают руками: карта у каждого своя, а поиск — одна строка
                          2. Здания по меткеИскать здание по типу нельзя, зато можно по роли: ядро, турель, склад, генератор
                          3. Подбитые здания и проверка находкиЧетвёртый вид поиска ищет то, что надо чинить. А заодно разберёмся, почему ответ иногда застревает

                          Мировой процессор

                          Что такое мировой процессор

                          Тот же язык, те же блоки — но он умеет менять саму карту, и построить его в обычной игре нельзя

                            Query

                            Радар отдаёт одного. Query отдаёт всех, кто попал в круг или прямоугольник

                              Get Block

                              У клетки не одно содержимое, а четыре слоя. getblock спрашивает про любой из них

                                Set Block

                                Правка карты на ходу: блок появляется мгновенно, без стройки, ресурсов и очереди

                                  Spawn Unit

                                  Юнит появляется целым и сразу — без завода, ресурсов и очереди

                                    Spawn Bullet

                                    Выстрел без стрелка: пуля берётся у турели, а летит откуда скажут

                                      Apply Status

                                      Горит, мёрзнет, разогнан, обездвижен — всё это одна инструкция с двумя режимами

                                        Weather Sense

                                        Идёт ли сейчас дождь, снег или буря — двоичный ответ и ничего сверх того

                                          Weather Set

                                          Погода на карте — не случайность, а состояние, которым сценарий может управлять

                                            Spawn Wave

                                            Волна по расписанию — дело игры. Мировой процессор умеет позвать её раньше или высадить не там, где обычно

                                              Set Rule

                                              То, что обычно задаёт создатель карты в настройках, мировой процессор меняет прямо во время игры

                                                Flush Message

                                                Тот же буфер печати, но уходит он не в блок сообщений, а прямо на экран игрока

                                                  Cutscene

                                                  Единственная инструкция, которая говорит не с картой, а с экраном игрока

                                                    Effect

                                                    Три десятка готовых эффектов игры: взрыв, дым, искры, след. Красиво и совершенно безвредно

                                                      Explosion

                                                      Урон без источника: ни турели, ни пули — просто в точке карты что-то взорвалось

                                                        Fetch

                                                        Радар видит вокруг себя, query — в области. Fetch видит всё, что есть у команды на карте

                                                          Sync

                                                          В одиночной игре не делает ничего. На сервере — единственный способ показать всем одно и то же число

                                                            Client Data

                                                            Сообщение не на экран, а в программу клиента: канал, значение и выбор между «надёжно» и «быстро»

                                                              Get Flag

                                                              Обратная сторона setflag — и единственный способ узнать, что где-то на карте что-то случилось

                                                                Set Flag

                                                                Общая память всей карты: не число и не объект, а просто «да» под именем

                                                                  Set Prop

                                                                  Обратная сторона sensor: то, что он читает, setprop записывает — мимо всякой физики

                                                                    Play Sound

                                                                    Звук из точки карты или прямо в уши игроку — со всеми ручками, какие есть у движка

                                                                      Play Music

                                                                      Самая простая инструкция во всей части: имя мелодии и один признак

                                                                        Set Marker

                                                                        Одна инструкция на все свойства всех меток: что этот вид понимает, то и меняется

                                                                          Make Marker

                                                                          Рисунок поверх карты, который видит игрок: круг над точкой, подпись, стрелка, линия

                                                                            Locale Print

                                                                            Тот же print, только текст берётся не из программы, а из словаря карты — своего для каждого языка

                                                                              Продвинутое

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

                                                                              1. @counter: переход как значениеПереход — это не только jump. Номер следующей строки лежит в переменной, и его можно вычислить
                                                                              2. Число внутриЧисло в mlog одно на всё — дробное двойной точности. Отсюда и предел в 53 бита, и 0.1 + 0.2 ≠ 0.3
                                                                              3. Метки вместо номеров строкНомер строки в jump — не обязанность, а выбор. В текстовой записи цель можно назвать по имени
                                                                              4. Время: @time, @tick, @secondТик, секунда, минута и миллисекунда — одно и то же время в четырёх видах. Выбирать приходится по задаче
                                                                              5. Сколько стоит инструкцияУ процессора нет «дорогих» и «дешёвых» строк: он считает их штуками, и штук за тик ровно @ipt
                                                                              6. Упаковка данныхМест в памяти мало, а флаг у юнита один. Несколько чисел приходится складывать в одно
                                                                              7. Несколько процессоровОдин процессор — это одна очередь строк. Два идут параллельно — и это единственный способ ускориться, не меняя блок
                                                                              8. Пределы и редактор игрыТысяча инструкций, четыреста символов буфера, 256 команд рисования — пределы стоит знать до того, как упрёшься
                                                                              9. Тонкости языкаСобрание мест, где интуиция подводит: сравнения с допуском, пустота вместо бесконечности и объекты, которые равны только сами себе

                                                                              Неофициальный проект, с Anuke не связан. Спрайты, шрифты и переводы Mindustry © Anuke, используются по GPL-3.0; Fira Code — по OFL-1.1. Код сайта — GPL-3.0.