Курс
Курс разложен по тому, чем вы заняты: язык, логический процессор, мировой и приёмы поверх инструкций. Внутри — категории и группы из самой игры: группа — инструкция, урок — одна её грань. Группы независимы: за юнитами можно идти сразу в них, а что нужно знать заранее, написано в начале каждой.
Основы
То, что не про инструкцию, но без чего не читается ни одна из них
- Как писать в игреГде живёт программа, из чего собрана строка и что делают кнопки вокруг
- Программа — это текстСобирается блоками, а хранится строками — и этим стоит пользоваться
- Окно переменныхЕдинственное место, которое говорит правду о том, что программа насчитала
- Как работает процессорПрограмма идёт сверху вниз и начинается заново. Строки считаются с нуля, скорость мерится инструкциями за тик
- Число, объект и текстВ переменной либо число, либо объект — и от этого зависит, что с ней можно сделать
- Пустота: nullЗначения нет — и это тоже значение. Главный источник молчаливых ошибок в mlog
- Переменные и именаПеременную не объявляют — её просто называют. Разбираемся, какие имена свободны, а какие уже заняты
- Связи и getlinkСвязь — не соседство: блок надо подключить, и только тогда у него появится имя
- Когда не работаетОшибок mlog не выдаёт. Значит, искать придётся самому — и есть порядок, в котором это делают
Логический процессор
Ввод и вывод
Read
Одна инструкция и три разных собеседника: ячейка памяти, чужой процессор и обычная строка
- Ячейка памятиПамять процессора умирает вместе с правкой программы. Ячейка помнит — и достают из неё по номеру места
- Переменные другого процессораЯчейка для обмена нужна не всегда: переменную соседа можно взять прямо у него, назвав её по имени
- Символ из строкиСтрока тоже читается по адресу: номер символа вместо номера места, код символа вместо значения
Write
Переменные живут между итерациями, но не переживают правку программы. Память — переживает
- Запись в ячейкуОдна строка, три поля — и значение переживает и итерацию, и правку программы, и сам процессор
- Объект в ячейкеЯчейка перестала быть массивом чисел. В неё кладут предмет, склад или юнита — и достают их же
- Общая памятьПеременные соседа не видны никому. Ячейка видна всем, кто к ней подключён — на этом и строят разделение труда
- Переменные соседаЯчейка для обмена нужна не всегда — но за короткий путь платят тем, что переменная меняется без следа в программе
Draw
draw ничего не рисует. Он копит команды в буфере процессора, а показывает их дисплею другая инструкция
- Первый рисунокЧетыре строки — и на дисплее появляется прямоугольник. Без последней из них не появляется ничего
- Фигуры и линииФигур шесть, и каждая просит свои числа: где-то угол, где-то середина, где-то радиус
- Цвет и прозрачностьЦвет — это состояние, а не свойство фигуры: выбрали один раз, и он держится до следующего раза
- Текст и картинкиТекст на дисплей попадает из того же буфера, что и в блок сообщений, — но кириллицы в нём не будет
- Сдвиг, поворот, масштабПроще не пересчитывать каждую точку, а сдвинуть саму сетку — и рисовать в ней как в первый раз
Текст в mlog не показывают, а накапливают: print пишет в буфер, а показывает его другая инструкция
- Текстовый буферСтрока собирается по кусочкам и лежит внутри процессора, пока её не отдадут наружу
- Что во что печатаетсяПечатать можно что угодно — и почти всё превращается в текст не так, как ждёшь
Print Char
Один символ за раз — зато любой: стрелка, рамка или иконка меди
Format
Шаблон целиком, а не текст кусочками: format вставляет значения в готовую надпись
Управление блоками
Draw Flush
Буфер команд у процессора не резиновый: 256 за раз, а всё лишнее пропадает молча
Print Flush
Накопленный текст показывает не print, а printflush — и он же чистит буфер, что бы ни случилось
Get Link
У связей есть порядок, и по нему их можно обойти — не зная заранее, что подключено
Control
sensor спрашивает, control приказывает. Слушаются только те блоки, с которыми процессор связан
- Включить и выключитьЕдинственная команда, которая работает с любым блоком: выключить и включить обратно
- Настройка блокаСортировщик, разгрузчик и завод настраиваются предметом — и логика умеет менять эту настройку на ходу
- СтрельбаТурель и сама неплохо стреляет. Логика нужна там, где важно, по кому именно
Radar
Как блок узнаёт, что рядом кто-то есть: только юниты, только в своей дальности и только лучший из них
- Найти юнитаТри условия складываются логическим И, а дальность берётся у блока, из которого смотрят
- Сортировка и кешРадар отвечает не «кто есть», а «кто лучший». Причём отвечает не каждый раз заново
Sensor
Как процессор узнаёт, что творится вокруг: сколько меди в хранилище, где юнит, цел ли блок
- Свойства зданийЗапросить у связанного блока число — сколько внутри, сколько влезет, цел ли он
- Предметы и пустой ответСколько в блоке меди — и чем «предмета нет» отличается от «запрос неприменим»
- Свойства юнитовПосле ubind у @unit можно запросить то же самое — где он, цел ли, чем занят
- Свойство есть не у каждогоПочему @ammo есть только у турели, а @progress — у бура, и чем тип блока отличается от здания
Операции
Set
Самая простая инструкция языка: взять значение и положить его в переменную
- Присваивание и копированиеПоложить число, текст или содержимое другой переменной — и чем копия отличается от оригинала
- Константы контентаПредмет, жидкость, блок и юнит — такие же значения, как число: их кладут в переменные и передают инструкциям
Operation
Всё, что процессор умеет считать: от сложения до синуса и шума
- АрифметикаСложить, вычесть, умножить, разделить — и что делать, когда действий два
- Целые и точностьКак получить целое число и остаток и чего ждать от дробей
- Сравнения и логикаСравнение — это тоже число, и с ним можно работать как с числом
- Битовые операцииЧисло как набор битов: маски, сдвиги и почему сдвиг на 64 ничего не меняет
- Углы и расстоянияРасстояние до точки, угол на неё и разница между углами — три операции, которые нужны всем
- Случайность и шумДве операции про непредсказуемость: одна каждый раз разная, вторая плавная
Select
Выбрать одно значение из двух по условию, не уводя выполнение в сторону
- Выбор значения без веткиВетка ради одного значения не нужна — но и select нужен не всегда: у сравнения ответ уже есть
Lookup
Весь контент игры пронумерован. Lookup превращает номер в объект — и открывает перебор по всему списку
Pack Color
Цвет из четырёх чисел неудобно носить с собой. packcolor складывает его в одно — и цвет становится обычным значением
Unpack Color
Обратная сторона packcolor: одно число снова становится четырьмя
Управление последовательностью
Wait
Программа крутится шестьдесят раз в секунду, даже когда не нужно. wait — способ этого не делать
- Пауза в секундахПодождать столько-то секунд — и не потратить на ожидание ни одной инструкции
- Ритм программыШестьдесят итераций в секунду нужны редко. Разбираемся, как выбрать ритм и чем его задать
Stop
Не пауза, а конец работы: после stop процессор не выполняет ничего
End
Начать итерацию заново — и, вопреки ожиданиям, не отдать при этом тик
Jump
Проверить условие и пойти не туда, куда пошёл бы обычно: ветвления и циклы
- Условие и ветвлениеОдна проверка — две дороги. Разбираемся, как программа перестаёт быть прямой
- ЦиклыТот же jump, только стрелка смотрит вверх — и программа начинает повторять кусок себя
- Вложенные условия и ранний выходУ jump одно условие и одна цель. Всё остальное — «и», «или», else, выход из цикла — собирается из нескольких переходов
Set Rate
Процессор работает на своей скорости всегда. setrate — единственный способ её изменить, и меняют её почти всегда вниз
Управление единицами
Unit Bind
Процессор не управляет юнитами вообще. Он управляет одним — тем, который сейчас привязан
- Привязка по типуОдин ubind — один юнит. Следующий даст другого, и так по кругу, пока не кончатся
- Держать одного юнитаПривязываться каждую итерацию незачем. Правильный цикл привязывается редко — только когда прежний юнит больше не годится
- Чужие юниты и командыУправлять чужим юнитом нельзя — ни по типу, ни по объекту. Смотреть на него можно сколько угодно
Unit Control
Всё, что юнит умеет делать по приказу, делает одна инструкция с разными первыми полями
- Движение и остановкаКоординаты в тайлах, команда живёт десять секунд, а «стоять» не значит «замереть»
- Прибытие: withinЮнит никогда не встанет ровно в точку. Спрашивать надо не «там ли он», а «близко ли»
- Предметы: взять и отдатьЮнит — это переносная ячейка склада: один вид предмета, немного мест и обязательная задержка между рейсами
- Флаг как меткаУ каждого юнита есть число, которое игра никак не использует. Без него два процессора растащат один отряд
- ДобычаКопать умеют не все и не всё, и копают с места — дотянуться до клетки юнит должен сам
- Кто управляет юнитомЮнит слушается того, кто скомандовал последним. Узнать, кто это сейчас, можно двумя свойствами
Unit Radar
Тот же радар, только смотрит не от здания, а от вашего юнита — и его дальностью
Unit Locate
Радар ищет юнитов, а ulocate — места: клетку с рудой, ближайшую турель врага, подбитое своё здание
- Где лежит рудаКоординаты руды не выписывают руками: карта у каждого своя, а поиск — одна строка
- Здания по меткеИскать здание по типу нельзя, зато можно по роли: ядро, турель, склад, генератор
- Подбитые здания и проверка находкиЧетвёртый вид поиска ищет то, что надо чинить. А заодно разберёмся, почему ответ иногда застревает
Мировой процессор
Что такое мировой процессор
Тот же язык, те же блоки — но он умеет менять саму карту, и построить его в обычной игре нельзя
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, только текст берётся не из программы, а из словаря карты — своего для каждого языка
Продвинутое
То, что не про одну инструкцию, а про то, как из них складывается работающая программа
- @counter: переход как значениеПереход — это не только jump. Номер следующей строки лежит в переменной, и его можно вычислить
- Число внутриЧисло в mlog одно на всё — дробное двойной точности. Отсюда и предел в 53 бита, и 0.1 + 0.2 ≠ 0.3
- Метки вместо номеров строкНомер строки в jump — не обязанность, а выбор. В текстовой записи цель можно назвать по имени
- Время: @time, @tick, @secondТик, секунда, минута и миллисекунда — одно и то же время в четырёх видах. Выбирать приходится по задаче
- Сколько стоит инструкцияУ процессора нет «дорогих» и «дешёвых» строк: он считает их штуками, и штук за тик ровно @ipt
- Упаковка данныхМест в памяти мало, а флаг у юнита один. Несколько чисел приходится складывать в одно
- Несколько процессоровОдин процессор — это одна очередь строк. Два идут параллельно — и это единственный способ ускориться, не меняя блок
- Пределы и редактор игрыТысяча инструкций, четыреста символов буфера, 256 команд рисования — пределы стоит знать до того, как упрёшься
- Тонкости языкаСобрание мест, где интуиция подводит: сравнения с допуском, пустота вместо бесконечности и объекты, которые равны только сами себе
Неофициальный проект, с Anuke не связан. Спрайты, шрифты и переводы Mindustry © Anuke, используются по GPL-3.0; Fira Code — по OFL-1.1. Код сайта — GPL-3.0.