1

Создай свою собственную игру на ZX Spectrum.
/Перевод на русский язык — сайт: viva-games.ru /

Часть 1

Одной из наиболее запоминающихся характеристик нашего любимого микро-хобби было то, что оно позволило многим сделать первые шаги в программировании и аппаратном обеспечении. Помимо всего прочего, и почти всегда в форме кратких мастер-классов мы могли «нарезать» куски кодовых строк для того, чтобы создавать наши собственные игры. Потом мы могли изменять их и даже обучаться в форме самообразования. Это было больше похоже на вечное обещание «Купи мне Спектрум, который поможет мне учиться».

Так вот, короче, мы всегда хотели иметь в Мире Спектрума технический отдел, и сегодня, благодаря Mojon Twins (“Близнецам Мохонам”), открывается новый раздел Семинара, в котором вы сможете научиться создавать ваши собственные игры для Спектрума. Лучше поздно, чем никогда. Это подходящий момент для того, чтобы избавиться от этой занозы, сидящей вот уже 20 или 30 лет, и, в конце концов, стать авторами вашего собственного спектрумского шедевра.

В этом повествовании, поделенном на главы, Mojon Twins расскажут нам в своем традиционном сюрреалистическом и очень юмористическом стиле о методе использования их программы Churrera v3.99b (Чуррера – продавщица «чуррос», сладкой выпечки из заварного теста). Вы увидите, насколько это просто, когда тебе все объясняют. И если у вас есть какие-нибудь сомнения, вы можете спрашивать все, что угодно посредством комментариев для того, чтобы преподаватель Мохоно, обезьяна или человек, либо ответил вам, либо продал вам подержанный мотоцикл, этого мы уже не знаем.

Итак, перед вами первая глава La Churrera v3.99b – Руководство пользователя – Copyleft 2013 The Mojon Twins.

Глава 1. Введение

Что это еще за забор?
Это говорю я. Что это еще за забор? Уффф… Столько нужно рассказать и столько мало места. Я мог бы болтать часами, говоря всякие глупости, однако постараюсь этого не делать. Мне сказали, что я должен выражать свои мысли коротко и ясно, и хотя мне это непросто, я попытаюсь быть таким.

Начнем с самого начала. В действительности продвинемся чуть-чуть дальше жаркого спора между креационистами и сторонниками теории эволюции. Отправимся в 2010 год… (Здесь звучит типичная музыка для того, чтобы поставить изображения из прошлого – та, что заставляет делать так: та-а-а, та-ра-ра-ра, та-ра-а-а…).

В начале года у нас в Мохонии была одна идея. В основном мы были по горло сыты тем, что, делая игры, копировали и вставляли. Потому что дело заключается не в том, чтобы копировать и вставлять, а в количестве тех вещей, которые всегда выполняются одинаково с изменением некоторых параметров. Посмотрим, думаешь ли ты, что мы – те, кто делает игры, – каждый раз при этом пишем одну и ту же рутину… Мы также устали от изнурительной ручной работы. Что, если перемещать вручную спрайты в формат splib2, что, если выстраивать вручную плитки для того, чтобы SevenuP прочитал их в правильном порядке, что, если пройти карту, что, если разместить врагов на листе в клетку… У нас была тысяча забот во время производства игр, которые получались скучными и тоскливыми. А кто хочет скучать, пока он делает то, что предположительно ему нравится? Мы – нет. И, полагаю, что и ты – тоже.

Я уже это знаю. То, что рисовать игры и делать все на милиметровой бумаге, – это привет из 80-х, и это действительно утомительно. Можно быть фриком, но мазохистом – никогда.

Поэтому случилось так, что нам стал нужен фреймворк, как его теперь называют, что позволил бы нам располагать кодовыми модулями, которые мы хотели бы использовать в простой форме, и который бы сносно выполнил нам всю тему преобразования и интеграции данных (рисунки, карты, расположение врагов и предметов…). Мы робко начинаем с написания утилит преобразования для того, чтобы потом, используя кусочки оттуда и отсюда, создавать движок, который послужил бы нам основанием.

http://zxaaa.net/store/images/02lala-beta-falsa-51051.png

У нас была куча идей для движка. Мы могли бы развивать его понемногу и затем получить окончательный вариант игры, но мы не действуем подобным образом. Поскольку с нами приключались приступы паранойи, мы получали игры всякий раз, когда отправляли что-то новое в движок. Таким образом, как только был готов «оперативный минимум», мы выпустили Lala the Magical («Волшебница Лала»), Cheril of the Bosque («Шерил из Леса»), Sir Ababol («Сэр Простофиля») и Viaje al Centro de la Napia («Путешествие к Центру Носа»).

Поскольку, оглядываясь назад, мы лепили игры как «чуррос» (но о каких «чуррос» речь, сеньора!), мы решили назвать систему «Ла Чуррера». И так все и началось…

Но тогда, что именно это такое, Churrera?
Пожалуй, вот так: Churrera – это фреймворк, который состоит из нескольких очень забавных вещей:

1. Движок или «мотор», сердце Чурреры. Речь идет о наборчике потрясающих кодов, который «управляется» посредством главного файла, именуемого “config.h“. В нем мы указываем, какие части «мотора» мы будем использовать в нашей игре, и как они будут себя вести.
2. Утилиты преобразования, которые позволяют нам нарисовать нашу игру в наших излюбленных редакторах и в бесцветной, лишенной запаха и вкуса, форме поместить в нее все эти данные.
3. Куча обезьян, незаменимых для любой вещи, которую хотелось бы сделать при наличии тех или иных условий.

http://zxaaa.net/store/images/03mono-27161.png
«Продаю подержанный мотоцикл»

У Чурреры было много версий на протяжении трех последних лет. От внутренней формы мы дошли до версии 4.7, однако наборчик получился непрезентабельным. Он был очень беспорядочный, и у него слишком было много хаков. Таким образом, когда нам пришло в голову сделать руководство пользователя, мы решили вернуться немного назад, в ту точку прошлого, когда эта тема была еще управляемой – к версии 3.1: Trabajo Basura («Грязная работа»), Zombie Calavera Prologue («Зомби Калавера. Пролог»). Но не думайте, что мы ограничимся тем, что дадим вам нашу «старую версию», и на этом хватит. Нет, ничего подобного.

В течение пары месяцев мы целиком и полностью посвятили себя тому, что взяли версию 3.1, исправили в ней все недоделки, поменяли половину компонентов для того, чтобы сделать их более быстрыми и компактными, а также добавили кучу характеристик.  Таким образом, мы создали версию 3.99b, которую предоставляем в ваше распоряжение, и которая во многих отношениях более продвинутая, более быстрая и выполняет больше действий, чем версия 4.7. На самом деле у нас получилось так хорошо, что мы продолжаем разработку, начиная с этой версии 3.99b, включая усовершенствования «ветви 4» «Ramiro el Vampiro» («Рамиро-Вампир»), которые мы будем считать интересными.

Версия 3.99b настолько оптимизирована, что, если мы рекомпилируем старые игры с ней, то получим бинарники на 2 – 5 килобайтов меньшего размера, с более быстрыми движениями и намного более связные. И она находится в вашем распоряжении.

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

Но что можно сделать с помощью этого?
Пожалуй, кучу разных вещей. И они уже пришли нам в голову. И хотя верно, что есть общие элементы и определенные ограничения, очень часто ты можешь вытащить из рукава новую паранойю, всего лишь комбинируя в различной форме элементы, которые имеешь в своем распоряжении. Хочешь примеры? Для этого самого мы запустили Mojon Twins Covertape #2. Если у тебя его еще нет, скачай. СЕЙЧАС.

Для Mojon Twins Covertape #2 мы наняли племя грязноногих индейцев родом из Джунглей Бадахоса. Каждому из них мы написали одну характеристику Чурреры на спине, а другую – на груди, и отправили их спускаться по холмам, образуя крокету (род котлеты). Когда они спускались вниз, мы сделали фотографию и отметили возникшие комбинации. С помощью этих комбинаций мы создали игру. Потом мы позвали Альберто, Одноглазую Обезьяну, который придумывает небылицы с тем, чтобы он подтвердил их, используя какой-нибудь убедительный аргумент. И это работает, серьезно.

http://zxaaa.net/store/images/04set1-29271.png

Окинем взглядом то, что мы имеем в наличии:

1. Характеристики: Все характеристики, связанные с движением главного героя, изменяемые. Мы можем сделать так, чтобы он прыгал больше или меньше, чтобы падал медленнее, чтобы больше скользил, бегал много или мало, и многое другое.
2. Ориентация: Мы можем сделать так, что наша игра будет смотреться сбоку или сверху (то, что мы в Мохонии называем «генитальной перспективой»). Это первое, что мы должны решить, потому что именно от этого будет зависеть весь дизайн игры.
3. Прыгать? Летать? Как? Если мы выберем боковую перспективу (так, чтобы игра смотрелась со стороны), мы должны будем определить, как станет двигаться фигурка. Мы можем сделать так, чтобы она прыгала, когда нажимаем на «прыжок» (Lala Lah, Julifrustris, Journey to the Centre of the Nose, Dogmole Tuppowski…), чтобы прыгала всегда (Bootee), или чтобы с каждым разом прыгала все выше, обретая силу (Monono). Также мы можем сделать, чтобы она летала (Jetpaco).
4. Отскакивать от стен. Если мы выберем для нашей игры «генитальную перспективу», то мы можем сделать так, чтобы герой немного отскакивал от стены, когда он с ней сталкивается.
5. Специальные блоки. Мы можем активировать или дезактивировать ключи и засовы или блоки, которые можно толкнуть. Это работает для обеих ориентаций, хотя при боковой перспективе блоки можно будет толкать только в сторону.
6. Стрелять. Также мы можем сделать так, чтобы главный герой стрелял. В играх с «генитальной перспективой» он будет стрелять в любом из четырех основных направлений. Также мы можем указать движку, какое направление (вертикальное или горизонтальное) имеет предпочтение на диагоналях. В играх с боковой перспективой он будет стрелять в том или ином направлении в зависимости от того, куда он смотрит – налево или направо.
7. Летающие враги: те, которые преследуют тебя без передышки.
8. Вражеские преследователи: похожие, но разные… Мы еще поговорим о них.
9. Острия и какие-то предметы со сцены, которые тебя убивают, необязательно острые.
10. Убивать: в играх с боковой перспективой мы можем сделать так, чтобы враги (определенный тип врагов) умирали, если ты наступишь им на голову.
11. Предметы: для того, чтобы были вещи, которые по ходу можно собирать и хранить в мешке.
12. Скриптинг Если всего вышеизложенного недостаточно, мы можем придумать гораздо больше опций, используя простой встроенный язык скриптинга.
И много-много другого, что сейчас я не помню, но по мере того, как мы будем продвигаться вперед, это обязательно придет мне на ум.

Трюк заключается в том, чтобы комбинировать эти вещи, призывая на помощь воображение, немного заимствуя от рисунков, и в итоге, быть немного креативным. Например, если мы включим слабую гравитацию, которая заставит главного героя падать очень медленно, предоставив ему возможность летать с очень маленьким ускорением, поставим синий фон и снабдим персонажа формой водолаза, то сможем сделать так, словно мы находимся под водой. Также можно попробовать какие-то крайности – как, например, включить характеристик вертикального ускорения и отрицательной гравитации с тем, чтобы фигурка резко улетала вверх и прикладывать усилия для того, чтобы опуститься вниз… Конечно, мы этого никогда не пробовали, и мне только что пришла в голову одна идея… Как только я поговорю с Альберто, и придумаю какой-нибудь аргумент, у нас будет новая игра.

Видите? Вот так это работает! Отправьте мне email, и я дам вам телефон Альберто.

Тогда с чего мы начнем?
С воображения. Меня не устраивает, что ты возьмешь какую-нибудь нашу игру, уже сделанную, и что-нибудь в ней поменяешь. Нет. Так ты далеко не уйдешь. Некоторые люди так не считают, но я говорю тебе – НЕТ. Изобрети что-нибудь, начни с нуля, и мы постепенно будем это строить, шаг за шагом.

Если у тебя не получается рисовать, найти друга, который бы умел это делать. Серьезно, такой человек всегда есть. Если ты его вдруг не найдешь, то ничего страшного – ты можешь использовать любой рисунок, который сделаем мы. В архивах исходного кода всех игр находятся все рисунки в формате png. Научиться вырезать и вставлять их с помощью графического редактора – это минимум того, чему ты должен научиться.

В любом случае, для того, чтобы начать, и будучи уверенным в том, что вы действительно не знаете, чего можно делать, а чего нельзя, я приглашаю вас к пошаговому созданию Dogmole Tuppowski. Почему именно этой игры? Потому что она использует много всего, включая скриптинг. Но я не хочу, чтобы ты уходил, забрав архив исходников Covertape #2, и ограничился тем, что стал бы следовать инструкции, просматривая эти архивы. Нет. Тебе предстоит начать с пустого движка, который мы предложим тебе ниже, и с каждой главой ты будешь получать различные средства и осуществлять необходимые действия, как если бы ты действительно создавал игру с нуля.

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

Давай же, поехали! Начинаем
Сначала надо придумать историю, которая указывала бы на геймплей. Мы не станем пока писать историю для игры (потому что на данный момент в ней не нуждаемся) – это придет чуть позже. Первым делом мы решим, что нужно делать.

Давайте создадим игру с Dogmole Tuppowski – персонажем, которого мы придумали давно, и который выглядит вот так.

http://zxaaa.net/store/images/05tuppowski-35411.gif

В первую очередь условимся, что мы делаем игру в боковой перспективе, с платформами, на которые запрыгивает этот персонаж. Он не станет прыгать слишком высоко, пусть он сможет покрыть расстояние в четыре или пять плиток по горизонтали и в две – по вертикали. Это мы должны решить сейчас, потому что дальше нам следует нарисовать карту и убедиться в том, что игрок сможет добраться до тех мест, которые мы ему определили.

Мы сделаем, чтобы для завершения игры нужно будет выполнить две миссии. Этого мы добьемся посредством скриптинга – то, что мы оставим на окончание процесса. Эти миссии будут простыми и будут использовать автоматические характеристики «движка» для того, чтобы не нужно было писать слишком сложный скрипт:

Будет определенный тип врагов, которых нам необходимо уничтожить. После этого мы получим доступ ко второй миссии, потому что на экране исчезнет каменный блок, который закрывает проход к какой-нибудь части карты.
Нужно будет перенести предметы по одному к той части карты, которая разблокируется после выполнения первой миссии.
Для того, чтобы обосновать это, объясним, что враги, которых следует уничтожить, являются колдунами или монахами или чем-то таким магическим, что удерживает закрытой ту часть сцены, куда нужно носить предметы. История пишется сама по себе!

Так как мы уже знаем, что должны будем создать игру с боковой перспективой, с прыжками (при этом можно будет наступать на определенный тип врагов и убивать их, и нести на себе только один предмет), нам потребуется скриптинг. Он нужен для того, чтобы нарисовать камень на входе в то место, куда будет нужно приносить предметы, если мы не убили врагов. Кроме того, перенос предметов по одному с тем, чтобы оставлять их в каком-то месте, также требует немного скриптинга.

Поскольку у нас есть яйцо, мы придумываем историю, которую ты уже знаешь, если прочитал в свое время описание Covertape #2:

Догмоле Тупповски – это хозяин жестяной шлюпки, на которой он перевозит редкие вещи и прочие артефакты сомнительного происхождения (некоторые говорят, что они обладают магическими свойствами) для некоего ведомства Университета Мискатоник (провинция Бадахос). Однако однажды ночью, когда он собирался совершить свою поставку в виде ящиков, полных загадочных и магических предметов, поднялся жуткий шторм, в результате которого его корабль налетел на кучу камней, из-за чего произошел потрясающий взрыв, и все ящики оказались разбросанными по пляжу и окрестностям.

Сеньорита Мимайд из Мискатоника, которая причесывалась при свете полной луны на своей крепостной башне, все это видела и, уверенная в том, что содержимое ящиков может представлять большую ценность для оккультистов и прочих странных личностей, решила собрать их. Поскольку ее грузовик был сломан и до следующего дня находился в ремонте, она отправила охранять ящики своих приспешников, а вместе с ними и двадцать Колдунов Религии Петете, которые своим колдовством закрыли двери Университета.

Следовательно, у Догмоле двойная миссия. Сначала он должен уничтожить двадцать Колдунов Религии Петете, и затем, открыв дверь Университета, найти и отнести по одному десять ящиков в вестибюль здания, где ему следует оставить их под вывеской «BOXES», нажимая «A».

Теперь мы можем приступить к дизайну нашей игры. В действительности все обычно получается так. В нашей игре мы обычно делаем ловушки и играем с форой; многие из наших игр появились, потому что мы добавили к Чуррере какую-нибудь новую опцию, и нужно было ее опробовать, как это произошло с Bootee, Balowwwn, Zombie Calavera или Cheril the Goddess. Креативный процесс не имеет «дна» и требует от тебя наличия некоторой изобретательности и воображения, чему, к сожалению, научить нельзя.

Да,  я уже было забыл. Также мы сделали рисунок Meemaid. Вот она:

http://zxaaa.net/store/images/06meemaid-01511.gif

Лицом в грязь

Давайте уже начинать собирать все необходимое. Прежде всего, тебе потребуется пакет z88dk, представляющий собой компилятор C под Z80, и splib2 – графическая библиотека, которые мы используем. Поскольку мы не хотим, чтобы ты осложнил себе жизнь, устанавливая их (особенно потому, что splib2 – очень старая, и ее трудно скомпилировать, используя современный z88dk), мы подготовили для пользователей Windows этот архив, который нужно распаковать прямо в корень С, и который содержит в себе z88dk 1.10 и splib2. Если у тебя все получится, то должна будет появиться папка C:\z88dk10 с файлами внутри.

http://www.mojontwins.com/churrera/mt-z88dk10.zip (скачать локально: mt-z88dk10)

Пользователи Linux и других систем не должны иметь никаких проблем с установкой последней версии z88dk на своих системах: нужно скопировать файлы splib2.lib и splib2t.lib туда, где папка clibs и spritepack.h туда, где папка includes. Эти два файла я оставил для них здесь:

http://www.mojontwins.com/churrera/mt-splib2.zip (скачать локально: mt-splib2)

Также нам будет нужен текстовый редактор. Если ты программист, то у тебя уже есть такой редактор, с которым ты великолепно обращаешься. Если ты таковым не являешься, то, пожалуйста, не используй “Блокнот”! Скачай, к примеру, Crimson Editor. В действительности любой из редакторов лучше, чем Блокнот на Windows. Если у тебя стоит Linux, то ты будешь иметь в своем распоряжении, по крайней мере, около шестнадцати установленных текстовых редакторов; так что, пользователи Linux, тут преимущество на вашей стороне.

Для того, чтобы сделать карты игры, нам будет нужен редактор Mappy. Можешь скачать официальную версию, хотя лучше использовать мохонскую версию. Она была изменена с добавлением всех необходимых вещей и пары пользовательских характеристик, пришедшихся очень кстати, в чем мы еще убедимся.

http://www.mojontwins.com/churrera/mt-mappy.zip (скачать локально: mt-mappy)

Также нам будет нужен SevenuP для осуществления преобразования рисунков. Скачай его с официального сайта, отсюда:

http://metalbrain.speccy.org/

Когда мы дойдем до звука, поговорим об утилитах Beepola и BeepFX. Ты можешь найти их и скачать сейчас, если хочешь, но мы не будем их использовать до самого конца.

Тебе также будет необходим хороший графический редактор для того, чтобы раскрашивать обезьянок и «рожки» на экране. Тебе подойдет любой, который сохраняет файлы в формате .png.  Я повторяю тебе, что, если ты не умеешь рисовать, и у тебя нет такого друга, ты можешь «стащить» рисунки с Mojon Twins. Таким же образом тебе потребуется графический редактор для того, чтобы вырезать наши рисунки и вставлять их в твои. Тебе подойдет любой. Я использую суперстарую версию Photoshop, потому что я к ней привык. Многие пользуются Gimp. Их насчитывается целая куча, выбирай тот, что тебе больше по вкусу. Но чтобы он сохранял файлы в формате .png. Запомни. Если пьешь, то за руль не садись.

После установки всего этого нам будет нужна Чуррера. По следующему адресу находится полный архив версии 3.99b:

http://www.mojontwins.com/churrera/mt-c … -3.99b.zip (скачать локально: mt-churrera-3.99b)

Для того, чтобы приступить к работе, распакуем архив Чурреры в корневую папку и персонализируем его для нашей игры, следуя этим шагам:

Изменяем имя главной директории Churrera3.99b на имя из нашей игры. Например, «Dogmole Tuppowski».
Изменяем имя главного модуля C на имя из нашей игры. Этот модуль находится в /dev/ и называется churromain.c. Мы изменим его на имя dogmole.c.
Редактируем файл make.bat который находится в /dev/ с помощью нашего текстового редактора для того, чтобы адаптировать его к нашей игре. В первую очередь, нужно заменить там, где ставится %1, и поставить имя, которое ты дал churromain.c. В нашем случае, dogmole.
Должно получиться так:

http://zxaaa.net/store/images/codigo01-06301317471.png

Всякий раз, когда мы создаем новую игру, мы должны будем распаковать новую копию Churrera и таким же образом ее персонализировать.

Мы уже готовы к тому, чтобы начать… Но вы должны будете подождать следующей главы.

2

Создай свою собственную игру на ZX Spectrum. Часть 2

http://zxaaa.net/store/images/tileset-55131-384x112.png

Продолжаем Семинар по созданию своей собственной игры на Спектруме с помощью Чурреры от Mojon Twins. Во второй главе мы уже вникнем в работу и начнем наблюдать за процессом создания игры. Он покажется сложным, но вы не пугайтесь – если посвятить этому немного времени и внимания, то не будет никакой проблемы. Кроме того, когда всё объясняют с юмором и в доступной форме, результат не заставит себя долго ждать.

Но не будем терять времени понапрасну. Пойдём туда.

Глава 2. Тайлсет
Перед тем, как приступить

В этой главе и практически во всех остальных мы должны будем открыть окно с командными строками для исполнения скриптов и программок, а также для того, чтобы запустить компиляцию игры. Я хочу сказать, что ты должен обладать какими-то базовыми знаниями об этих понятиях. Если ты не знаешь, что представляет собой то, о чем рассказывается по ссылке внизу, тебе лучше обратиться к какому-нибудь начальному курсу о работе с окном командных строк (или консоли) в той операционной системе, которую ты используешь. Или же позвони своему другу в очках и футболке с логотипом «Камень-Ножницы-Бумага».

http://zxaaa.net/store/images/consola-34391.png

Материалы

Все материалы, необходимые для того, чтобы следить за развитием событий в данной главе, я оставил вам здесь:

http://www.mojontwins.com/churrera/chur … itulo2.zip (скачать локально: churreratut-capitulo2)
http://viva-games.ru/wp-content/uploads … tulo21.zip

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

Тайлсет… О чем это мы вообще говорим?

О тайлах (плитках). Что такое «тайл»? Чтобы не усложнять скажем, что это не более, чем часть рисунка одинакового размера и формы по сравнению с другими частями. Для того, чтобы ты увидел их воочию, посмотри, что означает слово «azulejo» («изразец»),  хотя на самом деле речь идет об аббревиатуре TILE, которая расшифровывается как «у меня есть сумасшедшие и взбалмошные идеи». Подумай о стенке в своей ванной и представь себе, что в каждой плитке есть кусочек рисунка. У нас есть плитка с кусочком кирпича, с кусочком травы, черная плитка и плитка под цвет земли. Задействуя каждую из них, мы можем упорядочить их так, что в итоге получим рисунок, похожий на загородный дом. Такая ванная понравилась бы каждому, вне всякого сомнения.

http://zxaaa.net/store/images/tiles-35441.png

Это то, что Чуррера использует для того, чтобы делать фоновые рисунки. Поскольку сохранение каждого рисунка занимает одну ячейку, нужно сохранить определенное число частичек и потом – список, сколько таких частичек приходится на каждый экран. Набор частичек игры – это то, что подразумевается под словом «тайлсет». В данной главе мы объясним, что представляют собой тайлсеты Чурреры, как они создаются, как преобразуются, как импортируются и как используются. Но перед этим нам необходимо получить представление о некоторых понятиях. Иди, приготовь себе сок.

Столкновение

Помимо всего прочего, Чуррера использует плитки для определения столкновения. «Столкновение» – это очень забавное название для того, чтобы иметь в виду нечто очень глупое; главный герой игры сможет ходить по экрану вне зависимости от типа плитки, на которую он будет наступать. Каждая плитка связана с тем или иным его состоянием, статусом. Например, черной плитке мы могли бы придать статус «проходной» с тем, чтобы игрок мог свободно перемещаться по пространству, занимаемому этими плитками. Наоборот, плитка цвета травы могла бы стать «препятствием» для главного героя. В играх на платформах «мотор» заставит его падать всякий раз, когда у него под ногами окажется такое «препятствие».

В играх Чурреры мы располагаем следующими типами плиток – или, точнее говоря, их статусами. Кроме того, каждый из них обладает кодом, который нам потребуется знать – не сейчас, но позже, когда у нас уже будут все данные, и мы начнем составлять игру.

Пока же мы ограничимся следующим списком:

Тип «0», проходимый. В играх на платформах это могут быть небо, какие-то кирпичи на фоне, картина дяди Нарсисо, уродливая ваза для цветов или горы, похожие на задницу. В играх с «генитальной перспективой» мы используем его для пола, по которому можем ходить. Или же это будут предметы, которые не станут мешать передвижению фигурки.

Тип «1», проходимый и убивающий: через него можно проходить, но прикосновение к нему будет стоить жизни главному герою. Например, это могут быть какие-то острые предметы, колодец с лавой, радиоактивный кальмар, разбитые стекла или же грибы в Cheril of the Bosque (ты помнишь? их нельзя было даже трогать!).

Тип «2», проходимый, но прячущий. Это заросли из Zombie Calavera. Если герой был неподвижен за этими плитками, предполагалось, что он «спрятался». Подобные эффекты не представляют особого интереса, так как оказывают действие только на летучих мышей из Zombie Calavera, но мы будем иметь их в виду.

Тип «4», платформа. Очевидно, что они имеют смысл лишь в платформерах. Эти плитки задерживают главного героя только сверху; если ты находишься внизу, то можешь прыгать через них, но если ты упадешь сверху, то останешься на ней. Не знаю, как это тебе объяснить… наверное, как в игре Sonic. К примеру, если ты нарисуешь колонну, которая занимает три плитки (голова, тело и нога), ты можешь придать телу тип «0», а голове – «4», и тогда на колонну можно будет взобраться. Также подходит использовать этот тип для тоненьких платформ, которые не являются препятствиями для всего подряд как металлические платформы, появляющиеся во многих из наших игр.

Тип «8», препятствие. Этот тип останавливает главного героя со всех сторон: стены, скалы, пол – все это относится к типу «8». Он просто не дает ему пройти.

Тип «10», поддающийся внешнему воздействию. Это препятствие, но поскольку оно относится к типу «10», «мотор» знает, что оно является особенным. К нему пока относятся замки и блоки, которые можно толкать и сдвигать. Поговорим о них через некоторое время.

Ну что за дерьмо, посмотри, там пропущены числа! И ещё больше пропущено раньше. Это сделано потому, дружище, что очень сильно упрощает вычисления, и позволяет в будущем добавить еще больше типов. К примеру, заметь, что всё больше или равное 4 останавливает героя сверху, а всё, что меньше или равно 7 позволяет пройти сбоку. Видишь? Это трюки асов программирования.

Кроме того, в будущем, как мы уже сказали, это количество можно легко увеличить. Например, можно было бы добавить код к Чуррере для того, чтобы плитки типов «5» и «6» были бы словно транспортные ленты, движущиеся налево и направо соответственно. Их можно было бы добавить… Можно было бы. Скорее всего, под конец мы сделаем главу о том, как, засучив рукава, добавить новый код в Чурреру… Почему бы и нет?

Взаимодействующие плитки
В нынешней версии Churrera есть два вида взаимодействующих плиток: в виде замков и те, что можно двигать. Ты должен решить, нуждается ли твоя игра в таких характеристиках.

Замки тебе будут нужны, если ты вводишь в игру ключи. Если главный герой наталкивается на замок и имеет при себе ключ, то пусть он его откроет. Замок исчезнет, и можно будет пройти.

Плитки, которые можно толкать, при контакте с главным героем меняют свое расположение, если для этого есть свободное место. В платформерах их можно перемещать только в стороны; в играх с «генитальным отображением» их можно двигать в любом направлении. Как мы увидим в соответствующий момент времени, можно определить пару действий, связанных с плитками, которые разрешено толкать. Например, если мы захотим, чтобы враги не могли через них пройти, как это происходит в Cheril of the Bosque или Monono.

Перейдем уже к делу, а?
Да, уже переходим к делу. Давайте нарисуем наш тайлсет, или откуда-нибудь его стащим; ну, или попросим нарисовать его нашего друга. Да, дружище, на свете полно художников, обделенных вниманием. В первую очередь мы должны определиться с тем, будем ли мы использовать тайлсет из 16 разных плиток или же из 48, поскольку именно эти два размера тайлсета поддерживает Чуррера. Какая чушь, ты скажешь 48 – это больше! Конечно, мой дорогой Эйнштейн, но вот какая вещь: 16 разных плиток можно представить 4-битным числом. Это означает, что в одном байте, в котором содержится 8 бит, мы можем хранить две плитки. К чему я веду? Правильно, ты угадал! Карты займут в 2 раза меньше памяти, если мы будем использовать тайлсеты из 16 плиток вместо тайлсетов из 48.

Я уже знаю, что 16 плиток может показаться недостаточно, но подумайте над тем, что большинство наших игр сделаны именно таким образом, и они не так уж и уродливы. Приложив немного изобретательности, мы можем сделать очень забавные экраны с помощью малого числа плиток. Кроме того, как мы увидим в дальнейшем в этой самой главе, использованием тайлсетов из 16 плиток позволит нам активировать эффект автоматических теней, из-за чего будет казаться, что мы используем больше 16 плиток. Однако, сохраняй спокойствие, мы еще туда не добрались.

Пока что откройте вашу излюбленную программу графического редактирования и создайте новый файл размером 256 x 48 пикселей. Вне всякого сомнения, у вашей программы есть опция для активации сетки (grid). Запустите ее для того, чтобы сделать квадраты размером 16 x 16 пикселей, и, если это возможно, с двумя подделениями для того, чтобы мы смогли видеть, где начинается каждый символ (размера 8 x 8 – прим. пер.). Это поможет нам создать рисунки, придерживаясь ограничений Спектрума, или же знать, где начинается и заканчивается каждая плитка, когда мы будем вырезать и/или рисовать их. Я использую суперстарую версию Photoshop, и когда создаю новый тайлсет, вижу перед собой нечто подобное:
http://zxaaa.net/store/images/nuevo-tileset-48431.png

Тайлсет из 16 плиток
Если ты решил экономить память (например, если ты планируешь, что «мотор» игры получится довольно сложнымсо скриптингом и многими муторными вещами, или же если ты предпочитаешь, чтобы карта была достаточно большой) и использовать тайлсет из 16 плиток, ты должен создать нечто подобное:

http://zxaaa.net/store/images/tileset-dogmole-58551.png

Тайлсет делится на две части. Одна, образованная первыми шестнадцатью плитками, является набором плиток для карты, который мы будем использовать для того, чтобы сделать эту карту. Другая, образованная четырьмя следующими плитками, – это набор специальных плиток, который будет использоваться для того, чтобы рисовать какие-то особенные вещи.

Начнем с осмотра набора плиток для карты.

По определению, плитка 0 или первая в тайлсете (настоящие разработчики начинают считать с нуля) будет плиткой основного фона – той, что занимает большинство фона на большинстве экранов. Это не обязательное требование, но оно очевидно облегчит нам жизнь, когда мы сделаем карту, так как в пустой карте все плитки будут нулевыми.

Плитки от 1 до 13 могут быть какими угодно: плитками фона, препятствиями, платформами, убивающими…

Плитка 14 (предпоследняя), если ты решил активировать плитки, которые можно двигать, станет такой. Она должна быть именно 14-й, и никакой другой.

Плитка 15 (последняя), если ты решил активировать ключи и замки, станет плиткой замка. Она должна быть 15-й и никакой иной.

Если ты не собираешься использовать эти виды плиток, то 14 и 15, разумеется, останутся свободными.

Что касается набора специальных плиток, то он образован следующими плитками (слева направо):

Плитка 16 – это подзарядка жизни. Она появится на карте, и если пользователь ее заберет, то добавит себе немного жизни.

Плитка 17 представляет предметы – те, которые игрок должен будет собирать по ходу игры, если мы решим их активировать.

Плитка 18 представляет ключи. Если мы захотим включить в игру ключи и замки, то нарисуем ключ на этой плитке.

Плитка 19 – это альтернативный фон. Для того, чтобы придать экранам немного разнообразия в выборочной форме, иногда используют эту плитку вместо плитки 0. Например, если твоя плитка 0 – это небо, ты можешь поставить на нее звездочку. Или, если ты создаешь игру в «генитальной перспективе», то можешь задействовать различные вариации пола.

Для начала надо нарисовать 20 плиток: 16 для того, чтобы сделать карту, и 4 для того, чтобы представить объекты и уменьшить монотонность фонов. Не нужно говорить, что если ты, к примеру, не собираешься использовать в своей игре ключи и замки, то можешь сэкономить на краске, отказываясь рисовать ключ в плитке 18.

Например, в dogmole

http://viva-games.ru/game/dogmole-tuppowski

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

Автоматическое наложение теней
Автоматическое наложение теней может сделать так, что наши экраны будут смотреться намного прикольнее. Если мы его активируем, то Churrera сделает так, что плитки-препятствия станут отбрасывать тени на остальные. Для того, чтобы этого добиться, мы должны определить альтернативную версию набора плиток карты с помощью плиток, которые мы вставим в нижний ряд нашего плиточного файла следующим образом:

http://zxaaa.net/store/images/tileset-cheril-02521.png

У нас будет тотальный контроль над тем, как отбрасываются тени. Полученный результат вы можете видеть во многих из наших игр – в частности, в Cheril Perils, которой принадлежит этот тайлсет. Заметь, как плитки-препятствия отбрасывают тень над плитками фона. Также это видно в Lala Lah, к которой относится следующий экран:

http://zxaaa.net/store/images/cheril-perils-shot-04281.png
http://zxaaa.net/store/images/lalalah-shot-05091.png

Мы не можем использовать это в Dogmole, потому что пространство, которое заняли бы автоматические тени, нужно нам для других целей.

Примеры
В качестве примера давайте посмотрим на некоторые тайлсеты из наших игр, чтобы вы увидели, как они были разработаны.
http://zxaaa.net/store/images/tileset-lalalah-06181.png

Здесь у нас тайлсет из Lala lah. Как мы видим, первая плитка – это синий фон, который виден на большинстве экранов. За ним следует кусок платформы, который также является плиткой фона, а затем – бортик, который относится к плитке типа «платформа» (тип 4). Если ты играешь в эту игру, то увидишь, как будет себя вести данная плитка для того, чтобы все понять. Желтый камень, который следует за ней, это препятствие (тип 8). Дальше у нас два психоделических куста, служащих украшением фона (тип 0). Потом идет другой камень (8), выложенный кирпичом фон (0), вариация квадратиков (0), шар с шипами, который убивает (тип 1), ящик со звездой (8), две плитки для того, чтобы сделать две непроходимые ленты (и потому они типа 8), платформа с сосульками (тип 4). И в завершение, плитка №15 будет типа 10, потому что мы используем замки, а замки должны быть препятствиями, которые поддаются воздействию. Затем у нас есть подзарядка, предмет и ключ, альтернативная плитка для фона, а в нижнем ряду – те, что используются при автоматическом наложении теней. Давайте рассмотрим другой пример:

http://zxaaa.net/store/images/dveelng-work-07131.png

Это тайлсет из D‘Veel‘Ng, игры с «генитальной перспективой». Он начинается с двух плиток для пола (тип 0), за которыми следуют четыре препятствия (тип 8) – кости, череп, скелет и камень, две убивающих и причиняющих вред плитки (тип 1), коими являются эти столь отвратительные красные черепа. Потом идет другое препятствие в виде желтых кирпичиков (тип 8), другой пол, облицованный плиткой (тип 0), еще одна убивающая плитка в форме вредоносного гриба (тип 1), белые кирпичики (тип 8), еще пол (тип 0) и очередной череп, представляющий собой препятствие (тип 8). В этой игре есть плитки, которые сдвигаются, поскольку плитка 14 – это красный ящик типа 10. Также у нас есть ключи, поскольку плитка 15 – это замок типа 10. После этого следует типичная подзарядка жизни, предмет, ключ и альтернативный фон, который рисуется выборочно. В нижнем ряду у нас вновь будет отбрасывающая тень версия двух плиток фона. Заметь, как я оставил плитки, которые убивают, на «затеняющей» ленте – это для того, чтобы они всегда хорошо выделялись. Вот еще:

http://zxaaa.net/store/images/monono-work-09061.png

Теперь пришел черед тайлсета Monono.

Он очень прост: начнем с плитки основного фона, свободного от всего (тип 0). Дальше будут шесть препятствий (тип 8), еще две плитки фона для его украшения, окошко, чтобы высунуться и сказать: «Привет! Что ты тут делаешь?» и щит. Затем идут три плитки-препятствия (тип 8), несколько ядовитых шипов (тип 1), наша типичная металлическая платформа «специальная подпись (c) Mojon Twins» (тип 4), ящик, который можно толкать (плитка 14, тип 10) и замок (плитка 15, тип 10). Затем – то, что обычно: подзарядка, предмет, ключ, альтернативный фон. У него нет автоматического наложения тени.

Я мог бы продолжать, но у меня больше нет желания.

Тайлсет из 48 плиток
Как мы предупреждали, карты, сделанные с помощью тайлсетов из 48 плиток, занимают в два раза больше места, чем те, в которых было задействовано 16 плиток. Если ты все еще решил следовать по этому пути, то здесь ты найдешь объяснение, как это сделать.

Прежде всего, здесь нет четкой дифференциации между отделом карты и специальным отделом – всё объединено. Кроме того, невозможно добавлять автоматическое наложение тени (у нас нет места для альтернативных версий плиток). Особенно ощущается, что это тайлсет из 48 плиток, когда был добавлен удар по спине для Zombie Calavera, который мы больше так и не использовали. Однако, ты всё ещё можешь это применить.

В тайлсетах из 48 плиток мы можем использовать плитки от 0 до 47 для того, чтобы делать экраны за исключением тех, что соответствуют специальным характеристикам: 14-ю для сдвигаемой плитки, 15-ю для замков, 16-ю для подзарядки, 17-ю для предметов и 18-ю для ключей, если ты их будешь использовать. В противном случае можешь поставить свои собственные плитки. В тайлсетах из 48 плиток также не используется плитка 19 в качестве альтернативной плитки фона, и таким образом ты можешь поместить туда все, что захочешь.

Единственным примером является тайлсет из Zombie Calavera. Если ты заметил, в Zombie Calavera нет ни ключей, ни замков, поскольку в качестве «специальных» заняты только плитки 16 для зарядки жизни и 17 для предметов. Также нет сдвигаемых плиток. Все остальные используются для рисования сцены:
http://zxaaa.net/store/images/tileset-calavera-11041.png

У нас уже есть нарисованный тайлсет. И что теперь?
Прежде всего, следует сохранить его как главную копию в папке /gfx , назвав ее work.png. Теперь мы должны подготовить его к использованию. Сделаем две версии: ту, которую импортируем в игру, и ту, которую будем использовать в Mappy для того, чтобы сделать карту, и для размещения врагов и предметов для того, чтобы… догадайся)

Если ты следуешь по инструкции Dogmole без своих собственных экспериментов, ты можешь найти work.png в архиве файлов этой главы.

Тайлсет для Mappy
Mappy очень занудная. Нужно, чтобы плитка 0 была пустой или полностью черной. Если ты загружаешь тайлсет, в котором первая плитка не является полностью черной, то он сам добавляет полностью чёрную плитку в начало и сдвигает все остальные плитки. Это полная хрень, потому что тогда мы будем делать карту с пляшущими индексами. Нет, так не пойдет. Поскольку мы не можем изменить это свойство Mappy, мы модифицируем наш тайлсет. Если ты использовал рисунок в плитке 0 (например, делая так, чтобы фон твоей игры был синим, или, рисуя точечки для того, чтобы имитировать газон в «генитальной перспективе»), то ты должен сделать эту плитку полностью черной.  Мы вырежем 16 плиток (если наш тайлсет из 16 плиток) и оставим первую пустой (в нашем случае нам не нужно этого делать, но в таких играх как Cheril of the Bosque без этого было бы не обойтись):

http://zxaaa.net/store/images/tileset-mappy-47131.png

Данный тайлсет мы сохраним в папке /gfx как mappy.bmp, потому что Mappy и укладчик лучше всего работают с этим форматом.

Запомни, это важно (это следует читать материнским голосом, чтобы лучше до тебя дошло): если плитка 0 не является полностью черной, ты должен сделать так, чтобы она была такой. Посмотри предыдущие примеры. В Zombre Calavera, Lala lah или D‘Veel‘Ng, где это нужно было делать. Я прямо чувствую, что ты потом придешь ко мне с законченной картой и пляшущими индексами, и нам придется возиться для того, чтобы привести ее в порядок.

Тайлсет для импорта
Splib2, библиотека, на которой работает Churrera, управляет набором символов в количестве 256 штук для того, чтобы рисовать фон помимо спрайтов, которые идут сверху. Поэтому наш следующий шаг заключается в создании набора символов для того, чтобы импортировать в игру, используя наш тайлсет и какой-нибудь тип шрифта. Чуррера использует 64 символа, которые соответствуют кодам ASCII от 32 до 95, вот эти символы:

http://zxaaa.net/store/images/fuente-base-49451.png

Твоя задача заключается в том, чтобы скачать где-нибудь (есть много бесплатных) или нарисовать свой поверх этого рисунка, который ты найдешь внутри архива в файле fuente–base.png. Когда закончишь, то запиши его в /gfx как fuente.png. Очень важно, чтобы сохранялись позиции букв внутри рисунка, потому что в противном случае текст и цифры получатся плохо. Это файл fuente.png, что мы используем в Dogmole:

http://zxaaa.net/store/images/fuente-50291.png

В первую очередь мы займемся реорганизацией нашего тайлсета. Для этого мы «разрежем» каждую плитку на четыре куска 8×8. Каждый из этих кусков соотносится с тем, что мы, спектрумисты, знаем как UDG (User Defined Graphic) и, кроме того, будет нести в себе атрибут связанного цвета. Речь идет о том, чтобы получить нечто подобное для того, чтобы преобразовать его в код С, используя SevenuP:

http://zxaaa.net/store/images/udgs-53111.png

В прошлом мы делали это вручную, и это была сущая морока. На самом деле первым приложением, которое мы сделали для Churrera, было то, которое занималось именно реорганизацией тайлсетов в UDGs. Приложение находится в папке /util в Churrera и называется reordenator.exe. Для того, чтобы его использовать, откроем окно командной строки, зайдем в папку /gfx нашего проекта и напишем следующее:

../utils/reordenator.exe work.png udgs.png

Это заставит reordenator.exe работать, генерируя новый файл udgs.png, который будет в точности таким же, как мы видели выше.

Теперь у нас есть исходник в fuente.png и файлы udg в udgs.png; вернемся к нашему графическому редактору, создадим новый файл размером 256 x 64 пикселей и прикрепим файлы udg под исходником, вот так:

http://zxaaa.net/store/images/tileset-55131.png

Это мы и будем импортировать в нашу игру. Мы сохраняем это в /gfx как tileset.png. Это очень важно, так как SevenuP сгенерирует код, исходя из нашего изображения; структуру данных нужно назвать именно «tileset» – это то, что требуется для Churrera.

Отлично. Сделав все это, наконец, откроем SevenuP и нажмем I для того, чтобы «Importar» («Импортировать»). После этого откроется диалоговое окно выбора файлов, где мы переместимся в папку /gfx нашего проекта и выберем tileset.png. SevenuP его импортирует и преобразует в формат Спектрума.

Теперь нужно сконфигурировать экспорт данных из программ для того, чтобы мы достали набор символов в нужном нам порядке. Для этого мы отправляемся в меню File –> Output Options, который откроет диалоговое окно с множеством опций. Не нужно ничего трогать за исключением Byte Sort Priority, который мы должны будем поставить точно в таком вот виде (нажмите на Char line, а затем на кнопку Move up).

http://zxaaa.net/store/images/opciones_seveup-58031.png

Сделав это, мы жмем OK. Теперь мы будем экспортировать данные: нажимаем на D для того, чтобы «экспортировать Данные», и у нас откроется другое диалоговое окно с выбором файлов. Теперь мы должны проследовать к нашей папке /dev и сохранить в ней файл как tileset.h (нужно будет выбрать «С» в типе файла, так как я думаю, что по умолчанию получится ASM).

Таким образом, SevenuP сгенерирует файл /dev/tileset.h с кодом, необходимым для того, чтобы получить наш charset в игре. В частности, он напишет 8 байтов для каждого из 256 символов плюс 256 байтов с атрибутами их самих.

Выучи это наизусть. Нет, серьезно, я хочу, чтобы ты создал tileset.h самостоятельно. Поэтому я не включил его в архив.

Немного ручной работы
Спокойно, ее будет действительно немного. Вне всякого сомнения, к этому моменту рассказа вы поймете, как функционируют рисунки в Спектруме, и всю тему «colour clash» или наложения атрибутов. Обладая этим знанием, легко понять принцип, почему в Churrera у спрайтов нет собственного цвета, вместо этого они принимают цвет фона.

«Мотор» нарисует экран и потом поставит поверх него спрайты. Если ты был аккуратен, и все плитки, помеченные как «фон», имеют желтый цвет, игра у тебя получится достаточно однородной, и смесь цветов будет не слишком заметна. Проблема заключается в символах, которые состоят целиком из одного и того же цвета. SevenuP достаточно умен, когда дело доходит до выбора двух цветов, которыми обладает каждый символ. Но если у символа только один цвет, то у него ничего не выходит. То, что получается, обычно нам не годится, особенно, в случае Dogmole, в котором плитка 0 фона полностью черная (SevenuP не может добавить цвет “чернил” самостоятельно – прим. пер.). Закодируй атрибуты как PAPER 0 и INK 0, и таким образом спрайты не будут видны. Это нужно выполнить вручную.

http://zxaaa.net/store/images/atributos-00081.png

Открой /dev/tileset.h в текстовом редакторе. Нужно дойти до строки 279. Если твой текстовый редактор не отмечает номер строки, это означает, что тебе, конечно же, надо его поменять на более дружественный. Это первая строка, где определяются атрибуты символов, образующих наш тайлсет. Как ты увидишь, SevenuP форматирует данные в 8 байтов на строку. Это означает, что на каждой строке атрибутов есть цвета двух плиток. Если ты обратишь внимание (и если ты следуешь руководству пользователя с помощью данных Dogmole), SevenuP сгенерирует такую вот строку:

0, 0, 0, 0, 70, 6, 66, 2,

Видишь то, о чем я тебе говорил? Эти четыре нуля – четыре атрибута первой плитки. Итак, теперь поменяем их. Поставим белые чернила, INK 7? Если помнишь, значения атрибутов рассчитываются как INK + 8*PAPER + 64*BRIGHT, так что для того, чтобы поставить PAPER 0, INK 7 и BRIGHT 0, мы должны поменять эти нули на семерки:

7, 7, 7, 7, 70, 6, 66, 2,

На деле мы должны обратить внимание, есть ли где-нибудь другой «0», который нам не нужен, и поменять его. Если ты не придашь этому значения сейчас, поверь мне, ты сделаешь это после создания игры, когда увидишь, как куски спрайтов исчезают после прохождения по определенным местам.

Ладно, уже всё
Хорошо. Если  ты добрался сюда, то, значит, ты прошел первое испытание огнем. Нужно использовать командную строку для выполнения задач с параметрами. Нужно редактировать рисунки, вырезать и вставлять. Нужно использовать приложения преобразования. Нужно осуществлять изменения вручную! Я знаю, что многие из вас подумают: «Эй, это не то, что я себе представлял». Каким бы легким тебе это ни представлялось, для того, чтобы создать игру, нужно приложить какие-то усилия. За всем стоит труд. Первое требование – это наличие желания создать игру, целеустремленность и готовность немного поднапрячься.

И, отбросив в сторону все ненужное, проследуем по этому пути к следующей главе, где мы соберем карту.

Маленькое пояснение
Была пара сомнений относительно темы обычного тайлсета и тайлсета Mappy. Мы приведем несколько примеров для того, чтобы проиллюстрировать данную тему.

Прежде всего, посмотрим на нашего Dogmole Tuppowski.

http://viva-games.ru/game/dogmole-tuppowski

Для того, чтобы получить тайлсет Mappy, просто вырежем первые 16 плиток (верхняя лента) и запишем это как mappy.bmp. Не нужно больше ничего делать, так как первая плитка уже полностью черная.

http://zxaaa.net/store/images/c2re-dogmole-work-02141.png
http://zxaaa.net/store/images/c2re-dogmole-mappy-03061.png

Теперь другой пример. Посмотрим на тайлсет из Cheril of the Bosque. Для того, чтобы получить тайлсет Mappy, вырежем, как всегда, первые 16 плиток, и кроме того мы должны будем оставить первую полностью черной, так как изначально она имеет структуру прикольной травы. Сохраним все как mappy.bmp.

http://zxaaa.net/store/images/c2re-cheril-work-04261.png
http://zxaaa.net/store/images/c2re-cheril-mappy-04471.png

Я думаю, что вы уже схватили суть, но рассмотрим еще один пример. Здесь у меня тайлсет из Viaje al Centro de la Napia. В нем плитка 0 розовая, что нам также не подходит. Вырезаем первые 16 плиток и оставляем розовую плитку черной, записывая то, что получилось, как mappy.bmp.

http://zxaaa.net/store/images/c2re-viaje-work-05551.png
http://zxaaa.net/store/images/c2re-viaje-mappy-06131.png

На сегодня всё.

3

Создай свою собственную игру на ZX Spectrum. Часть 3: Карты

http://zxaaa.net/store/images/mappy-piedro-57431-384x235.png

Первым делом скачайте набор файлов, который нам понадобится для понимания этой статьи. Достаточно только нажать на эту ссылку:

http://www.mojontwins.com/churrera/chur … itulo3.zip (скачать локально: churreratut-capitulo3)

Запускаем карту!
В этой статье мы расскажем вам, как сделать карту. Необходимо будет сконструировать игровой экран, используя плитки, которые мы рисовали в предыдущей главе. Любой экран — это совокупность клеточных сеток, каждая из которых оснащена плиткой. Если быть точным, экраны формируются из плиток размером 15 x 10.

Чтобы изготовить карту, мы воспользуемся Mappy (похоже, что разработчики программы действительно ломали голову над поиском названия для неё). Mappy достаточно проста, работает отлично, и что самое важное, её можно обновлять и дополнять. Та версия Mappy, которую ты загрузил с Мохонии, уже выпущена с двумя дополнениями и обновлениями, что позволяет ей работать так, как мы пожелаем.

http://zxaaa.net/store/images/mappy-24501.png

Прежде чем начать, мы расскажем, как работает Mappy. Она основана на сложном формате,  описывающем карты, который в свою очередь предполагает различные слои, анимированные плитки и множество мелочей. Это родной формат Mappy, который называется fmp, его мы будем использовать для записи копии нашей работы с картой. Уточним, что это копия, которую мы будем загружать в Mappy каждый раз, когда мы захотим что-то отредактировать. Однако этот формат достаточно сложен для импорта в игру, так как обладает множеством дополнений, которые впоследствии нам ни разу не понадобятся.

Нам нужна некая совокупность байт, которая покажет нам, что плитка есть в каждой клеточке карты. Для этого Mappy работает с простым и персонализированным форматом —fmp. Мы его используем только для одной функции — как некую совокупность байт, которая покажет нам, что плитка есть в каждой клеточке карты. Именно в этом формате нужно будет сохранить карту, когда мы захотим сгенерировать копию для дальнейшей обработки и импорта в игру.

Необходимо быть очень внимательным при работе с программой, потому что после обновления и перезаписывания файла мы можем забыть его сохранить в формате fmp. Таким образом при последующем открытии Mappy мы обнаружим, что предыдущие сделанные нами изменения утеряны, и мы не сможем сделать новые. У нас же есть мартышка Colacao, оповещающая нас, когда мы забываем записать fmp, но мы понимаем, что у тебя не будет никакой мартышки, который будет заботиться о тебе, поэтому убедись, что ты сохранил map и fmp после каждого изменения. Пусть в дальнейшем ты не будешь забывать ничего. Не знаю, что для этого можно сделать…Приклей на себе какой-нибудь листочек с напоминанием.

Что же представляет из себя наша игра? Сейчас ты все поймешь, ведь это так просто: нужно только записать файл mapa.map или mapa.fmp и нажать File → Save. Скучно, зато эффективно.

Дадим характеристики нашей карте
В первую очередь мы должны решить, каков будет размер нашей карты. Она не будет больше, чем прямоугольник из N x M экранов. Логично, что чем больше экранов будет у карты, тем больше она будет занимать ОЗУ, то есть оперативной памяти. Следовательно, максимальный размер карты будет зависеть от того, какие характеристики мы придадим движку нашей игрухи. Если это будет простой движок, тогда в памяти поместится много экранов, если более сложный, с дополнениями и усложнениями вроде скриптов, тогда меньше.

Сложно предугадать, сколько максимум экранов поместится в нашей ОЗУ. В играх с простым интерфейсом, с малым количеством наворотов, наподобие Sir Ababol (написана с использованием Churrera версии 1.0 и включает в себя лишь базовые технические характеристики, присущие платформенным играм), помещается 45 экранов, и 3 кб ОЗУ хватает с избытком, поэтому возможно даже бОльшее количество экранов. Однако более сложные игры, например, Cheril the Goddess или Zombie Calavera, занимают почти всю ОЗУ с гораздо меньшим числом карт (24 или 25 экранов соответственно).

Вначале стоит сделать карту маленького размера, этого будет достаточно. Например, в уже упомянутом нами Cheril the Goddess нужно пройти из одного края в другой и оббежать его несколько раз, чтобы постепенно донести предметы к жертвенникам/алтарям. В итоге игра вовсе не будет простой и короткой по времени.

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

В предыдущей статье мы рассказывали о тайлсетах из 16 и 48 плиток, напомню, что задействовав один из экранов, мы тратим половину памяти. Так происходит потому, что используемый формат карты представляет собой пакет, или архив, где в каждом байте хранится по две плитки. Например, одна карта с похожими характеристиками занимает  15 x 10 / 2 = 75 байт на каждый экран. 30 экранов Lala the Magical занимают 2250 байт (30 х 75). Карты из 48 плиток невозможно сохранить таким же самым способом, ведь у них 1 плитка — это 1 байт, то есть каждый экран требует 150 байт. А для 25 экранов Zombie Calavera нужно целых 3750 байт. Видишь, как выгодно задействовать меньше плиток?

Я отдаю себе отчёт в том, что все это безобразие, которое я изложил, тебе малопонятно, однако это такая вещь, которую невозможно прояснить полностью, она познаётся с опытом. Я бы мог начать изучать, сколько байт занимает каждое дополнение Churrera, однако мне никогда не хотелось этого делать. Да, я тебе скажу, что движок, отвечающий за выстрелы, требует много памяти, летающие противники, которые тебя преследуют (Zombie Calavera), тоже достаточно прожорливы. Меньше байт занимают ключи, предметы и плитки, которые несут тебе смерть, различные типы движений (ты ведь можешь летать в Jet Paco, Cheril the Goddess), автоматический прыжок (Bootee). Не так много ресурсов потребуется для того, чтобы толкать блоки, ключи и предметы, о которых мы уже сказали. Различные сценарии (то есть скрипты) тоже могут занимать меньше памяти.

Обрати внимание на число, которое зачастую меняется от 25 до 40 экранов. Также оно может четко вырисоваться на экране. Также ты можешь подождать, пока мы дополним игру каким-нибудь типом сжатия RLE для карт. Вообще мы уже задумывались об этом с самого начала, однако почему-то до сих пор не реализовали эту идею.

Создаём проект в Mappy
Сначала открываем Mappy, идем в  File > New Map и открываем окошко, в котором мы установим необходимые значения нашей карты: размер плиток (16 х 16) и размер карты в плитках (ширину и высоту).

В одном из наших проектов Dogmole Tuppowski карта состоит из 8 х 3 экранов, тогда как в Maria del Mar и Mona их в сумме 24. Мы уже говорили, что каждый экран вмещает 15 х 10 плиток, это означает, что наша карта потребует 8 х 15 = 120 плиток в ширину и 3 х 10 = 30 плиток в высоту. То есть 120 х 30 плиток из 16 х 16. Именно эти показатели мы и должны ввести в открывшемся окошке.

http://zxaaa.net/store/images/mappy-newmap-52261.png

Нажимаем ОК, после чего Mappy выведет сообщение с напоминанием, что теперь мы должны загрузить тайлсет, это мы и сделаем. Идем в  File > Import, нам откроется окно выбора файла. Ищем папку gfx с нашим проектом и выбираем mappy.bmp. Если все сделано правильно, Mappy послушно выгрузит наш тайлсет, который мы увидим на палитре справа, она же и есть палитра наших плиток:

http://zxaaa.net/store/images/mappy-blocks-54061.png

И теперь нам осталось выполнить только одну операцию перед началом работы: нам нужна подсказка, чтобы узнать, где начинается и заканчивается каждый экран. Помните, что края каждого экрана должны включать в себя соседние экраны: если есть какое-нибудь препятствие на правом краю экрана, то должна быть и другая помеха на левой стороне экрана, который находится справа. Иногда это мы забываем, однако будем надеяться, что у вас все будет получаться. Всё внимание на края ??

Разберемся с границами наших экранов. Выбери MapTools > Dividers, чтобы открыть окошко с нужными параметрами. Нажми на Enable Dividers, в поле «Pixel gap x» введи 240, а в «Pixel gap y» — 160. Это и есть размеры наших экранов в пикселях (мы это знаем благодаря Maria del Mar, в которой подсчитали, что 15 х 16 = 240 и 10 х 16 = 160). Нажми ОК, далее ты увидишь, как рабочее окно разделится на прямоугольники с голубыми краями. Да, ты угадал: каждый прямоугольник — это и есть экран игры. Теперь мы готовы к работе!

Здесь мы и будем делать карту. Жмем на палитру с плитками (она находится справа) для выбора той плитки, которой мы будем рисовать. Переносим его на окно слева, образуя новые ячейки, или экраны. Эта работа усердная, медленная и иногда скучная. Советуем не лениться, а строить различные экранчики, хотя они и будут из одних и тех же плиток. Делай так, чтобы твой рисунок получился цельным, нестандартным и разноцветным. Так и ячейки будут более «живыми». Также имей в виду, что у нашего персонажа должна быть возможность дойти до любой точки. Помнишь, мы вначале решили сделать так, чтобы он прыгал вокруг двух плиток в высоту и четыре или пять в ширину? В соответствии с этим и нужно рисовать карту. Еще один нюанс: у нас не должно быть точек, из которых нельзя было бы вернуться назад. Это легко достигается, поэтому можешь быть спокойным.

Так, шаг за шагом создаем нашу карту, которая получится вот такой: (открой файл mapa.fmp из архива к этой статье, чтобы увидеть результат)

http://zxaaa.net/store/images/mappy-editando-56201.png

Учти, что нужно времени от времени перезаписывать карту в нашей папке map как mapa.fmp (File > Save As). Важно, чтобы ты всегда называл ее mapa.fmp, прописывая имя файла вручную. Так все обновления у нас будут в целости и сохранности.

Если в твоей игре есть засовы (плитка 15) или плитки, которые можно передвигать (плитка 14), размещай их где твоей душе угодно. Например, на этом экране мы разместили замочек. Не беспокойся насчет ключей, мы ими воспользуемся позже, когда установим наших противников и необходимые предметы на карте.

http://zxaaa.net/store/images/mappy-cerrojo-57111.png

Если у тебя качества нашего милого Colacao, то ты увидишь, что на карте есть участок (слева вверху), который закрыт для нас. Он относится к Universidad de Miskatonic (Университету Мискатоник). Возможно, ты помнишь, что когда мы продумали сценарий игры, мы уточнили, что Университет будет заблокирован до тех пор, пока мы не удалим всех Магов Ордена Petete, которых Meemaid поставила там для магических операций. Именно они и закрыли Университет, чтобы мы не смогли передвигать коробки. Когда мы дойдём до скриптов, то научимся добавлять код для устранения этого игрового препятствия. Разумеется, все Маги Ордена Petete должны быть мертвы (это осуществляется тоже с помощью скрипта, который очень быстро обновляет карту по нашему усмотрению). А сейчас мы поместим там камень и забудем.

http://zxaaa.net/store/images/mappy-piedro-57431.png
(Здесь проход невозможен. Удалим камень с помощью скрипта.)

Будь внимателен с нажатием клавиш: в игре должен существовать способ выхода из любой ямы. При нажатии на персонажа он прыгает невысоко, поэтому не размещай глубокие ямы (иначе он не сможет выбраться).

Экспорт нашей карты
Когда мы закончим работать с картой (хотя ничего плохого в том, если мы завершим лишь какой-то её фрагмент), нужно будет экспортировать ее в формат map и конвертировать для приложения к нашей игре.

Заходим в File > Save As и сохраняем ее как mapa.map в вышеупомянутой директории map. Да, необходимо сохранить ее как mapa.map. Сделав это, выбери снова File > Save As и сохрани теперь файл как mapa.fmp, набирая буква за буквой mapa.fmp. Серьёзно, сделай это. Обрати на меня внимание. Это выгоднее, чем забывать сохраниться после того, как сделал быстрые изменения в файле. С нами это уже происходило тысячу раз. Серьезно. Обрати внимание на эту милашку с жалостным лицом:

http://zxaaa.net/store/images/borfavo-59351.jpg
Пажааалуста

Превращаем карту в код
Для этого следует обратиться к другой утилите Churrera. Кстати, это вторая программа, которую мы разработали: великая mapcnv. Предназначена для архивов map программы Mappy и деления их на экраны (чтобы движок мог справиться с ними наиболее лёгким способом, сэкономив время и память). Кроме того, если используется тайлсет из 16 плиток, упакуй плитки так, как мы объяснили (по 2 на каждый байт). Так что как только наш файл mapa.map будет экспортирован в директорию map, откроем командную строку и введём mapcnv (который в папке /utils) со следующими параметрами:

..\utils mapa.map ширина_mapa высота_mapa ширина_pant высота_pant tile_замок packed

Объясним по порядку каждый параметр:

mapa.map — это файл нашей карты, сделанной в Mappy.

ширина_mapa — это ширина карты в экранах. В нашем случае это 8.

высота_mapa — это высота карты в экранах. В нашем случае это 3.

ширина_pant — это ширина каждого экрана в плитках. Для churrera всегда равно 15.

высота_pant — высота каждого экрана в плитках. Для Сhurrera всегда равно 10.

tile_замок — это номер плитки, который присваивается замку. Для Сhurrera номер плитки всегда должен быть 15. Если в твоей игре не применяются замки, то выбери любое значение, к примеру, 99. Например, в Zombie Calavera нет замков, следовательно, мы ввели 99. В Dogmole без замков мы не обойдемся, поэтому присваиваем параметру tile_замок число 15.

packed пишется, если наш тайлсет состоит из 16 плиток. При значении 48 ничего писать не надо.

Чтобы конвертировать карту, нужно отредактировать mapcnv следующим образом:

..\utils mapa.map 8 3 15 10 15 packed

Путем этого загадочного и магического процесса мы получим на выходе файл mapa.h, который нужно будет переместить в директорию dev нашего проекта.

http://zxaaa.net/store/images/mapcnv-02401.png

После открытия mapa.h текстовым редактором можно увидеть кучу чисел в фигурных скобочках, использующихся в языке C: это и есть наша карта. Чуть ниже охарактеризованы наши замки, их видно в таком же количестве, которое мы определили для карты. Видишь какие-то отличия? Значит, ты что-то сделал не так и тебе следует перепройти какой-то из этапов.

http://zxaaa.net/store/images/cerrojos-en-mapa-h-03151.png

Отлично. На сегодня мы заканчиваем. В следующей статье мы нарисуем спрайты игры. Узнаем, как нужно создавать спрайтсет и как их конвертировать для использования в нашей игрухе.

Тем временем тебе нужно практиковаться. И вот что мы хотели бы тебе посоветовать: скачай файлы с кодом для наших игр и просмотри карты. Открой файлы fmp программой Mappy и обрати внимание на их особенности.

До следующей встречи!

4

Создай свою собственную игру на ZX Spectrum. Глава 4. Спрайты

http://zxaaa.net/store/images/E20150322_172634_0011-384x224.png

На нашем любимом интернет-портале появился четвертый выпуск мастерской от Mojon Twins (группа разработчиков игр из Испании), посвященный движку Churrera. В этой статье мы научимся создавать спрайты. Если вы читаете эту статью, то у вас уже есть все необходимое, чтобы значительно улучшить свой навык создания игр на Спектруме. Как здорово звучит, да? Что же, а теперь вперед за новыми знаниями!

Глава 4. Спрайты

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

http://www.mojontwins.com/churrera/chur … itulo4.zip (скачать локально: churreratut-capitulo4).

Что такое спрайты?

Если на этом этапе ты не знаешь, что такое спрайт, это не есть хорошо…  Нет, я не буду как обычно говорить, что это газированная вода (хаха, какие мы остряки). Тем не менее, так как эта глава о спрайтах,  нужно начать с объяснения, что же это все-таки такое. Если ты этого не знаешь, то это говорит о плохом качестве обучения видеоиграм. Не важно, какого уровня обучающие материалы или о какой системе рассказывают: объяснить, что такое спрайты – обязательно. Того требует его  преосвященство Пако Пералес, отец всех туториалов.

Сама идея спрайта, в действительности, не имеет абсолютно никакого смысла в системах типа Спектрума, в которых вывод графики ограничивается матрицей. Абсолютно никакого смысла. Однако спрайт можно использовать по аналогии. Обычно, графический чип, спроектированный для использования в играх, управлял двумя объектами  – фоном и определенным количеством спрайтов. Спрайты были не более чем несколькими пикселями, обычно квадратной или прямоугольной формы, которые графический процессор компоновал поверх фона и посылал изображение на экран монитора или ТВ. Речь идет о символах, находящихся далеко от фона, и которые, следовательно, можно было перемещать без воздействия на сам фон. Центральному процессору просто нужно было «сказать» графическому процессору где находится каждый спрайт и забыть об этом, так как GPU сам заботился о том, чтобы  построить изображение, посылая на монитор пиксели спрайта вместо пикселей фона когда было нужно. Картинок  как будто там и нет, и отсюда их название: слово «спрайт» означает «феи» или «эльфы».

http://zxaaa.net/store/images/sprite-de-una-llama-57241.jpg

Почти все видеоконсоли 8 и 16-ти битные (по крайней мере, Нинтендо и Сега, Атари редко), например, MSX и Commodore 64, имели графический процессор, с которым можно было использовать фоны и спрайты.

В компьютерах типа Spectrum, Amstrad CPC или PC, концепт спрайта не имеет смысла. Почему? А потому, что только железо управляет матрицей, то есть, можно сказать, управляет фоном. В этом случае, нужно научить процессор «закрашивать» фон спрайтами: заменить определенные пиксели фона на пиксели картинок. Кроме того, программист должен уметь перемещать картинки: восстанавливать экран до того состояния как было до картинок и перерисовывать их на новое место. Тем не менее, по аналогии, эти картинки называются спрайты.

Мы их называем спрайтами, и это при том, что мы пуристы.

Спрайты на движке Churrera

У Churrera 4 спрайта 16×16 пикселей для персонажей (включая персонажа, которым управляет игрок) и до 3 спрайтов для снарядов (в «убивалках»). Спрайты для персонажей нарисованы графикой, которую мы знаем под названием spriteset  (спрайтсет).  Спрайтсет содержит 16 скриптов, из которых 8 используются для анимации главного персонажа и еще 8 для анимации 4 типов врагов (2 врага для каждого главного персонажа, если вы дружите с математикой). Спрайтсет примерно выглядит так (это спрайтсет для игры Dogmole):

http://viva-games.ru/game/dogmole-tuppowski

http://zxaaa.net/store/images/sprites-dogmole-59481.png

Как видишь, у картинки всегда есть графика, а справа от нее находится странное изображение, одинакового размера с картинкой. Мы сейчас объясним, что же это такое. Это называется «маска». Да, я знаю, что на маску это никоим образом не похоже, но, тем не менее, такое у нее название. Компьютерные мышки тоже не похожи на настоящих мышек, но никто не жалуется. Маска используется для того, чтобы указать графической библиотеке (в данном случае, splib2), что она отвечает за движения спрайтов (поскольку на Спектруме не существует графического чипа, который бы это делал), и что пиксели изображения «прозрачные», то есть, пиксели изображения не должны заменять пиксели фона.

Если бы не существовало маски, все спрайты были бы квадратные или прямоугольные, и это смотрелось бы некрасиво.

Мы расположили наш спрайтсет таким образом, чтобы каждая графическая картинка имела свою маску справа от себя. Можно заметить, что маски содержат черные пиксели в тех местах, где должна быть сама картинка, и цветные пиксели там, где должен быть фон. Мы назвали это силуэтом.

Зачем нужны маски? Проявив немного проницательности, ты сможешь догадаться: в Спектруме графика 1-битная, то есть, 1 пиксель представлен 1 битом. Таким образом, пиксели могут находиться только в двух состояниях:  живые или потухшие (1 или 0). Чтобы определить какие пиксели являются прозрачными, нам нужно 3-е состояние, но это невозможно (есть у бинарной системы). Поэтому нам нужна отдельная система для этой информации – маска! маска!

Создавая собственный спрайтсет
Перед тем как создать спрайтсет, очень важно понимать, какой будет наша игра – с боковой перспективой или «генитальной», как мы тут это называем. Могу предположить, что раз мы дошли до этого пункта, то это уже решено (может у нас уже и карта есть). Порядок скриптов в спрайтсете зависит от типа нашей игры.

Спрайтсеты игры с боковой перспективой
Для игр с боковой перспективой 16 иконок 16×16 (вместе с масками), из которых состоит спрайтсет, должны иметь следующий порядок:

Последовательность спрайтов для игр с боковой проекцией

http://zxaaa.net/store/images/tablicaaaa1.png

Как мы видим,  первые 8 позиций служат для анимирования, движения главного персонажа: 4 для того, чтобы смотреть направо, и остальные 4 – налево. У нас 3 основных движений персонажа: стоять, идти и прыгать/падать.

Стоять: Используется, для остановки персонажа. Это означает, что персонаж не двигается сам (если его перемещает другое существо, то персонаж все равно находится в состоянии «стоять»). Когда персонаж останавливается, движок закрашивает его, используя кадр 2  (номер 1, если смотрит направо или номер 5, если налево).

Идти: Когда персонаж двигается по поверхности. В этом случае мы используем анимацию 4 пунктов – 1, 2, 3, 2. в этом порядке (0, 1, 2, 1… если смотрим направо или 4, 5, 6, 5… если смотрим налево). Чтобы закрасить его, персонаж должен стоять на поверхности 2 ногами для пункта 2 и с расставленными ногами (правая или левая нога впереди) в фреймах 1 и 3.  Поэтому используем фрейм 2 для «стоять».

Прыгать/падать: Когда персонаж прыгает или падает. Движок закрашивает фрейм «в прыжке» (пункт 3, если смотрим направо и пункт 7, если налево).

Следующие 6 позиций для представления «врагов». Враги могут быть 3 типов, и у каждого 2 фрейма для анимации.

Два последних пункта служат для подвижных платформ, у которых также 2 фрейма для анимации. Подвижные платформы, как это понятно по их названию, это площадки, которые двигаются. Главный персонаж может взбираться на них и двигаться по ним. Чтобы зарисовать это изображение, нужно позаботиться о том, чтобы площадка, на которую нужно поставить персонажа, достигала верхнего края изображения.

Вот несколько примеров для ясности:

http://zxaaa.net/store/images/sprites-cheril-11261.png

Этот спрайтсет относится к игре Cheril Perils. Как мы видим, 8 изображений относятся к Cheril, сначала смотрят направо, а затем налево.

У нас также еще есть 3 врага в игре. Хорошо разберитесь в том, как анимировать  движения персонажа, представьте, что вы уже прошли от 1 фрейма ко 2-му, от 2 к 3-ему, от 3 ко 2-му, и от 2 к 1-му. Посмотри на изображения и представь их у себя в голове. Ты видишь это? Видишь, как двигаются персонажи? Туда-сюда, туда-сюда… Разберись также в том, почему именно фрейм 2 лучше использовать для остановки картинки.

http://zxaaa.net/store/images/sprites-monono-13331.png

Это другой спрайтсет к игре Monono. У нас также 8 иконок для Eleuterio (каким важным он получился), 3 типа врагов и в конце подвижная платформа. Обрати внимание на то, чтобы поверхность подвижной платформы касалась верхнего края квадрата спрайта. Также посмотри на то, как сделана анимация движения персонажа Eleuterio, как голова опускается ниже в тех фреймах, где расставлены ноги. Это придает персонажу озорной вид.

Спрайтсеты игры с «генитальной» перспективой
Для игр с этой перспективой, позиции должны идти в таком порядке:

http://zxaaa.net/store/images/tablicaaaa2.png

И снова – первые 8 пунктов служат для анимации главного персонажа, но на этот раз все более упрощенно: так как у нас всего 4 направления, в которых персонаж может перемещаться (вверх, вниз, направо, налево), то, получается, у нас только 2 фрейма для каждого направления.

8 других пунктов относятся к типам врагов, и в играх этого типа нет подвижных платформ, которые бы представляли ценность.

Еще раз для полной ясности картины рассмотрим несколько примеров:

http://zxaaa.net/store/images/sprites-hobbit-16551.png

Это спрайтсет для нашей гениально преобразованной игры Hobbit (продержалась дольше всех, что составляет нашу особую гордость). Заметь, как тут все поменялось: вверху у нас 8 скриптов с 2 фреймами для каждого направления движения, и внизу 4 типа врагов вместо трёх и платформы.

http://zxaaa.net/store/images/sprites-mega-meghan-17581.png

Этот спрайтсет из Mega Meghan. Здесь у нас снова 4 возможных направления движения у главной героини (Meghan – злобная убийца) с 2 фреймами анимации для каждого направления в верхней части, и еще 4 у женщин-врагов на нижней части.

Обрати внимание, как мы в этом случае воспользовались преимуществом «генитальной» перспективы: когда персонажи идут вверх, они поворачиваются спиной, и когда идут вниз, то могут смотреть вперед. Это суперзабавно.

Закрашивая наш спрайтсет
Нет ничего легче, чем создать новый архив на 256 x 32 пикселей, запрятать нас за решетку и закрасить спрайты. Нам нужно запомнить всего одно простое правило (или два, посмотрим). Чтобы закрасить спрайты и маски используем 2 цвета:

В спрайтах черный цвет – это цвет из палитры Paper, и другой цвет (мы его любим, использовать белый – хорошая идея) – это цвет из палитры INK. Запомни, что спрайты всё равно возьмут цвет тех плиток, которые находятся на заднем фоне.

В масках черный является частью графики, которая должна оставаться сплошной, и какой-нибудь другой цвет служит для обозначения прозрачных частей  (через которые вы видите фон).

На примерах наших работ, ты увидишь, что мы используем другой цвет (помимо черного) в спрайтах и масках. Ты можешь использовать любые цвета. Я лично использую разные цвета, потому что обычно закрашиваю спрайт и маску в иконке 16×16, чтобы потом выбрать пиксели цвета «маски» и переместить их в следующую иконку. Этот прием ты можешь использовать, если хорошо знаком с графическими редакторами.

Когда наши спрайты и маски закрашены и находятся в архиве спрайтсета, сохраняем их как sprites.png в gfx, и мы готовы к тому, чтобы конвертировать их в код языка С, который использует движок Churrera.

И снова хочу указать на то, чтобы ты использовал тот самый черный цвет. Все черные пиксели должны быть в RGB = (0, 0, 0).

Конвертируем наш спрайтсет
Теперь осталось поработать немного с окошком командной строки. Будем использовать еще одно преимущество Churrera, которое, как вы уже догадались, будет третье по счету: sprcnv.exe, конвертор спрайтсетов. Польза от этого преимущества небольшая, так как есть всего 2 параметра. Идём в /gfx и выполняем:

..\utils\sprncv.exe sprites.png ..\dev\sprites.h

Применяем, и после таинственного процесса получаем архив sprites.h в нашей папке dev. И на этом заканчиваем.

Черт возьми, уже?
Да, дружок. Тема спрайтов была довольно простой, по крайней мере, я в это верю. Если тебе кажется, что что-то осталось неясным, ты уже знаешь что делать: не жаловаться. Да, это шутка. Можешь в этом случае просто спросить нас. Но тебе придется умолять.

В следующей части мы расскажем о статических экранах: заставке, контексте игры и финальном экране. Но до следующей встречи вы должны закончить со спрайтами!

5

Создай свою собственную игру на ZX Spectrum.
Глава 5: Завершение графики (пока что)

http://zxaaa.net/store/images/dogmole-ending-55591.png

У нас уже готова для вас глава 5 семинара “Создай свою собственную игру на Спектруме”. Сегодня мы закончим графическую часть и начнем работать, кроме прочего, над стартовой и финальной заставкой игры. Как обычно, надеемся, что вам понравится, и вы найдете, что вынести для себя из этого урока.

Глава 5: Завершение графики (пока что)

Прежде всего, скачайте соответствующие материалы для этой главы, нажав на ссылку ниже:

http://www.mojontwins.com/churrera/chur … itulo5.zip (скачать локально: churreratut-capitulo5)

Чего нам не хватает?

Осталось нарисовать уже не так много. В этой главе мы объясним две вещи: сначала, как менять дополнительные спрайты (взрыв и пуля). Затем посмотрим, как создавать, конвертировать, сжимать и включать части игры, стартовый и финальный экраны.

Дополнительные спрайты
В принципе, мы не планировали разговаривать в этом семинаре/обучении на тему замены дополнительных спрайтов по очень простой причине: с тех пор, как мы создали взрыв для Cheril Perils и пулю для Zombie Calavera, мы их не поменяли ни на пиксель.  Да, нам хватило наглости создать все последующие игры со взрывами и пулями, не изменив эту графику. Но раз уж мы заметили в ваших рядах интерес к гиперкастомизации, займем-ка мы несколько параграфов объяснениями, как их поменять. Но предупреждаем: придется хорошенько выпачкать себе руки, занимаясь этой грязной работой.

http://zxaaa.net/store/images/piojo-39321.png
Это Пи-глаз (у него 3,14 глаз)

Разумеется, если в твоей игре нет пуль и врагов, по которым можно потоптаться, или если тебе дороги те, что уже есть, то можешь просто сбежать от этих объяснений, как последний засранец.

Итак. Чтобы поменять эту графику, что мы должны сделать, так это заменить ту, что прописали в файле Чурреры \dev\extrasprites.h. Для начала откроем архив в нашем не самом примитивном текстовом редакторе  и глянем, что там есть. В этом архиве  колбаски цифр используются для определения трех видов графики для спрайтов (и их масок): числа 17, 18 и 19. Число 17 как раз и соответствует взрыву. Число 18 – свободный спрайт, который использует мотор, когда не хватает одного из трех врагов, которые умещаются на экране, или для вспышек и других вещей, которые я сейчас не помню. Здесь мы, конечно, ничего менять не будем. Число 19 – спрайт пули, и он самый маленький (увидишь, что есть более маленькие цифры).

Изменение взрыва

Взрыв – это спрайт размером 16 х 16 (осторожно, пестиньо! (очередной подвид чуррос)). По правилам построения splib2, чтобы определить спрайт 16 х 16, отправляем его в верхнем левом угле размером 24 х 24. Именно поэтому splib2 работает с символами, и квадрат 24 х 24 на языке Си всегда может вместить целиком спрайт размером 16 х 16. Не волнуйся, если это выглядит, как китайская грамота,  понимать это необязательно (но если тебе любопытно, у нас всегда можно спросить). Мы говорим об этом, только чтобы ты сориентировался и знал, что мы собираемся менять. В архиве ты увидишь 3 колбаски чоризо из 24 строчек цифровых пар, каждая из них под этикеткой ._sprite_17_X, где х – это a, b или с. Это 3 колонки из 24 строчек по 8 пикселей, которые составляют наш спрайт, и как раз те данные,  которые мы должны заменить. Размести их в архиве.

Следующий шаг – создать свободный тайлсет (архив png 256 x 32) и нарисовать первую клетку взрыва и его маску. Вот так:

http://zxaaa.net/store/images/nueva-explosion-42231.png

Когда все сделано, сохраняем архив как \gfx\extra.png и кодируем его, используя sprcnv, как объясняли в прошлой главе, но в этот раз, указывая extra.h в качестве исходного архива:

..\utils\sprncv.exe extra.png extra.h

Всё это нам создает архив extra.h в \gfx. Открываем этот архив в текстовом редакторе.

Этот архив содержит определения 16 спрайтов. Нам нужен только самый первый из этих спрайтов, чтобы его вырезать и вставить в extrasprites.h, заменив на 17. Вот что делаем: выделяем 3 колонки спрайта 1 (выделенные этикетками ._sprite_1_X, где х – это a, b или с) и копируем их в буфер обмена.

Теперь переходим к extrasprites.h, удаляем три колонки  ._sprite_17_X, вставляем три колонки  ._sprite_1_X из буфера обмена, и теперь, спокойненько меняем все этикетки  ._sprite_1_X на  ._sprite_17_X.

Отлично! Делай это оооооочень медленно. Проверь, что сделал все правильно, переименовал корректно все этикетки.

http://zxaaa.net/store/images/code-seleccion-45571.png

Изменение выстрела

Оригинальный выстрел – это шарик, расположенный по центру ячейки 8 х 8. Мы используем шарик, потому что он подходит для выстрелов во всех направлениях: ориентированная в пространстве форма нам не подойдет.

Так же как и с графикой 16 х 16, определяем его в больший квадрат 24 х 24 для позиционирования на экране, определяем ячейку 8 х 8 в квадрат 16 х 16 или, что то же самое, в две колонки из 8 х 16 пикселей.

В архиве extrasprites.h находятся колбаски чоризо под этикетками ._sprite_19_a и ._sprite_19_b.

Чтобы быстрее дошло – у пуль нет масок. Это значит, что графика определяется первой величиной в восьми первых линиях. Как видим ниже, эти значения 0, 0, 24, 60, 60, 24, 0, 0.

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

00000000
00000000
00011000
00111100
00111100
00011000
00000000
00000000

Мы его поменяем, например, на звёздочку ниндзя (друзья, немножко воображения!):

00000000
00010000
00011000
00100110
01100100
00011000
00001000
00000000

Можем перенести числа в десятичный формат и заменить их, но это не нужно делать, потому что ассемблер z88dk – компетентный парень  (как и Винсент, умная обезьянка) и проглатывает сразу бинарный код, если перед ними поставить @, и таким образом заменим первые цифры восьми первых пар значений, под этикеткой ._sprite_19_a :

http://zxaaa.net/store/images/code-estrella-ninja-47321.png

Блин, чувак, какой бардак!
Да, старайся ничего не менять. Уже жалеешь, что спросил? Скорее всего, ты сейчас уже думаешь, что взрыв и пуля в изначальной версии в итоге не так уж и плохи.

Фиксированные окна
Ну что, переходим на тему фиксированных окон. В принципе, игры на Чуррера имеют три фиксированных окна: начальная заставка, которая показывает, помимо прочего, и меню (чтобы выбрать тип управления и начать игру), экран маркировки игры, где расписаны индикаторы жизней, объектов и прочих вещей, и финальная заставка, которая появляется, когда игрок выполнил поставленную цель.

Чтобы сэкономить память, к тому же есть возможность соединить начальную заставку и заставку с маркировками, благодаря чему экономим кучу памяти – и это опция, которую мы выбрали для нашей игры Dogmole.
http://viva-games.ru/game/dogmole-tuppowski

Но не волнуйся, мы все объясним.

И еще вещь, которую надо упомянуть, это что экраны хранятся в игре в сжатом формате. Используемый тип сжатия (как практически и любое сжатие) работает лучше с простыми изображениями. Другими словами: чем больше повторений и/или меньше объектов в окнах, тем меньше используется памяти. Не забывай об этом. Если у тебя заканчивается память, один из отличных способов – это сделать так, чтобы твои фиксированные окна были меньше наполнены.

Начальное окно

Как уже говорили, речь идет об окне, которое показывает название игры и настройки управления. Выбор управления тоже фиксированный: если игрок нажимает 1, выбирает управление клавиатурой. Если нажимает 2, выбирает Kempston, если 3, то это для игры джойстиком Sinclair (интерфейс 2, порт 1). Что бы это могло значить? Просто рисуем экран, который кроме названия игры, показывает и эти три опции. Например, как-то так:

http://zxaaa.net/store/images/vacdln-title-49281.png

Когда нарисуешь свое окно, сохрани его как title.png в директории \gfx.

Окно маркировки игры

С этого места наконец начинается мужской содержательный разговор.  Экран маркировки игры должен иметь различные важные зоны и отдельные места с орнаментом и индикаторами. Вот зоны, которые мы должны подготовить:

Зона игры, где, собственно, все и происходит. Как ты уже догадался, это окно должно быть такого же размера, как и другие наши окна. Если помнишь, наши окна размером 15 х 10 тайлов и, следовательно, занимают 240 х 160 пикселей. Ты должен зарезервировать зону этого размера для основной игровой области.

Индикатор жизней/энергии/ жизнеспособность / что-то еще: 2 цифры, нарисованные тем шрифтом, который ты выбрал, когда рисовал тайлы.  Надо его разместить где-то, добавив что-нибудь, означающие графики. Мы обычно рисуем фигурку нашего героя и «Х», как видишь на примерах.

Индикатор ключей (если используешь ключи в игре). Все делается так же, как и для индикатора жизней.

Индикатор объектов (если используешь объекты в игре): и снова то же самое для объектов.

Индикатор убитых врагов (если врагов можно убивать и важно их считать). Точно так же.

Все эти штуки можно разместить где вздумается, главное, чтобы они были вписаны в одну строку. После мы должны определить место каждой из этих штук (в координатах это 0, 31 для Х и 0, 23 для Y), чтобы это место было указано в настройках Чурреры (как мы обсуждали в нескольких главах ранее).

Рассмотрим это на примере. Это окно маркировки игры Lala Prologue. Мы видим различные элементы. В этой игре у нас есть ключи, а еще надо собирать объекты, поэтому нам надо указать оба индикатора, в плюс к индикатору энергии – и вот что мы видим:

http://zxaaa.net/store/images/lala-marco-52401.png

Игровая зона, как видим, начинается в координатах x = 1, y = 2, т.е. (1, 2).

Область, которую мы оставили для индикатора энергии, находится на (4, 0).

Индикатор объектов появился на (11, 0).

И, наконец, индикатор ключей – на (18, 0).

Как я уже говорил в нескольких главах, надо указать все эти значения при создании конфигурации нашей игры.

Когда создашь свое окно, сохрани его как marco.png в директории \gfx.

Совмещенные стартовое окно и окно маркировки игры
Прежде всего, мы начали это делать, чтобы сэкономить уйму памяти. Тема очень простая: к окну маркировки игры добавляем название и опции меню прямо внутри основной игровой зоны.  Решение здоровское и, повторюсь, экономит кучу памяти.

Что мы и сделаем для нашей игры Dogmole, как видно ниже:

http://zxaaa.net/store/images/dogmole-title-54241.png

Как видим, тут и название игры, и настройки управления, о которых мы говорили в части, посвященной начальному окну. Игровая зона, как видно, появилась под зоной, занятой названием и настройками управления:

Игровая зона находится в координатах (1, 0).

Счетчик убитых врагов (колдунов) появился на (12, 21).

Счетчик коробок (или объектов) нарисован на (17, 21).

Счетчик жизней – на (22, 21)

И, наконец, счетчик ключей у нас на (27, 21).

В этом случае совмещенное окно названия / маркировки сохраняется как title.png в \gfx.  Архива marco.png для игр, имеющих совмещенный экран названия / маркировки, у нас не будет, как видим на примере Dogmole.

Финальная заставка
Это окно, которое появляется,  когда игрок успешном завершил игру. Здесь никаких ограничений: рисуй все, что вздумается!  Лучше с юморком, но если тебе нравятся серьезные игры, никто не мешает. Это финальная заставка Dogmole:

http://zxaaa.net/store/images/dogmole-ending-55591.png
Дерьмо, задница, проклятье!!!

Когда все сделано, сохраняем его как ending.png в директории gfx.

Конвертация окон в формат Спектрум
Для этого снова воспользуемся  замечательнейшим SevenuP.  Можешь использовать и другие программы, но раз уж у нас уже есть SevenuP, им и воспользуемся, да? Начинаем, запускай SevenuP. Как открыли, нажимаем кнопку I (импортировать). В открывшемся окне выбора архивов ищем наш title.png. SevenuP сохранит архив и переведет его в формат окна Спектрум. Нажимаем S, чтобы сохранить, и отправляем его в \gfx под кличкой title.scr.

Проделываем то же самое с marco.png (если его используем) и ending.png. В конце концов, остаемся с title.scr, marco.scr (если его используем) и ending.scr в \gfx.  Не будь простофилей и не удаляй png, чтобы потом можно было что-то поменять или использовать в другой игре (хе-хе-хе).

Сжатие окон
Как ты возможно уже сообразил, 6912 байта, необходимых на каждый экран, умножить на 3 (или 2) – получится ого-го, и поэтому будем их сжимать. Для этого используем компрессор apack.exe из пакета в библиотеке aplib. Спокойно, мы его включили в папку utils. Открываем наше командное окно, идем в директорию gfx и сжимаем каждый из наших трех (или двух, если не будешь использовать отдельно маркировку игры) файлов scr в архив с тем же названием, но с bin на конце.

..\utils\apack.exe title.scr title.bin

..\utils\apack.exe marco.scr marco.bin

..\utils\apack.exe ending.scr ending.bin

В итоге получаем три (или два) архива .bin, которые скопируем в папку \dev.

Наблюдаем, как вес архивов стремительно уменьшается. В случае Dogmole, title.bin занимает 1277 байтов, а ending.bin1084 байта. Что значительно меньше,  чем 13824 байта до сжимания.

На этом всё
Что, уже? Это была скучная глава. Знаю. Но, блин, все же нужная. В следующей главе научимся размещать врагов, объекты и ключи на игровой карте. И скоро, очень скоро, сможем в первый раз все собрать вместе, чтобы увидеть, как оно работает.

6

Создай свою собственную игру на ZX Spectrum.
Глава 6: Размещение объектов

http://zxaaa.net/store/images/mapa-38201-384x203.jpg

Новая часть семинара “Создай свою собственную игру на Спектруме” на Чуррера от Mojon Twins. В этой части мы начнем располагать на карте отдельные элементы, которые мы до этого создавали. Без дальнейших отступлений, переходим к делу.

Глава 6: Размещение объектов

Прежде всего, скачайте соответствующие материалы для этой главы, нажав на ссылку ниже:

http://www.mojontwins.com/churrera/chur … itulo6.zip (скачать локально: churreratut-capitulo6).

А что теперь?

А что теперь?
А вот теперь-то мы начнем размещать объекты. Это похоже на тот момент, когда, вернувшись из супермаркета с набитыми сумками, ты должен распихать их содержимое по кухне. Это утомительный, но нужный процесс. Конечно, ты можешь этого и не делать, но тогда посмотрим, кому все же удастся найти сосиски. Или, например, фильтры для кофе. Кто-нибудь еще использует фильтры для кофе?

В принципе мы должны просто разместить на карте врагов, объекты и ключи. И нет, мы предлагаем сделать не совсем это:

http://zxaaa.net/store/images/mapa-38201-384x203.jpg

Каждый объект относится к конкретному окну и имеет серию значений, которые указывают на его позицию, тип, скорость, если это подвижный объект, и другие характеристики. На самом деле, мы говорим об огромной таблице цифр, которая становится занозой в заднице, если создавать ее вручную. Поэтому мы создали кривенькое приложение, чтобы выполнить эту работу в визуальной форме.

Инструмент, о котором мы говорили, и который назвали с большой долей воображения Разместитель (Colocador) – и это никак не связано с запрещенными препаратами – Разместитель помогает не только при создании игр в Чуррера. Каждый проект с использованием тайлов размером 16 х 16 пикселей для любого размера окна может быть сделан с помощью этого приложения. Чтобы не углубляться, скажем, что использовали его для размещения багов в таких играх как Uwol 2 под CPC и Lala Prologue под MSDOS, а также для экспериментального создания чего-то в какой-то 16-битной консоли, чтобы в один прекрасный день  добраться до конца и все окончательно бросить. Да, программа выглядит корявенько, но все же отлично нам поможет.

[Режим сталкера] Конечно, Разместитель – программа для платформ, работающих на Windows. Однако, при ее использовании с gcc и применении Allegro в качестве графической библиотеки, ее довольно просто перевести под Linux. Если ты готов это сделать и таким образом предоставить пользователям этой платформы еще одно приложение, свяжись с нами. Программа дополнительно содержится в файле .с, так что создать exe-шник под Linux должно быть самой простой задачей на планете.

Базовые понятия: враги и хотспоты
Для начала объясним некоторые базовые понятия, прежде чем начать издеваться над программой размещения, прежде всего потому, что названия, которые мы будем использовать, не настолько интуитивно понятны, как управление в Uchi-Mata.

http://zxaaa.net/store/images/kimono-41121.jpg
А моё кимоно? Кия-ааа! – Оно грязное! Кия-ааа! (AAA -тут употреблено случайно!)

Враги

Начнем с понятия «враги». В Чуррера враг – это те штуки, которые перемещаются по игровому окну и тебя убивают, а еще это подвижные платформы. Да, в Чуррера подвижные платформы – тоже враги. Поэтому когда мы говорим о расположении врагов, мы говорим также и о расположении подвижных платформ. И когда говорим, что в окне могут разместиться максимум 3 врага, считаем также и подвижные платформы. Мы бы могли назвать их, например, «мобильные», но они пришли нам на ум, когда мы уже запустили движок, и Амадор, наша обезьянка-программист, отказалась их переименовывать.

Враги имеют различные связанные с ними значения, но что еще важнее – тип. Тип врага определяет его поведение и, как следствие, графику, которой он обозначается. Будьте внимательны, потому что здесь все малость запутано, т.к. что это не было создано априори, а запатчено (см. выше про подвижные платформы):

Врагов типов 1, 2 и 34 в играх генитального типа) описывают линейные траектории, и они обозначаются первым, вторым или третьим (и четвертым) спрайтом врага тайлсета. Когда мы говорим о линейных траекториях, это относится к 2 возможным вариантам:

Траектории прямолинейные: вертикальные и горизонтальные: определяются начальная и конечная точка, соединенные прямой вертикальной или горизонтальной линией. Враг следует этой воображаемой линии туда и обратно без конца.

http://zxaaa.net/store/images/lineal-42001.png
Начало <–> конец

Диагональные траектории: Они появились из-за «фичи» движка (побочный эффект, получившийся из-за кривого алгоритма), но мы его оставили, потому что нас торкнуло. Мы реально часто использовали эту опцию. Если начальная и финальная точки не находятся на одной строчке или в одной колонке, персонаж перемещается по прямоугольнику, который создают эти точки, отскакивая от его углов и двигаясь по диагонали.

http://zxaaa.net/store/images/diagonal-44361.png
Чё творишь, псих?

Враги четвертого типа, когда используется боковой вид, это подвижные платформы. Они ведут себя точно так же, как и линейные враги, но с одним ограничением: хотя им и можно задать диагональную траекторию, мы не можем гарантировать, что это будет работать правильно во всех случаях. Поэтому можно использовать только горизонтальные и вертикальные траектории.

Враги пятого типа были добавлены, когда мы делали Zombie Calavera. Это тип летучих мышей. Они обозначаются графикой третьего врага тайлсета и имеют особенное поведение: появляются вне экрана, и, если персонаж не спрятался, преследуют его. Если  персонаж спрятался, они пролетают мимо и исчезают с экрана. Мы не пробовали этот тип врагов в обновленной версии Чуррера, поэтому не можем утверждать, что они здесь будут работать.  Решишься попробовать? По умолчанию код для перемещения и управления врагами пятого типа не включен в движок, поэтому его нужно активировать отдельно.

Враги шестого типа не включены в эту версию Чурреры по одной простой причине: они всегда и полностью кастомизируются. В Cheril the Goddess это были слепые летучие мыши, которые тебя преследовали, только если ты приближался к ним на определенное расстояние, а когда отдалялся – возвращались на свое место. В игре Ramiro el Vampiro – это летучие мыши из склепа, которые появляются, когда активируешь люк, и тебя преследуют, пока ты не соберешь все кресты. В Uwol 2 под CPC,  это Fanty на низших уровнях. Для каждой игры, в которой мы использовали шестой тип, мы планировали новое поведение (заново используя отдельные элементы, конечно). Для этого мы оставили эту «лазейку», если нужно кастомизировать поведение для какой-нибудь игры, у нас есть, где это сделать. На этом же движке, даже если ты  создашь врага шестого типа, на экране ничего не появится.

Врагов седьмого типа мы называем НДВ или Невероятно Доставучие Враги. Это линейные преследователи. Эти враги появляются в той точке, которую ты задаешь для начала преследования игрока. Они не могут пересечь сцену. Если игрок может в них стрелять и убивать, они через некоторое время снова появляются в том же месте, где они появились в первый раз. Графика для этих персонажей выбирается наугад из доступных рисунков. Они лучше всего работают в играх с генитальным видом, и ты можешь увидеть их в работе в  Mega Meghan. Так же как и для врагов пятого типа, код для их управления не включен в этот движок по умолчанию, это надо делать отдельно.

http://zxaaa.net/store/images/mojon-twinsmega-meghan-20130611a_48121.png

Мы же будем использовать в Dogmole только врагов 1, 2 и 3 типа, а также подвижные платформы четвертого типа.

В заключающих главах этого учебника, в которых будем говорить о дополнениях и модификациях, увидим, как делать следующие две вещи с движком: добавить шестой тип с кастомизированным поведением и как изменять весь движок врагов, чтобы использовать больше четырех линейных базовых типов: использовать 8 различных типов с анимацией (с использованием кучи памяти в процессе создания). Но до этого еще придется дожить. Рано еще заводиться, не устраивайте бардак!

Хотспоты
Хотспоты (горячие точки) – это, проще говоря, точки в окне, где могут быть размещены предметы, ключи и дополнительные жизни. В каждом окне определяется только один хотспот. Каждый хотспот связан со своими величинами. Если у него значение «0», он будет неактивный, и в нем ничего не появится. Если дашь ему значение «1», то в этом месте появится предмет. Если дашь ему значение «2», то тут будет ключ. Хотспоты со значениями «1» или «2» считаются активными. Когда мы забираем  предмет или ключ с активного хотспота, движок может разместить здесь дополнительную жизнь в следующий раз, когда мы вернемся на это окно.

Когда мы говорим о предметах, мы говорим об объектах, которые начинаются с тайла с номером 17, и который автоматически считается движком игры без дополнительных действий с нашей стороны, кроме как указать ему, что мы используем предметы. Это могут быть зелья в Lala Prologue или кресты в Zombie Calavera, карандаши в Viaje al Centro de la Napia или дискеты в Trabajo Basura. В нашей игре мы будем использовать предметы, чтобы изобразить ящики, которые надо собрать и доставить в университет Мискатоник. Затем, через скрипты и конфигурацию, сделаем, чтобы поведение предметов было особенное (предмет не засчитывается, пока, подобрав его, не оставишь его в определенном месте университета – это очень похоже на то, как работают дискеты в игре Trabajo Basura), но обычно речь идет об объектах, которые надо разместить на карте, используя хотспот первого типа объекта.

Я знаю, что ты собирался у меня спросить: нет, в одном окне не может быть больше одного хотспота, так как это прописано в движке.

Подготовка необходимых предметов

Итак. Закатаем рукава и примемся за работу. Первое, что нам нужно сделать, это скопировать нужные материалы в директорию, где находится Разместитель, т.е. в директорию \enems. Нужно две вещи:  карта игры в формате .map и тайлсет для Mappy в формате .bmp. Для этого копируем \map\mapa.map и \gfx\mappy.bmp в \enems. К марш-броску готовы!

Конфигурация нашего проекта
Когда запускаешь Разместитель (например, дважды кликнув на colocador.exe), появится главное окно, в которое загружаем существующий проект или конфигурируем новый. Т.к. у нас нет существующего проекта, создаем новый.

http://zxaaa.net/store/images/colocador-config-52271.png

Как видим, в первых двух ячейках нужно ввести имя нашей карты и тайлсета (mapa.map и mappy.bmp, которые должны быть в директории \enems). Затем идут четыре ячейки, которые определяют размер карты и окон. MAP_W и MAP_H должны содержать ширину и высоту твоей карты в попугаях (то есть окнах). SCR_W и SCR_H используются для определения ширины и высоты окон в тайлах. Для игр Чурреры эти значения, как ты уже должен знать, равняются 15 и 10.

Последняя ячейка – это количество врагов, которое появляется в каждом окне. В Чуррера их 3. Нет, если поставишь больше, больше их в игре не появится. Просто все сломается. Поставь 3. Я тебя уверяю, трех вполне достаточно.

Базовая работа программы

Функционирование очень простое. Как раз, потому что сама программа очень простая. Если посмотришь, увидишь таблицу с текущим окном. Если таблица не появляется, или то, что появляется, не относится к первому окну твоей карты, все плохо. Проверь предыдущие шаги, особенно относительно размеров карты и окон.

Чтобы перемещаться по карте (чтобы появилось другое окно в таблице) используем клавиши со стрелками. Попробуй. Если все хорошо, ты сможешь проложить настоящий туристический маршрут по твоей карте.

Если нажмем ESC, программа закроется, что безумно удобно, когда мы все доделали и хотим выйти. Но осторожно: программа просто закрывается безо всяких но. Спокойствие, только спокойствие. Не нажимай ESC, не сохранившись перед этим.  Программа не предупреждает. Она просто закрывается.

Как раз чтобы сохраниться, у нас есть кнопочка S. Давайте нажмем ее прямо сейчас, хотя мы пока ни одного врага не разместили. По умолчанию используем .ene как расширение для архивов Разместителя. Нажми S и в появившемся окошке напиши enems.ene и кликни на кнопку ОК. Мы уже сохранили наше размещение. Делай это очень часто.  Верь нам!

Теперь посмотрим, как это работает. Нажми ESC, чтобы выйти. Проверь, что теперь появился архив enems.ene в \enems. Снова запусти colocador.exe. В этот раз вместо заполнения всех значений, пропиши enems.ene в окне под названием «Открыть существующий проект» (Abrir un proyecto existente) и нажми на кнопку с надписью Загрузить (Cargar). Если все прошло хорошо, у тебя снова появится первое окно карты.

http://zxaaa.net/store/images/colocador-existente-56551.png

Этот архив enems.ene не используется напрямую в игре. Чтобы в нашей игре появились враги, нам нужно, чтобы Разместитель экспортировал код С. Это можно сделать, нажав кнопку Е. Когда это сделано, появляется диалоговое окно, похожее на окно для сохранения. Вписываем в него enems.h, нажимаем на ОК, и копируем этот архив в \dev. Сделаем это, когда завершим размещение всех врагов и захотим интегрировать их в игру.

Размещение врагов и платформ

Самое простое – разместить линейных врагов (горизонтальных, вертикальных или в редких случаях диагональных, которых видели чуть выше). Для этого нужно определить траекторию, тип и скорость. Перейдем к делу.

Прежде всего, нужно установить мышку чуть выше ячейки начала траектории и кликнуть. Это будет начальная позиция, где появится враг, а также она будет ограничивать его траекторию (смотри рисунки, расположенные выше, когда мы говорили о типах врагов). Когда это сделано, появится диалоговое окно, в котором мы должны прописать тип врага. Не забывай, что в случае линейных врагов это будет значение от 1 до 4, где 4 относится к платформам в играх с боковым видом. Вводим номер и нажимаем ОК.

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

Вводимое значение соответствует количеству пикселей, на которое продвинется враг или платформа в каждой части игры. Чтобы не было проблем, это значение должно быть кратно двум. Например, 1, 2, 4, 8…. На самом деле, подходящие значения – это 1, 2 или 4. Больше будет слишком быстро и создаст различные проблемы. Значения, не кратные двум, также создадут проблемы. Если хочешь, можешь попробовать поставить 3 или что-нибудь еще, чтобы посмотреть, что произойдет, но я тебе гарантирую, что, скорее всего, в результате твои враги отправятся на рыбалку подальше от твоего игрового окна – или что похуже. Когда ты ввел значение, нажми ОК – и твой первый враг появится на карте.

http://zxaaa.net/store/images/colocador-enem-00031.png

Для остальных врагов (пока  поговорим о типах 5 или 7), тема немножко другая. Например, врагам пятого типа все равно, где ты их расположишь: они всегда появляются вне экрана (вспомни летучих мышей из Zombie Calavera, чтобы понять, о чем я говорю). Можешь обозначить начало и конец траектории, где хочешь. Скорость, которую ты пропишешь, тоже не будет принята в расчет. С врагами типа 7 (Mega Meghan) будет учтена только начальная позиция. Скорость и финальная позиция тоже будут полностью проигнорированы.

Когда мы в будущем перейдем к программированию в движке кастомизированного врага шестого типа, мы будем прописывать и начальную и финальную позицию, и скорость. Например, если можно выстрелить из пушки, то можно прописать направление, в котором она будет стрелять.  Но не будем забегать вперед. К тому же Dogmole не использует нелинейных врагов, не говоря уж о таких редких явлениях.

Можешь поставить трех врагов в каждом окне (программа не даст тебе прописать больше). Не обязательно ставить трех врагов в каждом окне, у тебя могут быть окна с одним или двумя врагами – или вообще без таковых.

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

Таким образом, мы начинаем потихоньку размещать наших врагов и платформы на карте, максимум три в каждом окне, помня, что не надо ставить большее значение типа врага, и не забывая, что скорость должна равняться 1, 2 или 4.

Размещаем хотспоты
Как говорили ранее, хотспот – это ячейка, где появляется ключ или предмет во время игры, и где может появиться дополнительная жизнь, если вернуться в это окно, после того как мы забрали тот самый ключ или предмет.

Если помните, мы говорили, что хотспоты разделяются на несколько видов. В Чуррера этот тип может быть 0 (неактивный), 1 (содержит предмет) или 2 (содержит ключ). Если ты считаешь себя крутым, ты можешь, конечно, изменить движок, чтобы их было больше, но в своем нынешнем виде Чуррера допускает только эти три типа.

Мы помним, что каждое окно может иметь только один хотспот. Это значит, что общее количество ключей и предметов, необходимых для завершения игры, не может быть больше общего количества игровых окон. Например, в Lala Prologue у нас 30 окон. Чтобы успешно завершить игру, нужно собрать 25 предметов, к тому же нужно открыть 4 замка, для чего нам нужно 4 ключа. Это значит, что в 25 из 30 окон расположен предмет, а в 4 – ключ. Отлично: используем 29 окон из 30. Важно запланировать это заранее. Если тебе приперло установить кучу замков, то может так случиться, что тебе не хватит места и на ключи, и на предметы, которые нужно собрать.

Также нужно убедиться, что ты разместил достаточно ключей,  чтобы открыть все замки, и что всегда есть возможность завершить игру, не оставшись у закрытой двери.  Так что лучше с этим без фанатизма, иначе можно получить несовместимую комбинацию замков и ключей, если по дороге будешь менять конфигурацию: в итоге игрок израсходует ключи на запланированной тобой дороге, а дальше пройти не сможет.

Чтобы разместить хотспот на открытом окне, просто кликаем правой кнопкой мыши в точке, где хотим разместить ключ или предмет. Появляется маленькое диалоговое окно, куда вводим тип. На картинке ниже показано расположение одного из трех ключей в Lala Prologue.

http://zxaaa.net/store/images/colocador-hotspot-01561.png

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

Генерация кода
Когда мы все уже расположили, как говорили раньше, мы должны создать код, используемый в Чуррера. Помнишь, суперскую таблицу значений, которую мы упоминали в начале главы? Это она. Когда закончил, нажми Е и сохрани код как enems.h. Скопируй этот файл в \dev. Если тебе любопытно, можешь открыть его в текстовом редакторе и посмотреть, сколько цифр тебе не пришлось писать вручную.

А теперь все!
С большим волнением, в следующем выпуске мы начнем в первый раз собирать нашу игру, пока, правда, без скриптов, чтобы увидеть, как у нас идут дела.

7

Создай свою собственную игру на ZX Spectrum.
Глава 7: Первая сборка

http://zxaaa.net/store/images/colisiones-06171.png

Мы добрались до седьмой части семинара “Создай свою собственную игру на Спектруме” на Чуррера от Mojon Twins. Наконец мы сможем собрать нашу игру, но сначала надо зарядить батарейки, потому что эта глава потребует максимальной концентрации. Готовы? Поехали!

Глава 7: Первая сборка
Прежде всего, скачайте соответствующие материалы для этой главы, нажав на ссылку ниже:

http://www.mojontwins.com/churrera/chur … itulo7.zip (скачать локально: churreratut-capitulo7)

Давай же! Я хочу посмотреть, как они ходят!

Мы как раз до этого и добрались. Эта глава будет сложной, очень сложной. Приготовьтесь впитывать тонны и тонны информации, как губки. Чтобы следить за развитием событий в этой главе, рекомендуем тебе съесть арбузную тянучку, которая зарядит твой мозг и добавит мужества.

http://zxaaa.net/store/images/produit_9479-44321.jpg

Начнем с простого: сначала проверим, что у нас есть все, нужное для работы.

Прежде всего, нам нужно разархивировать файл Чурреры и персонализировать архивы, как мы объясняли в начале этого семинара. Должно получиться что-то такое:

http://zxaaa.net/store/images/carpeta-00551.png

Кроме того, мы должны скопировать все архивы, которые мы до этого разработали, конвертировали и создали, то есть:

Тайлсет в архиве tileset.h

Спрайтсет,  в архиве sprites.h

Карта в архиве mapa.h

Фиксированные окна title.bin, marco.bin (если его используем) и ending.bin

Враги и хотспоты в enems.h

Ну что, всё есть? Точно? Значит, можем начать конфигурацию движка для нашей первой компиляции. Осторожнее на поворотах!

Архив конфигурации
Если посмотришь в папку запуска /dev, содержащую все необходимые списки и ресурсы, то там есть архив под названием config.h. Зрите в оба: это самый важный архив из всех, так как именно он определяет, какие части движка собираются вместе, чтобы сформировать игру, и какие значения параметров используются для этих частей. По идее это мы уже делали, но на всякий случай: открой /dev/config.h в твоем любимом текстовом редакторе (который, как мы помним, выбран с умом). Ужаснись дикому количеству вещей, которые там написаны. Пройдемся по ним, чтобы объяснить каждую часть: для чего служат эти значения, как их использовать, и как их заполнить для нашего Dogmole. Глубокий вдох – поехали.

Общая конфигурация
В этом параграфе настраиваются общие параметры игры: размер карты, количество предметов (если применимо), и стилевые параметры:

Размер карты

#define MAP_W 8 //

#define MAP_H 3 // Map dimensions in screens

Две эти команды определяют размер нашей карты. Если помним, для нашей игры Dogmole мы взяли карту 8 х 3 окна. Соответственно, прописываем 8 и 3 (W от Width, ширина, y H от Height, высота).

Начальная позиция

#define SCR_INICIO 16 // Initial screen

#define PLAYER_INI_X 1 //

#define PLAYER_INI_Y 7 // Initial tile coordinates

Здесь определяем позицию главного героя, когда начинается новая игра. SCR_INICIO определяет, в каком он будет окне, а PLAYER_INI_X и Y определяют координаты тайла, в котором появится игрок. Мы начинаем в первом окне третьей строки (если посчитаем, можно и на калькуляторе), которое носит номер 16. Мы расположили героя Dogmole на земле рядом с каменной стеной, в точке с координатами (1, 7) (помни, настоящие разработчики начинают считать с нуля!).

Финальная позиция

#define SCR_FIN 99 // Last screen. 99 = deactivated.

#define PLAYER_FIN_X 99 //

#define PLAYER_FIN_Y 99 // Player tile coordinates to finish game

Здесь определяем финальную позицию, до которой должны добраться, чтобы закончить игру. Может быть вариант с игрой, в которой  просто достаточно добраться до конкретного места, чтобы выиграть. В этом случае заполняем эти значения. Как так в игре, которую делаем мы, это не используется (и никогда, понимаете, НИКОГДА, этого не использовали!), ставим значение, находящееся вне ряда наших значений. Обычно, это число 99 (например, на нашей карте нет такого количества окон), и это крутое число.

Количество предметов

#define PLAYER_NUM_OBJETOS 99 // Objects to get to finish game

Здесь нужно быть внимательными: этот параметр определяет количество предметов, которые мы должны собрать для завершения игры. В простых играх, как Lala Prologue, подсчет собранных предметов и проверка, собрали ли мы уже нужное количество, ведутся автоматически и используют это значение: как только игрок достигает прописанного значения, появляется экран завершения игры. В нашем случае все по-другому: мы будем использовать скрипт для управления предметами и подтверждением, что выполнили все задания, чтобы выиграть, поэтому нам это не пригодится. Поэтому ставим значение, находящееся вне ряда наших значений, наше любимое число 99, чтобы движок игнорировал автоматический подсчет предметов. Если же ты делаешь игру сам по себе, и тебе нужно просто собрать все предметы, как во многих наших играх, впиши сюда максимальное количество предметов.

Изначальное количество жизней и дополнительные жизни

#define PLAYER_LIFE 15 // Max and starting life gauge.

#define PLAYER_REFILL 1 // Life recharge

Здесь мы определяем, сколько изначально жизней у нашего персонажа, и сколько добавляется, когда он собирает дополнительную жизнь. В Dogmole мы начинаем с 15 жизнями, и 1 собранное сердце добавляет 1 жизнь. Так как в нашем движке будет прописано, что при столкновении с врагом персонаж начинает мигать, жизни будут потихоньку растрачиваться одна за другой. А в таких играх, как Lala Prologue, в которых при столкновении с врагом персонаж отскакивает, и враг может снова и снова на него нападать, жизни воспринимаются как «энергия», и поэтому используются более высокие значения, как 99, и дополнительные жизни также дают больше: от 10 до 25 пунктов.

Игры с несколькими уровнями

//#define COMPRESSED_LEVELS // use levels.h instead of mapa.h and enems.h

//#define MAX_LEVELS 2 // # of compressed levels

//#define REFILL_ME // If defined, refill player on each level

Чуррера может работать с несколькими сжатыми уровнями, как обычно с низким использованием оперативной памяти, но с возможностью применять легкие изменения для использования дополнительной оперативной памяти при работе с моделями 128K. Здесь речь идет о продвинутых характеристиках, о которых мы поговорим в следующих главах.

Тип движка

Теперь переходим к серьезным вещам: к конфигурации частей кода, которые будут собраны из трансформированных частей, чтобы сформировать нашего гомункула. Вот здесь-то вся соль нашей работы. Это будет весело, потому что мы будем экспериментировать с использованием различных странных комбинаций (мы это опробовали в Covertape #2) и наблюдать получающийся эффект. Как мы уже упоминали, невозможно активировать все функции одновременно, не только потому что есть взаимоисключающие вещи, но и потому что они просто-напросто нам не подходят.

Здесь у нас есть 2 типа параметров: те, которые имеют цифровое значение – такие как те, которые мы видели выше, и те, которые могут быть активны или неактивны. Чтобы дезактивировать один из параметров, просто ставим комментарий. На языке Си комментарии изображаются двумя слешами: //. Когда видишь строчку с двумя слешами в начале, это комментарий, и, соответственно, описываемая характеристика дезактивирована.

Каждой части свое время, как говаривал Виктор Франкенштейн…

Размер ячейки столкновения

#define BOUNDING_BOX_8_BOTTOM // 8×8 aligned to bottom center in 16×16

//#define BOUNDING_BOX_8_CENTERED // 8×8 aligned to center in 16×16

//#define SMALL_COLLISION // 8×8 centered collision instead of 12×12

Ячейка столкновения соответствует квадрату, который занимает наш спрайт. Чтобы мы друг друга понимали: наш спрайт сталкивается с окружением в игре. Это столкновение считается внутри воображаемого квадрата, который может иметь 2 размера: 16 х 16 или 8 x 8. Движок просто проверяет, что этот квадрат не встречается с препятствиями.

Чтобы ты понимал разницу, посмотри, как Lala работает со сценарием в Lala Prologue (там прописана ячейка столкновения размером 16 х 16, которую занимает весь спрайт) и в Lala Lah (в которой используем ячейку столкновения 8 х 8, т.е. меньше, чем спрайт). Столкновение 8 х 8 – это одно из дополнений в этой новой специальной версии 3.99b Чурреры, и, по нашему мнению, это делает управление более естественным. В любом случае, мы оставили разработчику (то есть тебе) возможность выбрать также и ячейку 16 х 16, что может оказаться более адекватным выбором в некоторых ситуациях.

Если мы выбираем столкновение 8 х 8, у нас 2 опции: чтобы квадрат располагался по центру спрайта или в его нижней части:

http://zxaaa.net/store/images/colisiones-06171.png

Первая опция (квадрат в центре) создана для игр генитального типа, как Balowwwn или D’Veel’Ng. Вторая хорошо работает в играх с боковым или генитальным видом «с некоторой перспективой», как Mega Meghan.

Только одна из настроек может быть активна (потому что они взаимоисключающие): если выбираем расположенный по центру квадрат столкновения 8 х 8, активируем BOUNDING_BOX_8_CENTERED и дезактивируем другую опцию. Если мы хотим столкновение 8 х 8 в нижней части, то активируем BOUNDING_BOX_8_BOTTOM и отключаем вторую. Если хотим столкновение 16 х 16, то включаем обе.

Третья команда относится к столкновению с врагами. Если активируем SMALL_COLLISIO, вражеским спрайтам придется сильно врубиться в персонажа, чтобы он это почувствовал. С включенной опцией SMALL_COLLISION от врагов гораздо проще увернуться. Это отлично работает в играх с быстрым управлением, как Bootee. Для Dogmole же мы ее не будем включать.

Общие команды

#define PLAYER_AUTO_CHANGE_SCREEN // Player changes screen automatically

Если включаем эту опцию, игрок будет переходить на следующий экран, когда подойдет к краю своего экрана. Если же эта опция не прописана, то надо будет нажать на кнопку соответствующего направления, чтобы перейти. Обычно эта опция включена, чтобы, если персонаж продолжает двигаться по инерции, экран автоматически менялся. Нам не встречались ситуации, в которых это создавало бы негативные последствия, но на всякий случай мы дали возможность отключить эту опцию.

//#define PLAYER_PUSH_BOXES // If defined, tile #14 is pushable

//#define FIRE_TO_PUSH

Эти две команды активируют и конфигурируют передвигаемые блоки. Мы не будем использовать в Dogmole такие блоки, поэтому дезактивируем эту опцию. Если активировать первую команду (PLAYER_PUSH_BOXES), то активируются блоки, и соответственно тайлы #14 (с поведением 10 типа, помнишь?) можно передвигать.

Вторая команда, FIRE_TO_PUSH, определяет, нужно ли игроку еще и нажимать на выстрел, чтобы сдвинуть блок в соответствующем направлении – или нет. В Cheril Perils, например, на выстрел нажимать не надо: достаточно дотронуться до блока во время движения вперед. В D’Veel’N, наоборот, нужно нажимать на выстрел, чтобы сдвинуть блок. Если будешь использовать передвигаемые блоки, ты должен выбрать опцию, которая больше тебе по душе (и которая больше подходит тому типу игры, который ты хочешь в итоге получить).

#define DIRECT_TO_PLAY // If defined, title screen = game frame.

Эта  команда активируется, чтобы получить то, о чем мы говорили в главе о фиксированных экранах: чтобы начальный экран игры был совмещен с экраном маркировки игры. Если у тебя есть отдельные файлы title.bin и marco.bin, тебе надо дезактивировать эту опцию. В нашем случае у нас только один файл title.bin, совмещенный с экраном маркировки игры, поэтому оставляем опцию активной.

//#define DEACTIVATE_KEYS // If defined, keys are not present.
//#define DEACTIVATE_OBJECTS // If defined, objects are not present.

Эти две команды служат для дезактивации ключей и предметов. Если твоя игра не использует ключи и замки, ты должен активировать DEACTIVATE_KEYS. Если ты не используешь предметы, то активируем DEACTIVATE_OBJECTS.

Конечно, кто-то из вас уже подумал: почему не активируем DEACTIVATE_OBJECTS в Dogmole, если мы сказали, что будет ими управлять через скрипты? Отличный вопрос! Все просто: что мы будем контролировать скриптом, так это подсчет предметов и финальное условие, но нужно, чтобы движок управлял сбором и расположением предметов.

Черт, какая мешанина, правда? Терпение, игра требует жертв!

define ONLY_ONE_OBJECT // If defined, only one object can be carried

#define OBJECT_COUNT 1 // Defines FLAG to be used to store object #

Продолжим работать с командами с особенным применением: если активируем первую, ONLY_ONE_OBJECT, то можем брать только один предмет. Как только ты собрал предмет, сбор остальных предметов блокируется, и больше ты ничего взять не сможешь. Чтобы снова активировать эту опцию, будем использовать скрипты. Таким образом, мы получим требуемый эффект: ящики надо относить в требуемую локацию по одному: конфигурируем движок так, чтобы он дал относить только один ящик за раз, а благодаря скрипту, когда доставляем ящик в нужное место (конкретное место в университете), сбор предметов снова активируется, чтобы мы могли принести следующий ящик.

Вторая команда, OBJECT_COUNT, делает так, что индикатор собранных ящиков показывает не общее значение собранных  предметов, а то количество, которое выполнило условия скрипта (флагов). Как мы увидим в будущем, когда будем объяснять движок сприпта, скрипт имеет до 32 переменных или «флагов», которые мы можем использовать для сохранения данных и проведения проверок. Каждая переменная имеет свой номер. Если мы прописываем эту команду, движок покажет значение флага, указанного в счетчике собранных предметов. Благодаря скрипту, это значение будет увеличиваться каждый раз, как игрок будет относить очередной ящик в Университет.

В конце концов, мы можем просто прописать OBJECT_COUNT, если сами будем вести счет вручную, при помощи скрипта. Если мы не будем использовать скрипты, или нам не нужно будет вручную считать количество собранных предметов, то просто комментируем эту команду, чтобы она не принималась в расчёт.

//#define DEACTIVATE_EVIL_TILE // If defined, no killing tiles are detected.

Сними комментарии с этой команды, если хочешь убрать тайлы, которые тебя убивают (тип 1). Если не используешь тайлы первого типа в твоей игре, сними комментарий в этой строчке, и сэкономишь место, так как таким образом определение убивающих тайлов не будет включено в код.

//#define PLAYER_BOUNCES // If defined, collisions make player bounce

//#define FULL_BOUNCE

//#define SLOW_DRAIN // Works with bounces. Drain is 4 times slower

#define PLAYER_FLICKERS // If defined, collisions make player flicker

Эти две команды контролирует отскакивание. Если активируешь PLAYER_BOUNCES, игрок будет отскакивать от врагов при их касании. Сила этого отскока контролируется опцией FULL_BOUNCE: если она активна, отскоки будут гораздо более сильные, потому что будет использоваться скорость, с которой персонаж продвигается, но на этот раз, в обратном направлении. Если дезактивировать FULL_BOUNCE, то отскок будет равен половине изначальной скорости.

Если мы к тому же активируем опцию SLOW_DRAIN, то скорость снизится в 4 раза, если мы останемся на пути у врага (вспомни Lala Prologue, Sir Ababol или оригинальную версию Viaje al Centro de la Napia). Это используется в игре Bootee, где запросто можно остаться на траектории передвижения врага, что усложняет уход с нее. Это делает игру более доступной.

Как ты мог уже догадаться, FULL_BOUNCE и SLOW_DRAIN зависят от PLAYER_BOUNCES. Если PLAYER_BOUNCES дезактивировано, две остальные команды будут проигнорированы.

Активируя PLAYER_FLICKERS, получаем следующий эффект: персонаж мигает, если встречается с врагом (и остается неуязвимым в течение короткого периода времени). Обычно выбор делается между PLAYER_BOUNCES и PLAYER_FLICKERS, но можно активировать и обе функции. Мы же в Dogmole хотим, чтобы персонаж мигал при столкновении с врагом, поэтому дезактивируем PLAYER_BOUNCES и активируем PLAYER_FLICKERS.

//#define MAP_BOTTOM_KILLS // If defined, exiting the map bottom kills

Дезактивируй эту команду, если хочешь, чтобы, если персонаж, упав в самый низ игрового окна, отскакивал и сохранял жизнь, как это происходит в Zombie Calavera. Если твоя карта закрыта снизу, дезактивируй эту опцию, чтобы сэкономить насколько байтов.

//#define WALLS_STOP_ENEMIES // If defined… erm…

Эта команда связана с передвигаемыми тайлами. Если ты выбрал передвигаемые блоки, может быть, тебя заинтересует вариант, в котором враги реагируют на них и изменяют свои траектории, как это происходит, например, в Monono или Cheril of the Bosque (и во многих других). Если же не используешь передвигаемые тайлы, или тебе все равно, проходят ли враги через них или нет, дезактивируй эту опцию, чтобы сэкономить уйму памяти.

Дополнительные типы врагов
Теперь давайте рассмотрим сочетание команд, которые помогут нам активировать врагов типов 5, 6 или 7. Вспомните, что мы говорили об этих типах врагов: 5 – это летучие мыши из Zombie Calavera, 7 – это преследующие тебя враги из Mega Meghan, а 6 служит для создания новых типов врагов.

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

//#define ENABLE_RANDOM_RESPAWN // If defined, flying enemies

//#define FANTY_MAX_V 256 // Flying enemies max speed.

//#define FANTY_A 12 // Flying enemies acceleration.

//#define FANTIES_LIFE_GAUGE 10 // Amount of shots needed to kill.

Если мы активируем ENABLE_RANDOM_RESPAWN, то активируем врагов пятого типа. Эти враги появляются вне границ окна, если есть хоть один враг пятого типа или хоть один убитый враг, и преследуют игрока, только если он не использует тайл второго типа (спрятался). Следующие команды конфигурируют их поведение:

FANTY_MAX_V задает максимальную скорость. Чтобы создать себе представление, раздели это значение на 64, и получившийся результат – это максимальное количество пикселей, на которое враг продвинется в каждом фрейме игры. Если ставим значение 256, то летучий враг сможет продвинуться на 4 пикселя в каждом фрейме.

FANTY_A – это значение ускорения. С каждым фреймом скорость будет увеличиваться на прописанное значение в направлении игрока, если тот не спрятался. Чем меньше это значение, тем медленнее враг будет реагировать на изменение направления движения игрока.

FANTIES_LIFE_GAUGE определяет, сколько выстрелов надо произвести в зверюшку, чтобы убить ее, в случае если мы активировали стрельбу (смотри дальше).

//#define ENABLE_PURSUERS // If defined, type 7 enemies are active

//#define DEATH_COUNT_EXPRESSION 8 + (rand() & 15)

Активируя ENABLE_PURSUERS, добавляем врагов седьмого типа. Эти враги появляются там, где мы их разместили (вспоминаем главу про размещение врагов) и преследуют игрока. Препятствия на карте их останавливают, в отличие от врагов пятого типа.

Если мы активировали движок выстрелов, когда мы убиваем врага седьмого типа, пройдет некоторое время, прежде чем он снова появится. Это время, выраженное в количестве фреймов, вычисляется с помощью формулы, прописанной в DEATH_COUNT_EXPRESSION. То, что мы видим в этом примере, используется в Mega Meghan: 8 + любое число между 0 и 15 (таким образом, от 8 до 23 фреймов).

Движок выстрелов
Движок выстрелов обходится нам дорого с точки зрения использования памяти. Его активация добавляет большое количество кодов, которые принимают в расчет дополнительные столкновения и учитывают кучу других вещей, к тому же нужны дополнительные спрайты.

//#define PLAYER_CAN_FIRE // If defined, shooting engine is enabled.

Если активируем эту команду, включаем движок выстрелов. Последующие команды конфигурируют их поведение.

//#define PLAYER_BULLET_SPEED 8 // Pixels/frame.

//#define MAX_BULLETS 3 // Max number of bullets on screen.

Команда PLAYER_BULLET_SPEED контролирует скорость пуль. 8 пикселей на фрейм – это нормальное значение, которое мы используем во всех играх. Большее значение может привести к потере столкновений, к тому же, все, что происходит в окне, становится дискретным (не непрерывным), и если враг перемещается быстро в направлении от пули, которая летит слишком быстро, возможно, что они в итоге окажутся в разных фреймах, и столкновения не будет. Если подумаешь об этом и представишь игру в замедленном режиме съемки, как последовательность фреймов, будет понятнее.

Значение MAX_BULLETS определяет максимальное количество пуль, которое может использоваться в одном окне. Здесь особо не заигрывайся, я уже вижу, как у тебя чешутся руки: в принципе можно прописать больше трех пуль, но для этого надо поменять часть движка, который использует память, необходимую для системы спрайтов. Каждый перемещающийся спрайт требует кучу памяти (14 байтов на блок, спрайт 8 х 8 использует 4 блока), поэтому, чем меньше, тем лучше. По правде говоря, все настолько подогнано, что тут уже яблочному огрызку некуда упасть, но, возможно, в конце семинара я объясню, как изменять количество блоков, которые используются спрайтами, чтобы можно было прописать больше пуль.

Зачем же тогда прописывать это значение? Ну, вдруг тебе захочется прописать меньше. Например, для некоторых игр было бы неплохо прописать только одну пулю.

//#define PLAYER_BULLET_Y_OFFSET 6 // vertical offset from the player’s top.

//#define PLAYER_BULLET_X_OFFSET 0 // horz offset from the player’s left/right.

Эти две команды определяют, где появляются пули при выстреле. Поведение этих значений довольно сложное (ну ладно, не настолько) и изменяется в зависимости от выбранного вида:

Если игра имеет боковой вид, мы можем стрелять только влево или вправо. В этом случае PLAYER_BULLET_Y_OFFSET определяет высоту, в пикселях, на которой появляется пуля, с отсчетом от верхней части спрайта игрока. Это помогает определить форму, которая появляется из пистолета или откуда хотим (хоть из ширинки).PLAYER_BULLET_X_OFFSET полностью  игнорируется.

Если же игра генитального вида, поведение пули такое же, как описано выше, если смотрим налево или направо, но если смотрим вверх или вниз, пуля будет смещена вбок: влево, если мы смотрим вниз, или вправо, если мы смотрим вверх. Это значит, что наш игрок правша. Посмотри на спрайты Mega Meghan. Чтобы игрок был левшой, достаточно поменять 2 строчки в движке. Если тебе интересно, и это вопрос жизни и смерти, напиши нам, и мы теперь всё расскажем, дружище Фландерс.

//#define ENEMIES_LIFE_GAUGE 4 // Amount of shots needed to kill enemies.

//#define RESPAWN_ON_ENTER // Enemies respawn when entering screen

Эти команды нужны, чтобы контролировать, что случится, когда пули врезаются в обычных врагов (типы 1, 2 или 3). Прежде всего, ENEMIES_LIFE_GAUGE определяет количество выстрелов, которые нужно выполнить, чтобы убить врага. Если активируем RESPAWN_ON_ENTER, то враги оживают после того, как мы выходим из этого окна и потом в него возвращаемся. Ну как в классических играх.

Конечно, убитые враги будут считаться, и это значение может управляться скриптом.

8

Скрипты
Следующие команды активируют движок скриптов и определяют пару связанных с этим параметров. Пока мы его активировать не будем, чтобы сначала доделать и опробовать игру без скриптов. Уже не терпится, да? Спокойно, к ним мы вернемся, когда начнется хардкор.

//#define ACTIVATE_SCRIPTING // Activates msc scripting and flags.

#define SCRIPTING_DOWN // Use DOWN as the action key.

//#define SCRIPTING_KEY_M // Use M as the action key instead.

Первый пункт очень простой: если активируем ACTIVATE_SCRIPTING, вся система скриптов будет включена в движок. Два остальных определяют, какая будет кнопка действия: вниз или выстрел. Только одна из них может быть активна. Мы будем использовать кнопку вниз, чтобы выполнять действия, поэтому активируем SCRIPTING_DOWN.

Как я уже говорил, пока мы не активируем ACTIVATE_SCRIPTING. Мы включим эту опцию, когда начнем писать наш скрипт.

Команды, связанные с генитальным видом

//#define PLAYER_MOGGY_STYLE // Enable top view.

//#define TOP_OVER_SIDE // UP/DOWN has priority over LEFT/RIGHT

Если мы активируем PLAYER_MOGGY_STYLE, то игра будет генитального типа. Если эта опция не активирована, игра будет иметь боковой вид. Таким образом, оставляем ее неактивной для Dogmole.

Следующая команда, TOP_OVER_SIDE, определяет поведение диагоналей. Это полезно, прежде всего, если в твоей игре есть выстрелы. Если включить TOP_OVER_SIDE, то при перемещении по диагонали персонаж будет смотреть вверх или вниз и стрелять тоже в соответствующем направлении. В зависимости от типа игры или от конфигурации карты, тебя заинтересует та или иная опция. И нет, стрелять по диагонали нельзя.

Команды, связанные с боковым видом
Здесь у нас куча разных вещей:

#define PLAYER_HAS_JUMP // If defined, player is able to jump.

Если включить эту опцию, то игрок может прыгать при нажатии на кнопку выстрела, если выстрелы не активированы. Если выстрелы включены, то эту функцию выполняет кнопка вверх.

//#define PLAYER_HAS_JETPAC // If defined, player can thrust a jetpac

Если включаем PLAYER_HAS_JETPAC, кнопка вверх будет включать реактивный ранец. Это почти как прыгать. Конечно, если одновременно активируешь и прыжки, и реактивный ранец, не сможешь стрелять… хотя мы не пробовали,  но в лучшем случае произойдет что-нибудь странное. Лучше не пробуй. Или, не знаю, попробуй. Если не знаешь, о чем идет речь, поиграй в Cheril the Goddess или Jet Paco.

Эти команды активируют топтание по врагам. Если PLAYER_KILLS_ENEMIES активно, то игрок может прыгать на врагов, чтобы их убить.  PLAYER_MIN_KILLABLE делает так, чтобы не всех врагов можно было убить. В Dogmole можно убивать только колдунов, которые относятся к третьему типу. В общем, убивать можно только тех врагов, чей тип больше или равен тому значению, которое мы прописываем.

//#define PLAYER_BOOTEE // Always jumping engine.

Эта команда активирует постоянное прыганье (смотри Bootee). Эта команда несовместима с PLAYER_HAS_JUMP или с PLAYER_HAS_JETPAC. Если активируешь PLAYER_BOOTEE, нужно отключить остальные две. Если нет, то получится плохо.

//#define PLAYER_BOUNCE_WITH_WALLS // Bounce when hitting a wall

Игрок отскакивает от стен, как в Balowwwn. Это работает и при генитальном виде (на самом деле мы его специально программировали для Balowwwn, который относится к генитальному виду), не знаю, почему мы про него пишем здесь. Ой, нет, знаю.

//#define PLAYER_CUMULATIVE_JUMP // Keep pressing JUMP to JUMP higher

Эта функция работает с PLAYER_HAS_JUMP. Если она включена, то когда нажимаем кнопку прыжка, сначала прыгаем невысоко, но каждый раз прыгаем все выше, как в Monono.

Конфигурация окна
В этой части разместим все элементы в окне. Помнишь, как мы рисовали экран маркировки игры? Вот здесь и разместим все значения, которые уже прописали, а именно:

define VIEWPORT_X 1 //

#define VIEWPORT_Y 0 // Viewport character coordinates

Определяют позицию (всегда в координатах языка Си) игрового окна. Наша игровая зона начнется в (0, 1), и это значения, которые прописываем для VIEWPORT_X и VIEWPORT_Y.

#define LIFE_X 22 //

#define LIFE_Y 21 // Life gauge counter character coordinates

Определяют положение счетчика жизней (самого числа, да)

#define OBJECTS_X 17 //

#define OBJECTS_Y 21 // Objects counter character coordinates

Определяют позицию счетчика предметов, если мы их используем (положение числа)

#define OBJECTS_ICON_X 15 // Objects icon character coordinates

#define OBJECTS_ICON_Y 21 // (use with ONLY_ONE_OBJECT)

Эти два значения используются с командой ONLY_ONE_OBJECT: Когда подбираем лишний предмет, движок нам дает об этом знать, заставляя мигать иконку предмета в зоне индикатора. В OBJECTS_ICON_X и Y указываем, где появляется эта иконка (тайл с картинкой ящика). Как увидишь, это приводит к тому, что мы используем в качестве индикатора не текст или еще что-нибудь, а именно картинку.

Да, есть такое ограничение.

Графические эффекты
В этой части определяются различные графические эффекты (самые базовые), которые мы можем активировать, и которые отвечают за то, как отображается игра. Здесь мы можем отконфигурировать Чурреру, чтобы она рисовала или не рисовала тени в тот момент, когда пишем сценарий, и прописать пару вещей, связанных со спрайтами и прочими.

//#define USE_AUTO_SHADOWS // Automatic shadows made of darker attributes

//#define USE_AUTO_TILE_SHADOWS // Automatic shadows using tiles 32-47.

Эти две команды отвечают за тени тайлов, и можно активировать либо одну из них, либо ни одной. Если помнишь, в главе о тайлсетах мы говорили об автоматических тенях. Если мы активируем USE_AUTO_SHADOWS,  то тайлы препятствий создадут тени на проходимых тайлах, используя только атрибуты (иногда получается вполне симпатично, на далеко не всегда).

USE_AUTO_TILE_SHADOWS использует затемнённые версии тайлов фона для создания теней, как мы и объясняли. Если отключить обе команды, теней не будет.

В Dogmole мы не используем никаких теней, потому что тени атрибутов нам не нравятся, а тени тайлов не можем себе позволить, поэтому используем эти тайлы только чтобы приукрасить некоторые окна, нанеся графику через скрипт.

//#define UNPACKED_MAP // Full, uncompressed maps.

Если включаем UNPACKED_MAP, то говорим нашему движку, что наша карта содержит 48 тайлов.

//#define NO_MASKS // Sprites are rendered using OR

//#define PLAYER_ALTERNATE_ANIMATION // If defined, animation is 1,2,3,1,2,3…

Эти две команды были созданы специально для Zombie Calavera. Первая (NO_MASKS) делает так, чтобы у тайлов не было масок, что экономит память. Так как Zombie Calavera маски не нужны, мы смогли сэкономить кучу байтов для других вещей. Однако, конвертор спрайтов, работающий сейчас в Чуррера, не может экспортировать спрайтсеты без масок, поэтому пока эта команда тебе особо не пригодится. Если будет достаточно запросов, мы попросим Амадора, обезьянку программиста, чтобы он обновил конвертор спрайтов, чтобы можно было вносить спрайты без масок.

PLAYER_ALTERNATE_ANIMATION может тебе пригодиться, так как меняет порядок анимации персонажа, когда он ходит. Обычно анимация такая: 2, 1, 2, 3, 2, 1, 2, 3… Но если активируешь эту команду, то анимация будет  1, 2, 3, 1, 2, 3,…

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

В принципе у нас есть то, что называется Прямолинейное Движение Без Ускорения (ПДБУ) по каждой оси: горизонтальной и вертикальной. У нас есть позиция (например, Х), на которую влияет скорость (скажем, VX),  на которую в свою очередь влияет ускорение (AX).

Следующие параметры служат для спецификации различных величин, связанных с движением по каждой оси в играх с боковым видом. В играх с генитальным видом, для вертикальной оси выставляются те же значения, что для горизонтальной оси.

Чтобы получить гладкое движение, не применяя десятичные значения (с которыми невероятно сложно работать), используем арифметику фиксированной точки. В принципе значения выражаются в 1/64 пикселя. Это значит, что используемое значение делится на 64 в момент перемещения реальных спрайтов в окно. Это нам дает точность 1/64 пикселя для обеих осей, что приводит к большей гладкости движения.

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

http://zxaaa.net/store/images/combinacion-08071.jpg

Вертикальная ось в играх с боковым видом
При вертикальном перемещении на него влияет гравитация. Вертикальная скорость увеличивается за счет гравитации до того момента, когда персонаж не приземлится на платформу или препятствие. К тому же, в момент прыжка, создается дополнительный импульс, который мы также здесь пропишем. Вот значения для Dogmole; чуть ниже мы каждое из них детально распишем:

define PLAYER_MAX_VY_CAYENDO 512 // Max falling speed

#define PLAYER_G 48 // Gravity acceleration


#define PLAYER_VY_INICIAL_SALTO 96 // Initial junp velocity

#define PLAYER_MAX_VY_SALTANDO 312 // Max jump velocity

#define PLAYER_INCR_SALTO 48 // acceleration while JUMP is pressed


#define PLAYER_INCR_JETPAC 32 // Vertical jetpac gauge

#define PLAYER_MAX_VY_JETPAC 256 // Max vertical jetpac speed

Свободное падение: скорость игрока, которую измеряем в пикселях на фрейм, увеличивается в PLAYER_G/64 pixels/frame^2, пока не достигнет максимума, прописанного в PLAYER_MAX_CAYENDO/64. Со значениями, которые мы выбрали для Dogmole, вертикальная скорость при свободном падении увеличивается на 48/64=0,75 пикселей / фрейм, пока не достигнет максимального значения 512/64=8 пикселей / фрейм. Это значит, что Dogmole будет падать все быстрее, пока не достигнет максимальной скорости 8 пикселей / фрейм. Увеличив значение PLAYER_G, получим достижение максимальной скорости гораздо раньше. Эти значения влияют на прыжок: с большей гравитацией прыжок будет ниже, и меньше продлится начальный импульс. Изменив PLAYER_MAX_CAYENDO, можем добиться, чтобы максимальная скорость, которая достигается раньше или позже, в зависимости от PLAYER_G, была больше или меньше. Используя маленькие величины, можем сымитировать в качестве внешней среды среду с небольшой гравитацией, как на поверхности Луны или на дне моря. Значение 512 (соответствующее 8 пикселям / фрейм) можем считать максимальным, потому что более высокая скорость и более затяжные падения могут привести к зависаниям и редким явлениям.

Прыжок
Прыжки контролируются по трем параметрам. Первый, PLAYER_VY_INICIAL_SALTO, это значение начального импульса: когда игрок нажимает кнопку прыжка, вертикальная скорость автоматически приобретет прописанное значение. Пока нажата кнопка прыжка и в течение около восьми фреймов скорость будет увеличиваться на значение, прописанное для PLAYER_INCR_SALTO, пока не достигнет значения PLAYER_MAX_VY_SALTANDO. Это сделано с тем, чтобы можно было контролировать силу прыжка, нажимая на кнопку прыжка более долгое или короткое время. Период ускорения, который длится 8 фреймов, фиксирован и не может быть изменен (чтобы его поменять, надо вносить изменения в движок), но мы можем получить более резкие прыжки, увеличив значения  PLAYER_INCR_SALTO и PLAYER_MAX_VY_SALTANDO.

Обычно для того чтобы найти идеальные значения требуется применить метод проб и ошибок. Нужно учитывать, что горизонтальные прыжки при перескакивании с одной платформы на другую также вводят в игру значения горизонтального перемещения, поэтому если ты решил, что  в твоей игре персонаж должен прыгать на расстояние Х тайлов, нужно найти оптимальную комбинацию, попробовав все параметры.

Два значения, которые нам остались, не используются в Dogmole, потому что связаны с применением реактивного ранца. Первый параметр – это ускорение, получаемое при нажатии кнопки вверх, а второе – максимально достижимое значение. Если твоя игра не использует реактивный ранец, эти значения не применяются.

Горизонтальная ось в играх с боковым видом / общее поведение при генитальном виде
Следующий набор параметров описывает поведение движения по горизонтальной оси, если твоя игра бокового типа, или по обеим осям, если твоя игра генитального тира. Эти параметры гораздо проще:

#define PLAYER_MAX_VX 256 // Max velocity

#define PLAYER_AX 48 // Acceleration

#define PLAYER_RX 64 // Friction

Первый, PLAYER_MAX_VX, обозначает максимальную скорость, на которой персонаж перемещается по горизонтальной оси (или в любом направлении, если речь идет об игре генитального типа). Чем больше это значение, тем он быстрее будет бегать, и тем дальше будет прыгать (горизонтально). Значение 256 значит, что максимальная скорость бега будет 4 пикселя на фрейм.

PLAYER_AX контролирует ускорение персонажа, пока игрок нажимает на кнопку направления. Чем больше будет это значение, тем раньше будет достигнута максимальная скорость. Небольшие значения приводят к тому, что персонажу даже ноги переставлять тяжело. Значение 48 значит, что для достижения максимальной скорости потребуется примерно 6 фреймов (256/48).

PLAYER_RX – значение трения или сопротивления. Когда игрок перестал нажимать на кнопку направления, начинается применение этого ускорения в направлении, обратном направлению движения персонажа. Чем больше это значение, тем раньше персонаж остановится. Значение 64 означает, что для полной остановки после достижения максимальной скорости потребуется 4 фрейма.

Использование небольших значений для PLAYER_AX и PLAYER_RX приведет к тому, что будет казаться, что персонаж  скользит. Это происходит, например, Viaje al Centro de la Napia. Кроме загадочных исключений, практически всегда лучше играется, если значение PLAYER_AX больше, чем PLAYER_RX.

Поведение тайлов
Помнишь, как мы объясняли, что каждый тайл имеет свой тип поведения? Тайлы, которые убивают, которые являются препятствиями, платформами или взаимодействующими. В этой части config.h (последней, наконец-то)  мы определим поведение каждого из 48 тайлов полного тайлсета.

Нам нужно определить поведение 48 тайлов, несмотря на то, что наша игра использует тайлсет из 16. Обычно в таких случаях все тайлы с 16 до 47 имеют тип «0», но возможно, что нам потребуются другие значения, если мы используем дополнительные тайлы, чтобы нарисовать графику или украшения в скрипте, как мы и сделаем. В Dogmole мы не будем прописывать дополнительные препятствия вне тайлсета, но такие игры как сага о Ramiro el Vampiro содержат препятствия такого типа.

Чтобы ввести значения, просто открываем тайлсет и смотрим – они в том же порядке, в котором появляются в тайлсете:

http://zxaaa.net/store/images/tileset-dogmole-10341.png

unsigned char comportamiento_tiles[] = {

0, 8, 8, 8, 8, 8, 0, 8, 4, 0, 8, 1, 0, 0, 0, 10,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

};

Как видим, первый тайл свободный (тип 0), затем идут 5 тайлов камня, являющиеся препятствиями (тип 8), один фоновый тайл (колонна, тип 0), кирпич (тип 8), два тайла, формирующие арку (тип 4, платформа и тип 0, проходимый), плитка (тип 8),  пики, которые убивают (тип 1), три тайла фона (тип 0), и тайл замка (тип 10, взаимодействующий).

Когда изменяешь эти значения, не запутайся в запятых и не потеряй ни один из номеров.

Гав, гав, гав!

А, ты еще здесь? Я-то думал, что уже утомил тебя до смерти и отбил желание продолжать. Отлично, вижу, что ты крепкий и терпеливый парень. Все, мы закончили конфигурацию нашей игры. Теперь пора ее собирать. Тут будь очень терпелив, особенно, если не привык бороться с компилятором в командной строке.

Сейчас мы сконфигурируем наш скрипт компиляции make.bat, чтобы было попроще. Скрипт компиляции, кроме прочего, будет каждый раз заново ренегировать карту, что очень удобно, если мы постоянно вносим изменения (например, на этапе проверки), что значительно автоматизирует процесс.

Подготовка скрипта компиляции
Открываем make.bat в нашем текстовом редакторе, чтобы кое-что поменять. Если ты меня внимательно слушал в первой главе, сейчас у тебя должна быть более-менее похожая на это картина:

@echo off

rem cd ..\script

rem msc dogmole.spt msc.h 24

rem copy *.h ..\dev

rem cd ..\dev

cd ..\map

..\utils\mapcnv mapa.map 8 3 15 10 15 packed

copy mapa.h ..\dev

cd ..\dev

zcc +zx -vn dogmole.c -o dogmole.bin -lndos -lsplib2 -zorg=25000

..\utils\bas2tap -a10 -sLOADER loader.bas loader.tap

..\utils\bin2tap -o screen.tap -a 16384 loading.bin

..\utils\bin2tap -o main.tap -a 25000 dogmole.bin

copy /b loader.tap + screen.tap + main.tap dogmole.tap

del loader.tap

del screen.tap

del main.tap

del dogmole.bin

echo DONE

Удостоверься, что прописал “dogmole.*” (или другое имя, которое ты выбрал для своей игры) во всех местах, которые отмечены черным курсивом. Это первое. Также удостоверься, что не забыл переименовать churromain.c в dogmole.c (или название твоей игры).

Сейчас посмотрим, что делает каждая строчка, потому что если ты делал свою собственную игру, тебе придется кое-что поменять.

Прежде всего, видим, что есть 4 строчки, начинающиеся с rem. Эти линии имеют комментарии и не выполняются. Мы уберем rem, когда начнем писать нам скрипт, поэтому пока оставим их в покое.

Второй шаг: скрипт меняет директорию сохранения карты, чтобы заново генерировать mapa.h и скопировать его в /dev, на случай если мы внесли изменения, чтобы они отображались автоматически. Эта одна из линий, которые надо будет поменять в твоей игре, указав правильные параметры mapcnv (а именно, размеры окон или, если не используешь замки, чтобы прописать 99 вместо 15, или если используешь карты из 48 тайлов чтобы убрать packed):

cd ..\map

..\utils\mapcnv mapa.map 8 3 15 10 15 packed

copy mapa.h ..\dev

cd ..\dev

Следующая линия компилирует игру:

zcc +zx -vn dogmole.c -o dogmole.bin -lndos -lsplib2 -zorg=25000

Это как раз выполнение компилятора z88dk, который использует в качестве источника dogmole.c (и все архивы .h, которые включены), и выдает бинарный результат в машинном коде dogmole.bin. Директория компиляции – 25000.

Следующий шаг: скрипт создает три ленты в формате .tap. Первая содержит загрузчик под BASIC (который можешь поменять, если ты фрик – источник находится в loader.bas). Следующая содержит окно загрузки. Сейчас не будем на этом останавливаться, т.к. твоя игра будет иметь окно загрузки Чуррера по умолчанию (находится в loading.bin). Последняя содержит dogmole.bin, который начинаем компилировать:

..\utils\bas2tap -a10 -sLOADER loader.bas loader.tap

..\utils\bin2tap -o screen.tap -a 16384 loading.bin

..\utils\bin2tap -o main.tap -a 25000 dogmole.bin

Посмотри на –sLOADER в первой строчке, которая создает загрузчик BASIC. Это название появляется после “PROGRAM:” при загрузке ленты в реальный Спектрум, можешь его поменять на что-то другое. Помни, что названия архивов ленты Спектрума могут содержать максимум до 10 символов. Поменяем его, чтобы получилось DOGMOLE:

..\utils\bas2tap -a10 -sDOGMOLE loader.bas loader.tap

Когда у нас получилось три ленты, каждая из них с блоком (загрузчик, окно и игра), единственное, что нам остается, это их соединить:

copy /b loader.tap + screen.tap + main.tap dogmole.tap

И, наконец, наведем порядок и уберем временные архивы, которые нам уже не пригодятся:

del loader.tap

del screen.tap

del main.tap

del dogmole.bin

Заново сохрани make.bat со всеми изменениями. Все готово. Ну что, начали?

Компиляция
Первое, что делаем, это открываем командное окно и переходим к папке /dev нашей игры:

http://zxaaa.net/store/images/linea_de_comandos-12431.png

После этого выполним скрипт z88dk, который пропишет некоторые данные окружения. Помни, что устанавливаем его в C:\z88dk10. Выполняем:

C:\z88dk10\setenv.bat

http://zxaaa.net/store/images/setenv-13461.png

Когда это выполнено (мы должны делать это каждый раз, как открываем командное окно для компиляции игры), можем выполнить скрипт make.bat. Что бы ни случилось, не закрывай командное окно, тебе обязательно придется еще сотню раз проводить компиляцию (особенно, если подбираешь значения передвижения или изменяешь карту, чтобы все настроить).

make.bat

Если мы все сделали правильно, проблем быть не должно:

http://zxaaa.net/store/images/haciendo_make-14281.png

Все DONE! Мы закончили! Мы получили наш dogmole.tap с игрой, готовой для первой. Конечно, не все сразу сработает, потому что у нас пока нет скрипта, но, по крайней мере, ты сможешь увидеть, как персонажи двигаются, проверить, что ты не напортачил с картой, что движения выполняются как надо, что колдуны умирают, когда по ним потопчешься, и так далее. Если что-то пошло не так, исправь это, заново скомпилируй и снова пробуй.

И так как мозги кипят у нас у всех, у тебя, и у меня, оставим все как есть до следующей главы. Если ты решил начать с чего-нибудь полегче, типа Lala Prologue или Sir Ababol, то ты уже дошел до финала. Если нет, у нас впереди еще много работы.

Создай свою игру на ZX Spectrum. Часть 7b – Небольшое отступление

http://zxaaa.net/store/images/churros-650-jpg-384x288.jpg

Чуррера обновилась, и наши друзья из Mojon Twins решили написать главу 7b, чтобы объяснить произошедшие изменения. Теперь у нас еще больше возможностей (если это вообще возможно) для нашей игры в Спектруме. Наслаждаемся!

Чуррера 3.99.1
Прежде всего, скачайте соответствующие материалы для этой главы, нажав на ссылку ниже: http://www.mojontwins.com/churrera/mt-c … 3.99.1.zip (скачать локально: mt-churrera-3.99.1)

Но что же это?

Мы временно прервем наше обучение, прежде чем перейти к теме скриптов, чтобы представить вам новую версию Чурреры. Мы же не хотим, чтобы вы отстали от жизни: мы ввели пару новых интересных вещей и, что еще важнее, исправили несколько багов и значительно оптимизировали существующий код (чтобы у тебя умещалось больше всякой всячины в игру). Поэтому мы решили, что не продолжим наш семинар, пока ты не перейдешь на новую версию.

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

Обязательно ли обновляться? Ну, ты увидишь. Если хочешь продолжать обучение в нашем семинаре о создании Dogmole, по правде говоря, это не обязательно. Но я  все равно рекомендую обновить его.

Все готовы? Ну, начнём разговор про то, что появилось нового.

Что нового?
Начнем разбираться в каждой части отдельно, потому что изменения затронули сразу несколько аспектов. Самое замечательное – это то, что теперь у тебя есть ясный инструмент, который позволяет понять, как оно все работает, и объяснять эти вещи нам станет гораздо легче.

Разрушаемые тайлы
Для начала (пока что) для игр, использующих выстрелы, мы создали новый тип тайлов, под номером 16. Эти тайлы разрушаются и исчезают (заменяются на тайл с номером 0) после того, как в них попадают пули (количество необходимых выстрелов прописывается отдельно). Чтобы их включить в дополнение к 16-ым тайлам, мы должны отконфигурировать кое-что в config.h:

#define BREAKABLE_WALLS // Breakable walls – стены, которые ломаются
#define BREAKABLE_WALLS_LIFE 1 // Amount of hits to break wall – количество выстрелов, чтобы сломать стену

Первая команда, BREAKABLE_WALLS, активирует это свойство и добавляет весь код, необходимый для появления разрушаемых тайлов (если ее не активируешь, потому что у тебя и так есть тайлы 16-го типа, ничего не случится). Вторая команда, BREAKABLE_WALLS_LIFE, определяет количество выстрелов, необходимое для разрушения тайла. Конечно, нужно написать число, большее, чем 0. Если поставишь 3, тайл разрушится после третьего попавшего в цель выстрела.

Типы комбинируемых тайлов
Это то, что мы хотели создать с самого начала, но в результате оставили на десерт. И именно из-за того, что мы планировали добавить комбинируемые тайлы, в списке типов тайлов так много дыр. Сейчас увидишь, для чего мы это сделали.

В принципе, речь идет о комбинировании типов тайлов, чтобы один тайл был одновременно, например, и убивающей платформой, и препятствием, которое можно разрушить. Чтобы комбинировать типы тайлов, нужно просто суммировать типы, которые мы собираемся соединить. Отсюда и дыры в нумерации.

Например, чтобы создать разрушаемое препятствие, нужно чтобы этот тайл имел тип препятствия (8) и тип разрушаемости (16), таким образом, 8+16=24. В последней созданной нами игре, Sgt. Helmet, есть электрические заграждения (которые убивают), которые можно разрушить. Если ты посмотришь на код игры (должен бы, ты же теперь настоящий чуррос,… то есть разработчик!) и посмотришь на часть, посвящённую типам тайлов (behaviours) в конце config.h, увидишь, что тайл электрического забора имеет тип 17, т.е. убивающий (1) и разрушаемый (16): 16+1=17

Есть куча тупых и не имеющих смысла комбинаций, как, например, создать убивающее препятствие (8+1=9). На самом деле, как раз одну из этих тупых и невозможных комбинаций мы использовали для специальных тайлов (передвигаемые блоки и замки) с типом 10 (8+2, т.е. препятствие, которое тебя прячет).

Движок продолжает также работать и с простыми тайлами (1, 2, 4 и 8), так что в Dogmole или твоей собственной игре можешь ничего и не менять.

Заканчивающиеся пули
Теперь ты можешь создать заканчивающиеся пули. К тому же можешь размещать дополнительные пули в игре. Для этого, прежде всего, открываем config.h, чтобы активировать и отконфигурировать эту возможность:

#define MAX_AMMO 99 // If defined, ammo is not infinite! – Если определено, патроны не бесконечны!
#define AMMO_REFILL 50 // type 3 hotspots refill amo, using tile 20 – Хотспоты типа 3 перезаряжают патроны, используется плитка 20
//#define INITIAL_AMMO 0 // If defined, ammo = X when entering game. – Если задано, количество патронов = X при входе в игру.

Первая команда, MAX_AMMO, если включена, делает так, что пули заканчиваются, и их максимальное количество будет равняться прописанному. Если тебе нужно неограниченное количество пуль, просто поставь комментарий к этой команде. Следующая команда, AMMO_REFILL, определяет, сколько добавляется пуль, когда мы собираем дополнительное вооружение. Третья, INITIAL_AMMO, если включена, делает так, чтобы в начале игры мы имели определённое здесь количество пуль. Если опция не включена, количество пуль в начале игры будет максимальным, т.е. равным прописанному в MAX_AMMO.

Как видно здесь (это конфигурация Sgt. Helmet), максимум пуль равен 99, при сборе амуниции получаем по 50 пуль, а игра начинается с максимальным количеством, т.е. 99.

Чтобы расположить пули, поработаем с Разместителем и будем использовать хотспоты. До сегодняшнего дня нам приходилось использовать хотспоты первого типа для предметов и второго типа для ключей. Чтобы расположить амуницию, нам потребуются хотспоты 4-го типа. Соответственно, в нашем тайлсете тайл под номером 20 должен соответствовать амуниции. Вот тайлсет Sgt. Helmet. Посмотри, как выглядит тайл амуниции:

http://zxaaa.net/store/images/tileset-helmet-35461.png

Улучшения для врагов 7-го типа
Мы также добавили пару вещиц для врагов 7-го типа. Раньше враги 7-го типа появлялись в определенном тобой в Разместителе месте и преследовали тебя. Соответствующая графика выбиралась наугад между 4 возможными типами спрайтсетов. Теперь у тебя есть возможность выбрать самому графику, раз и навсегда. К тому же эти враги раньше не могли проходить через препятствия (тайлы 8-го типа). Сейчас же мы можем прописать, что любой тайл, не являющийся непроходимым (тип 0), задерживает их. Это сделано, например, в Sgt. Helmet, чтобы их задерживали, в том числе, и электрические заграждения (которые не относятся к 8 типу). Все это подчиняется двум новым командам в config.h:

#define TYPE_7_FIXED_SPRITE 4 // If defined, type 7 enemies are always 4 – Если задано, враги типа 7 всегда 4
#define EVERYTHING_IS_A_WALL // If defined, any tile <> type 0 is a wall. – Если задано, любая плитка <> 0 является стеной

Первая используется, чтобы установить номер графики для врагов 7-го типа. Вторая – чтобы враги преследовали персонажа только по тайлам нулевого типа. Если к последней команде поставишь комментарий, то поведение врага будет такое же, как сейчас: они будут преследовать персонажа по всем тайлам, и останавливают их только тайлы 8-го типа.

Детали движка скриптов
Да, мы здесь придумали много новых деталюшек. Но давайте дождемся главы, в которой начнем объяснять движок скрипта.

Исправления и улучшения
Мы к тому же полностью переписали часть движка, которая управляла выстрелами, чтобы теперь столкновение было более точным и занимало меньше места. Мы также разобрались с некоторыми багами и поменяли некоторые части кода, еще больше оптимизировав его работу. До этой оптимизации игра Sgt. Helmet не помещалась в памяти, ну ни за что. Так что крутяк, чувак!

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

Поменяй название папки твоей игры – ну не знаю, напиши «-old» в конце.
Подготовь новую папку так же, как делал раньше, т.е. разархивируй ее, поменяй название папки игры, поменяй название /dev/churromain.c и script/churromain.spt на название твоей игры и измени make.bat, поменяв %1 на название твоей игры. Все точно так же, как раньше.
Скопируй графику, карты и архивы врагов из твоей старой папки в новую, т.е. все, что находится в gfx/,  /map и /enems
Снова измени config.h – надо открыть новый и старый /dev/config.h и сделать в новом все, так же как и в старом. Обрати внимание на новые характеристики: поставь комментарий к тем, которые тебе не нужны или попробуй их поиспользовать, или что тебя больше вставляет.
Снова скопируй архивы твоей игры из старой папки /dev в новую. То есть: tileset.h, spriteset.h, title.bin, marco.bin (если используешь), ending.bin, mapa.h и enems.h
И всё. Теперь только надо проверить, что все сделано правильно: открываешь командную строку и выполняешь make.bat… Если не работает, проверь все шаги.

И в следующий раз перейдем к нашим любимым скриптам. А пока ждешь, можешь поиграть в Sgt. Helmet!

ОБЪЯВЛЕНИЕ

Благодаря Fabio Didone, который следит за нашим семинаром и создает свою собственную игру, мы сообразили, что в последней версии Чуррера оказался небольшой баг, который нарушает работу команды ONLY_ONE_OBJECT. Мы обновили пакет 3.99.1, исправив ошибку. Теперь можно загрузить новый архив по традиционной ссылке:

http://www.mojontwins.com/churrera/mt-c … 3.99.1.zip (скачать локально: mt-churrera-3.99.1)

Если вы уже начали делать вашу игру, вам не придется заново все собирать. Достаточно прописать mainloop.h в новой версии, включенной в эту папку.

P.S. На заставке этой статьи изображено испанское печенье под названием “Чуррос”.

9

Чуррера 3.99.2

http://zxaaa.net/store/images/churros1-384x288.jpg

Эта глава является своеобразным окончанием “описания дополнений” к Чуррере новой версии, в которой вы узнаете ещё больше крутых штук, которые можно реализовать с помощью этого современного игрового движка.

Прежде всего, скачайте соответствующие материалы для этой главы, нажав на ссылку ниже:

http://www.mojontwins.com/churrera/mt-c … 3.99.2.zip (скачать локально: mt-churrera-3.99.2)

Что, опять? А как же глава со скриптами?
Да, я знаю, что мы вам обещали главу про скрипты и еще кучу вещей, но нам показалось неправильным продолжать развивать Чурреру, не дав вам возможность воспользоваться нашими новшествами. Что это значит? Возможно и ничего, возможно, вам в лучшем случае понадобятся только отдельные из новых функций, которые мы сегодня будем объяснять, но немножко терпения. Глава о скриптах очень важная, и мы не хотим ее делать абы как. Очень скоро мы начнем делать первые наброски. А тем временем, можешь глянуть сюда. Но сначала вернись в прошлую главу, в которой объясняется, как обновить Чурреру твоей игры до новой версии.

Таймеры
Мы добавили в Чурреру таймер, который можно использовать как в автоматическом режиме, так и через скрипт. Таймер задает изначальное значение, ведет обратный отсчет, может заново запускаться, может конфигурироваться, когда каждый из фреймов  заканчивается, и что происходит, когда это случается. В config.h, как обычно:

#define TIMER_ENABLE

Вместе с TIMER_ENABLE включается код, необходимый для управления таймером. Этот код потребует некоторых дополнительных команд, которые определяют его функционирование:

#define TIMER_INITIAL 99
#define TIMER_REFILL 25
#define TIMER_LAPSE 32

TIMER_INITIAL определяет изначальное значение таймера. Иконки дополнительного времени, размещенные под видом тайлов 5-го типа, добавляют дополнительное время, прописанное командой TIMER_REFILL. Максимальное значение таймера, как для начального, так и для дополнительного, равняется 99. Чтобы контролировать интервал между каждым счетным отрезком таймера, прописываем в команде TIMER_LAPSE количество фреймов, которые должны пройти.

#define TIMER_START

Если TIMER_START включен, таймер будет включен с самого начала. К тому же у нас есть дополнительные команды, которые определяют, что произойдёт, когда таймер дойдет до нуля. Достаточно убрать комментарии у тех команд, которые мы будем применять:

#define TIMER_SCRIPT_0

Если мы прописали эту команду, при достижении нуля таймером начнется выполнение серии специальных скриптов, ON_TIMER_OFF. Это идеальное решение – отдать все управление таймером скриптам, как это сделано в Cadàveriön.

//#define TIMER_GAMEOVER_0

Если работает эта команда, когда таймер дойдет до нуля, игра закончится (“GAME OVER”).

//#define TIMER_KILL_0
//#define TIMER_WARP_TO 0
//#define TIMER_WARP_TO_X 1
//#define TIMER_WARP_TO_Y 1

Если работает команда TIMER_KILL_0, то при достижении нуля, будет теряться одна жизнь. Если к тому же прописать TIMER_WARP_TO, то изменится и окно: игрок появится в координатах TIMER_WARP_TO_X и TIMER_WARP_TO_Y. Используй эту опцию, если эти данные будут зафиксированы в течение всей игры. В Cadàveriön, например, мы изменили код, чтобы все управлялось скриптами.

//#define TIMER_AUTO_RESET

Если работает эта опция, то таймер автоматически вернется к максимальному значению по достижении нуля. Если ты предпочитаешь отдать контроль скрипту, лучше оставить у этой опции комментарий.

#define SHOW_TIMER_OVER

Если включена эта опция, при том, что одна из этих команд активирована (TIMER_SCRIPT_0 или TIMER_KILL_0), то когда таймер дойдет до нуля, покажется надпись “TIME’S UP!” («ВРЕМЯ КОНЧИЛОСЬ!»).

Скрипты:

Как мы уже говорили, таймер может управляться через скрипт. Если мы решили обратиться к этой возможности и активируем TIMER_SCRIPT_0, чтобы команда ON_TIMER_OFF выполнялась по достижении таймером нуля, скрипт получает полный контроль, что самое прикольное.

К тому же мы добавляем следующие проверки и команды:

Проверки:

IF TIMER >= x
IF TIMER <= x

Будут выполняться, если значение таймера больше и равно или меньше и рано заданной величине, соответственно

Команда:

SET_TIMER a, b

Она служит, чтобы указать значения TIMER_INITIAL (a) и TIMER_LAPSE (b) в скрипте

Запуск таймера:

TIMER_START

Остановка таймера:

TIMER_STOP

Контроль передвигаемых блоков
Мы улучшили движок, чтобы можно было делать больше разных вещей с тайлом 14 10-го типа (передвигаемый тайл), чем просто сдвигать его, или чтобы он преграждал путь врагам. Теперь мы можем сказать движку, чтобы он запускал команду PRESS_FIRE текущего окна в скрипте сразу после того, как будет сдвинут передвигаемый блок. К тому же, номер тайла, который сдвигается, и финальные координаты сохраняются в трех флагах, которые мы можем конфигурировать, чтобы потом использовать их в скрипте для проведения проверок.

Такая система используется, например,  в скрипте Cadàveriön для проверки, что статуи стоят на пьедесталах.

Вспомним, что у нас было прописано раньше:

#define PLAYER_PUSH_BOXES
#define FIRE_TO_PUSH

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

Теперь посмотрим на новые команды:

#define ENABLE_PUSHED_SCRIPTING
#define MOVED_TILE_FLAG 1
#define MOVED_X_FLAG 2
#define MOVED_Y_FLAG 3

Если активировать ENABLE_PUSHED_SCRIPTING, перемещаемый тайл и его координаты сохраняются в специальных флагах для команд MOVED_TILE_FLAG, MOVED_X_FLAG и MOVED_Y_FLAG соответственно. В отображаемом коде передвигаемый тайл сохраняется во флаге 1, а его координаты во флагах 2 и 3.

#define PUSHING_ACTION

Если работает эта команда, при передвижении блока выполняются команды PRESS_FIRE AT ANY и PRESS_FIRE текущего окна скрипта. В этом случае выполняется условие “JUST_PUSHED”, и через скрипт можно контролировать, что происходит при передвижении блока.

Мы советуем изучить скрипт Cadàveriön, к тому же он отличный пример использования таймера и контроля передвигаемых блоков, в результате получается очень сложный скрипт, использующий кучу передовых технологий. Точнее, будет использовать, когда мы закончим этот семинар :*)

Проверка выхода с карты
Мы рекомендуем установить границы карты, чтобы игрок не мог сбежать с карты, и чтобы движок не устраивал фокусы, но если твоя карта узкая, возможно, ты захочешь использовать все окно. В этом случае, можешь активировать:

#define PLAYER_CHECK_MAP_BOUNDARIES

Это добавит дополнительные проверки и не позволит игроку исчезнуть с карты. Но! Если можешь избежать использования этой опции, будет лучше: сэкономишь место.

В подарок: кастомизированный тип врага
До сегодняшнего дня мы враги 6-го типа не имели кода, но мы подумали, что нам ничего не стоит добавить хотя бы один, например. Он ведет себя, как летучие мыши из Cheril the Goddess. Чтобы использовать его, отправь его в Разместитель врагов 6-го типа и используй эти команды:

#define ENABLE_CUSTOM_TYPE_6
#define TYPE_6_FIXED_SPRITE 2
#define SIGHT_DISTANCE 96

Первая активирует опцию, вторая определяет, какой спрайт будет использоваться (выбранный спрайт минус 1: то есть, если хочешь третий спрайт врага, то ставь 2. Сорри за мешанину, но зато это экономит память). Третья говорит, за сколько пикселей этот жучок тебя увидит. А когда увидит, будет преследовать. Если не увидит, вернется на свое место (куда ты его поставил в Разместителе).

Это дополнение к тому же использует команды врагов 5-го типа:

#define FANTY_MAX_V 256
#define FANTY_A 12

Здесь определяется ускорение и максимальная скорость твоих представителей 6-го типа. Если будешь использовать и пятый тип тоже и хочешь другие значения, будь мужиком и переделай движок.

Конфигурация клавиатуры / джойстика под две кнопки
Есть игры бокового типа, в которые лучше играется двумя кнопками: одна для прыжка и вторая для выстрелов. Если активируешь эту команду:

#define USE_TWO_BUTTONS
#define FANTY_A 12

Клавиатура по умолчанию будет вот такой, вместо привычной:

A – Влево
D – Вправо
W – Вверх
S – Вниз
N – Прыжок
M – Стрелять

Если выбран джойстик, то FIRE и M стреляют, N прыгает.

Выстрелы вверх и по диагонали для бокового вида
Теперь можно дать игроку возможность стрелять вверх или по диагонали. Чтобы прописать это:

#define CAN_FIRE_UP

Эта конфигурация лучше работает с USE_TWO_BUTTONS: таким образом, отделяем выстрел вверх от прыжка.

Если не нажимаешь вверх, то игрок выстрелит в ту сторону, в которую смотрит. Если нажмешь вверх во время выстрела, игрок выстрелит вверх. Если к тому же нажмешь на кнопку направления, персонаж выстрелит в указанном направлении.

Маски пуль
Для увеличения скорости, пули не имеют масок. Это хорошо работает, если фон, на котором происходит действие, темный (мало активных пикселей INK). Однако есть ситуации, в которых это условие не выполняется, и выглядит это не очень. В этом случае, мы можем активировать маски пуль:

#define MASKED_BULLETS

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

10

Создай свою игру на ZX Spectrum.
Часть 8 – Начинаем работу со скриптами

Практически не дав вам времени отдышаться, друзья из Mojon Twins снова вернулись со своим семинаром по созданию игр на Чуррере. Эту главу мы посвятим скриптам. Целая Вселенная возможностей, которая требует от нас максимальной собранности. Работа будет тяжелая, и мы все это знаем, так что заточите поострее ваши ножи. Ножи – в зубы, и начинаем главу, которую многие так ждали.

Глава 8: Начинаем работу со скриптами
Прежде всего, скачайте соответствующие материалы для этой главы, нажав на ссылку ниже:

http://www.mojontwins.com/churrera/chur … itulo8.zip (скачать локально: churreratut-capitulo8)

Чувак, ну наконец-то!
Ага, уже. Только ты еще об этом пожалеешь. Потому что все будет настолько неприятно и болезненно, насколько тебе хватит воображения. Нет, серьезно все не так страшно: немножко вазелина, и ты почти ничего не почувствуешь. В этой первой части объясним, как собирается система, чтобы ты понимал, что тут есть, для чего служит и как работает – и в конце рассмотрим примеры детсадовского уровня, правда очень-очень легкие. В следующей части мы закончим скрипт Dogmole Tuppowski, и с этого момента начнем изучать, что можно вытворять с помощью скрипта. Потому что натворить можно много разного.

Ну что ж, приступим!
Давай. Что такое скрипт Чурреры? Это просто набор проверок с соответствующими действиями, организованными по секциям, которые позволяют определить сценарий твоей игры. Или, проще говоря, то, что происходит, и то, что должно произойти, чтобы все было хорошо – или плохо.

То есть без скрипта у тебя есть примитивная базовая версия игры. Собрать Х предметов, чтобы выиграть, убить N врагов… Чтобы выйти на новый уровень крутости, необходимо включить в сценарий игры проверки и связанные с этими проверками действия: если мы находимся там-то и сделали то-то, то дверь и откроется. Если зайдем на такой-то экран и поговорим с тем-то персонажем, появится текст «ПРИВЕТ, ЧЁ ТВОРИШЬ», и ты услышишь определенный звук. Вот мы о чем тут вещаем.

Скрипт тебе нужен для всех действий начиная с размещения красивого тайла в четвертом окне и текста «ТЫ ДОМА» до реагирования на твои действия в одном окне, проверки того, что ты уже сделал, подтверждения, что ты сдвинул такой-то тайл, а еще после этого включается таймер – или чтобы поменять сценарий или что тебе взбредет в голову.

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

И это не шутка!

Но это программирование.

Правда, чуваки, одно дело, это запрограммировать сценарий на языке Си и прошить его в движок, и совсем другое дело – иметь язык, специально созданный для  описания сценария, и который так просто выучить и освоить. Потому что я уверен, что многим будет знакомо то, о чем мы будем говорить, особенно если вы когда-то сталкивались с PAWS или GAC или выпивали с каким-нибудь разработчиком игр. Потому что нам, мохонам, очень в кайф заново изобретать колесо, и в результате у нас есть супер система, наиболее используемая для этих функций, из всех, когда-либо существовавших в истории. Ты сам увидишь.

Давай, расскажи мне, как это работает.

Договорились. Посмотрим, смогу ли я это сказать на одном дыхании, а потом мы разберемся во всем по отдельности: скрипт состоит из секций. Каждая секция – это просто набор условий. Каждое условие состоит из списка проверок и списка команд.  Если каждое из условий из этого списка выполняется, то каждая команда также выполняется в определенном порядке. Движок игры будет обращаться к движку скриптов при определенных условиях, выполняя одну из этих секций. Выполнить условие – значит выполнить проверки каждого условия из списка проверок и, если они выполняются, выполнить по порядку команды из списка команд. Это важный концепт,  который надо четко понимать.

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

ENTERING SCREEN n, где n – номер экрана. Эта команда выполняется при входе на экран, когда создается сценарий, инициализируются враги и размещаются хотспоты. Можем его использовать, чтобы изменять сценарий или вносить вариативные варианты. Например, в окне 3 можно разместить скрипт, который проверит, убили ли мы всех врагов и, если нет, ставит препятствие, через которое не можем пройти.

ENTERING ANY: выполняется для всех окон, сразу перед ENTERING SCREEN n. То есть, когда ты заходишь на третий экран, сначала выполняется секция ENTERING ANY (если она прописана в скрипте), и только потом выполняется секция ENTERING SCREEN 3 (если она прописана в скрипте).

ENTERING GAME: выполняется только один раз в начале игры. Это первый выполняемый скрипт. Можешь его использовать, чтобы, например, изменять величины изменяемых значений. Скоро мы увидим, как.

PRESS_FIRE AT SCREEN n, где n – номер экрана. Выполняется при различных вариантах в окне n: если игрок нажимает на кнопку действия при передвижении блока, при активированной команде PUSHING_ACTION, или при входе в специальную зону, определенную скриптом под названием “fire zone” (это мы тоже объясним), если активна команда ENABLE_FIRE_ZONE. Обычно эти секции используются, чтобы реагировать на действия игрока.

PRESS_FIRE AT ANY: выполняется при всех предыдущих ситуациях для любого окна, сразу перед нажатием PRESS_FIRE AT SCREEN n. То есть, если нажимаем кнопку действия на 7 экране, сначала выполняются условия PRESS_FIRE AT ANY, а сразу за этим – PRESS_FIRE AT SCREEN 7.

ON_TIMER_OFF: выполняется, когда таймер обнуляется, если он активирован, и мы прописали это командой TIMER_SCRIPT_0.

Для версии 3.99.2 это все возможные секции, но мы добавим еще больше в следующих версиях. Например, при уничтожении врага. Но пока такого скрипта нет.

Конечно, необязательно использовать все возможные секции. Движок будет выполнять секцию, только если она существует. Например, если на экране 8 нечего делать, то для окна 8 можно не прописывать секций. Если нет никаких общих для всех окон действий при входе на экран, то не будет и секции ENTERING ANY. И так далее. Если нечего выполнять, то движок ничего и не выполнит.

Так, давайте вспомним: зачем нам такая куча секций и прочей фигни? Все просто: с одной стороны, чтобы проверки и действия менялись от окна к окну. Но это детали. Самое важное, это что у нас 8-битный экран, и мы не можем себе позволить постоянно делать все проверки. У нас нет лишних фреймов, поэтому мы оставим проверки только для отдельных моментов: никто не умрет, если смена экрана задержится на несколько миллисекунд, или если действие произойдет не сразу после нажатия кнопки действия.

Сохраняем значения: флаги

Перед тем как продолжать, нам надо объяснить еще одно понятие: флаги, которые являются ничем иным, как изменяемыми, которые могут сохранять значения – как раз для этого у нас и есть флаги. Изначально имеется 16 флагов под номерами от 0 до 15, но этот номер можно легко изменить, поменяв определение в definitions.h (ищи #define MAX_FLAGS и поменяй 16 на другое значение).

Каждый флаг сохраняет значение от 0 до 255, что нам дает гораздо больше возможностей. Большую часть времени мы сохраняем только двоичные значения (0 или 1).

В скрипте бОльшая часть проверок и команд имеют цифровые значения. Например, IF PLAYER_TOUCHES 4, 5 оценит с точностью, дотронулся ли игрок до координат (4, 5). Если перед номером поставить #, то это будет относиться к значению соответствующего флага, чтобы IF PLAYER_TOUCHES #4, #5 с точностью оценил, дотронулся ли игрок до ячейки координат, сохраненных во флагах 4 и 5, какое бы это ни было значение.

Этот уровень опосредованности (выучи это слово, чтобы использовать его на дискотеках: тёлочки обожают программистов, знакомых с этим понятием) действительно полезен, потому что таким образом ты можешь сэкономить объем кода. Например, в Cadàveriön это позволяет соединить в одной секции связь между количеством размещенных колонн и исчезновением решетки, блокирующей выход из каждого окна: все координаты сохранены во флагах, и мы используем знак #, чтобы добраться до этих значений в проверках.

Не волнуйся, если ты сейчас не до всего допёр, скоро мы все разжуём.

Фух.

Много информации? Я понимаю. Но когда увидишь, как это работает, до тебя сразу дойдет. Мы начнем с самых простых примеров скрипта, рассмотрев некоторые из секций, необходимых для нашего Dogmole, которые мы будем потихоньку собирать. Мы посвятим этому эту и следующую главу. Потом мы объясним в тематическом виде все возможные проверки и команды.

Как активировать скрипт? Куда его вносить?
Чтобы активировать скрипт, нам надо выполнить 2 вещи: сначала его активировать и отконфигурировать в config.h, а затем изменить наш make.bat, чтобы включить его в проект. Начнем с config.h. Вот соответствующие команды для активации и конфигурации:

#define ACTIVATE_SCRIPTING // Активирует возможность скриптинга и штуки, связанные с флагами.
#define SCRIPTING_DOWN // Использовать ВНИЗ как кнопку действия.
//#define SCRIPTING_KEY_M // Использовать M как кнопку действия.
//#define SCRIPTING_KEY_FIRE // Использовать ОГОНЬ как кнопку действия.
//#define ENABLE_EXTERN_CODE // Разрешает расширенный режим с EXTERN n
//#define ENABLE_FIRE_ZONE // Позволяет определить зону, которая автонажимает “ОГОНЬ”

Первая команда, ACTIVATE_SCRIPTING, как раз и активирует движок скрипта и добавит необходимый дополнительный код, чтобы выполнялась нужная секция скрипта в нужный момент. Эта как раз то, что нам нужно активировать, и без размышлений.

Из трех следующих команд мы должны активировать только одну. Они определяют, какая кнопка будет кнопкой действия, т.е. которая будет запускать скрипты PRESS_FIRE AT ANY и PRESS_FIRE AT SCREEN n. Первая, SCRIPTING_DOWN, конфигурирует кнопку «вниз». Это отлично работает в играх с боковым видом, т.к. эта кнопка больше ни для чего не используется. Вторая, SCRIPTING_KEY_M, привязывает клавишу «М» к скрипту. Третья, SCRIPTING_KEY_FIRE, конфигурирует для этого кнопку выстрела (или кнопку джойстика). Конечно, если в твоей игре есть выстрелы, ты не можешь использовать эту опцию. А если можешь, то сам виноват.

Следующая команда – ENABLE_EXTERN_CODE. Обычно оставляем ее дезактивированной, только если ты не магистр Чурреры. Есть специальная команда скрипта, EXTERN n, где n – номер. Этот скрипт вызывает функцию системы Си, расположенную во внешнем архиве extern.h, используя этот номер. Благодаря этой функции можно добавить код системы Си, если тебе не терпится  добавить различные штуки. Например, D_Skywalk использовал это в Justin and the Lost Abbey для добавления кода, который рисует собранные части меча в экране маркировки. Если тебе не нужно программировать дополнительное поведение в системе Си, оставь эту функцию дезактивированной – это сэкономит тебе пару байтов.

Наконец, ENABLE_FIRE_ZONE служит для определения специального прямоугольника внутри игровой зоны текущего экрана. Обычно используем ENTERING SCREEN n, чтобы определить зону, использующую команду SET_FIRE_ZONE x1, y1, x2, y2. Когда игрок находится в этой зоне, выполняются скрипты PRESS_FIRE AT ANY и PRESS_FIRE AT SCREEN n текущего экрана. Это действительно удобно для выполнения действий – и игроку не приходится нажимать на кнопку действия. Мы используем эту функцию в Sgt. Helmet, чтобы устанавливать бомбы в финальном окне или показывать сообщение «ПРОДАЮ ПОДЕРЖАННЫЙ МОТОЦИКЛ». Если ты считаешь, что тебе это нужно, активируй эту команду. Если нет, не активируй ее и сэкономь место. Не волнуйся, мы еще раз объясним это. Следующее действие – это отконфигурировать make.bat, активировав компиляцию и добавление скрипта. Если откроешь make.bat, увидишь, что в начале есть отсылка к msc. Это компилятор скриптов, который получает название архива скрипта, название выхода (msc.h) и общее количество окон в игре:

echo ### COMPILANDO SCRIPT ###
cd ..script
msc cadaver.spt msc.h 20
copy *.h ..dev

Название твоего скрипта – такое же, как название твоей игры с расширением .spt. Архив находится в script. Если зайдешь в script, увидишь churromain.spt. Переименуй его, чтобы название совпадало с названием твоей игры (такое же как у твоего архива .c в dev). Не ошибись в количестве окон, это очень важно. Если перепутаешь, код выполнения скриптов будет неправильно сгенерирован. Для нашего Dogmole архив будет devdogmole.spt, и в make.bat прописываем:

echo ### COMPILANDO SCRIPT ###
cd ..script
msc dogmole.spt msc.h 24
copy *.h ..dev

Потому что в нашем Dogmole 24 окна.

Если теперь перейдешь в script и откроешь архив со скриптом (который раньше назывался churromain.spt и которому ты дал называние своей игры) увидишь, что он пустой, ну или почти. В нем только скелет одной секции. Выглядит примерно так:

# Título tonto
# Copyleft 201X tu grupo roneón soft.
# Churrera 3.1

# flags:
# 1 –

ENTERING GAME
IF TRUE
THEN
SET FLAG 1 = 0
END
END

Вот здесь-то мы и начинаем писать наш скрипт. Посмотри, как он выглядит: это секция ENTERING GAME, которая выполняется при начале игры. В этой секции только одно условие. Это условие имеет только одну проверку: IF TRUE, которая всегда будет выполняться. Затем идет THEN – отсюда и до слова END идет список команд. В нашем случае команда только одна: SET FLAG 1 = 0, которая устанавливает флаг 1 в 0.

Этот скрипт абсолютно ничего не делает. И более того, из-за него система с самого начала ставит все флаги на 0, так что тебе не надо их обнулять. И зачем нам это? Блин, не знаю, просто чтобы было. Поэтому первое, что ты сделаешь, это УДАЛИШЬ ЕГО.

Интересно будет поменять эту часть. Строчки, начинающиеся с # (это может быть и не #, можешь поставить, например ; или ‘ или // или все, что тебе взбредет в голову), – это комментарии. Привыкай ставить комментарии в твоих строчках. Не ставь комментарии после проверки или команды, потому что компилятор может запутаться и увидеть то, чего там нет. И прежде всего привыкай оставлять комментарии. Так ты сможешь вспомнить, что делал 3 дня назад, до попойки и бурной ночи с этой брюнеточкой с ресепшена.

Так как пока изменяемые величины (флаги) определяются номером (я хочу доработать компилятор, чтобы давать им другие значения, как предложил D_Skywalk), было бы здорово сделать список, что делает каждый из них, чтобы нам потом не мучиться. И я это сделал, глянь:

# Cadàveriön

# Copyleft 2013 Mojon Twins

# Churrera 3.99.2

# flags:

# 1 – Тайл для передвигаемого блока

# 2, 3 – координаты X и Y

# 4, 5 – координаты X и Y тайла “retry”

# 6, 7 – координаты X и Y тайла двери

# 8 – количество завершенных окон

# 9 – количество статуй, которые нужно разместить

# 10 – количество размещенных статуй

# 11 – Уже покинули подъезд

# 12 – Окно, в которое мы возвращаемся по завершении отведенного времени

# 13, 14 – Координаты, в которые возвращаемся… бла-бла-бла

# 15 – Пол

# 0 – сохранено значение 8

# 16 – Продаю подержанный мотоцикл

Видишь? Классно знать, с чем имеешь дело.

Мои первые условия
Теперь, когда мы знаем, что есть в нашем арсенале, начинаем наш скрипт. Видим базовый синтаксис. Именно отсюда начинаем рисовать наш скрипт:

СЕКЦИЯ

ПРОВЕРКИ

THEN

КОМАНДЫ

END

END

Как мы видим, каждая секция начинается с названия секции и заканчивается END. Между названием секции и END находятся условия, которые ее составляют, которых может быть одно или несколько. Каждое условие состоит из списка проверок, по одной на строчку, слова  THEN, списка команд, по одной на строчку, и слова END. После этого не может стоять дополнительных условий.

Вспомни, как это работает: выполнение секции соответствует выполнению каждого условия, по порядку. Выполнить условие – это выполнить все проверки из списка. Если ни одно не выпадает, то есть, все выполняются, выполняются все команды из списка.

Чтобы посмотреть как это выглядит, создадим простой скрипт, который добавляет декорации в некоторые окна. Расширим тайлсет Dogmole, включив новые тайлы, которые мы не расположили на карте (потому что мы уже использовали 16 тайлов, т.е. максимальное количество), – добавим их через скрипт. Это наш новый расширенный скрипт:

http://zxaaa.net/store/images/dogmole-full-tileset-10311127251.png

(ты уже знаешь, что делать: расположи их в нужном порядке, отправь их на страницу кода, загрузи  в SevenuP, сгенерируй код и перенеси его в /dev/tileset.h).

Здесь у нас куча вещей, которые мы будем размещать через скрипт. Идеальное место, чтобы это сделать, это секции ENTERING SCREEN n окон, которые мы хотим украсить, и которые выполняются, когда все остальное уже на месте: фон уже нарисован, чтобы мы могли поверх нарисовать наши тайлы. Начнем украшать окно под номером 0, куда надо доставлять ящики. Нам надо разместить  подиум из тайлов 22 и 23 и добавим еще кое-какие декорации: сосуды (29), несколько полок (20 и 21), несколько коробок (27 и 28), доспехи (32 и 33), лампочку на проводе (30 и 31). Начнем создавать секцию ENTERING SCREEN 0 в нашем scriptdogmole.spt:

# Вестибюль университета

ENTERING SCREEN 0

END

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

# Вестибюль университета

ENTERING SCREEN 0

# Декорации и подиум

IF TRUE

THEN



END

END

Это значит, что всегда, когда входим на экран 0, выполняются команды из списка команд этого условия, и единственное условие ВСЕГДА будет выполняться.

Команда для добавления тайла в окно выглядит так:

SET TILE (x, y) = t

Где (x, y) – координата (помнишь, у нас 15 x 10 тайлов в окне, так что х может быть от 0 до 14, а у – от 0 до 9), а t – номер тайла, который мы хотим нарисовать. Открываем карту в mappy, чтобы считать ячейки и определить, где будем дорисовывать тайлы, и размещаем сначала подиум, а потом все остальные декорации:

# Вестибюль университета

ENTERING SCREEN 0

# Декорации и подиум

IF TRUE

THEN

# Подиум

SET TILE (3, 7) = 22

SET TILE (4, 7) = 23

# Декорации

SET TILE (1, 5) = 29

SET TILE (1, 6) = 20

SET TILE (1, 7) = 21

SET TILE (6, 6) = 20

SET TILE (6, 7) = 21

SET TILE (7, 7) = 28

SET TILE (1, 2) = 27

SET TILE (1, 3) = 28

SET TILE (2, 2) = 29

SET TILE (2, 3) = 27

SET TILE (3, 2) = 32

SET TILE (3, 3) = 33

SET TILE (9, 1) = 30

SET TILE (9, 2) = 30

SET TILE (9, 3) = 31

END

END

Отлично, ты написал свое первое условие. Пока не слишком сложно, правда? Я так полагаю, что, чтобы удовольствие было полным, ты хочешь еще и посмотреть, как это работает. Хорошо: добавим еще несколько кодов, которые потом уберем из финальной версии, и которые будем использовать, чтобы перейти сразу в нужное окно при начале игры, – и проверим, все ли мы сделали правильно.

Если помнишь, одна из возможных секций, которую можем добавить к скрипту, выполняется сразу в начале игры: ENTERING GAME, которая сначала показывается пустой, и которую мы удалили, потому что она нам не нужна. Ну что, давайте тогда сделаем ENTERING GAME, который позволит нам сразу перейти сразу на экран под номером 0  и проверить, что мы расположили все тайлы в командах условия секции ENTERING SCREEN 0. Так что добавим этот код (можешь добавить его куда хочешь, но я обычно оставляю его в начале. Все равно, куда его поставишь, но всегда удобно соблюдать порядок).

ENTERING GAME
IF TRUE
THEN
WARP_TO 0, 12, 2
END
END

Что это нам дает? Благодаря этому в начале игры выполняется список условий из одного единственного условия, которое всегда будет выполняться (потому что имеет IF TRUE) и которое переносит нас в координаты (12, 2) окна 0 – это роль команды WARP:

WARP_TO n, x, y

Она нас переносит в окно n, в координаты (х, у).

Что произойдет? Ого! Это просто: когда игрок начинает игру, выполняется секция ENTERING GAME. Единственное, что выполняет эта секция – это переносит игрока в позицию (2, 2) и меняет окно на окно под номером 0. Так что при входе на экран 0 выполняется секция ENTERING SCREEN 0, которая дорисовывает дополнительные тайлы. Попробуем! Скомпилируй игру и запусти ее. Если все работает, то персонаж должен появиться в украшенном окне 0:

http://zxaaa.net/store/images/dogmole-script-1-28131.png

Вах! Черт, все отлично! Ещё, ещё! Нарисуем еще тайлы, чтобы украсить и остальные окна. Таким же образом, как мы украсили окно 0, украсим и окно 1, установив табличку Университета Мискатоник (тайлы 24, 25 и 26) и доспехи (тайлы 32 и 33):

# Коридор университета
ENTERING SCREEN 1
# Табличка “Мискатоник” и т.д.
IF TRUE
THEN
SET TILE (7, 2) = 24
SET TILE (8, 2) = 25
SET TILE (9, 2) = 26
SET TILE (1, 6) = 32
SET TILE (1, 7) = 33
SET TILE (13, 6) = 32
SET TILE (13, 7) = 33
END
END

Ну что, посмотрим! Измени ENTERING_GAME, чтобы зайти в окно 1, вместо 0.

Компилируем, выполняем… и вуаля!

http://zxaaa.net/store/images/dogmole-script-2-28321.png

Таким же образом добавляем код, чтобы добавить еще декорации на карту. По правде говоря, нам скоро надоело, и мы добавили финтифлюшки только в 6 окне (лампу) и в 18 (якорь на пляже). Может тебе захочется побольше добавить? Вот что мы прописали в оригинальной игре:

ENTERING SCREEN 6
IF TRUE
THEN
SET TILE (10, 1) = 30
SET TILE (10, 2) = 31
SET TILE (10, 4) = 35
END
END

ENTERING SCREEN 18
IF TRUE
THEN
SET TILE (4, 8) = 34
END
END

По-моему, до меня дошло
Пора сделать перерыв. Постарайся впитать эти знания, запомни все. Если что-то тут не понял, не торопись и подожди продолжения, в конце концов, ты все поймёшь. И как всегда, если хочешь что-то спросить – спрашивай!

В следующей главе начнется самое месиво: мы будем определять, убиты ли все колдуны, чтобы убрать камень от входа в университет, и пропишем логику, чтобы оставлять ящики в вестибюле.

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

11

Создай свою игру.
Часть 9 – Базовые скрипты

http://zxaaa.net/store/images/coordenadas2-04361-384x288.png

Вот наконец-то ожидаемая и наводящая ужас глава Семинара Чурреры: Базовые скрипты. В девятой главе мы рассмотрим в забавной и детализированной форме систему скриптов, позволяющую нам максимально персонализировать нашу игру с применением различных функций. За нашими клавиатурами открывается целый новый мир. Используйте эту «силу» с умом. И помните, что с великой силой приходит и великая ответственность.

Глава 9: Базовые скрипты

http://zxaaa.net/store/images/06meemaid-01291.gif

Базовые скрипты?
Да, так точно. А этой главе мы пропишем сценарий Dogmole Tuppowski

http://viva-games.ru/game/dogmole-tuppowski

и научимся некоторым базовым принципам скриптов.

Система скриптов Чуррера очень простая, и кажется сильно ограниченной, но приложив немного умения, ты сможешь делать и более сложные системы. К тому же, в каждой новой версии Чуррера мы добавляем новые функции, так что при некотором опыте ты сможешь делать для своих игр довольно мудреные сценарии. Правила Dogmole специально созданы простыми, чтобы показать простое поведение и на них научиться. Дальше мы увидим скрипты различных мохоновских игр, чтобы ты увидел, какие штуки нам удалось сделать.

Система скриптов содержит множество команд и различных проверок. Так как я не хочу из этого урока делать нескончаемый список, я предлагаю тебе обратиться к архиву motor_de_clausulas.txt, который находится в папке /script Чурреры: там есть список всего того, что msc может скомпилировать. Ни одного чурроса там не забыли.

Освежим наши знания
Мы помним, что скрипт состоит из секций, и каждая секция включает условия. Условие – это просто список проверок и команд: если все проверки получают положительный результат, команды выполняются.

Мы контролируем выполнение условий, прописывая их в ту или иную секцию. Мы помним, какие есть секции, и когда они выполняются:

ENTERING GAME: Эта секция выполняется только при начале игры.

ENTERING ANY: Эта секция выполняется при входе на каждый экран, и когда мы встаем на врага. Да, никакой логики тут нет, но это так, потому что так удобнее для некоторых явлений.

ENTERING SCREEN n: Эта секция выполняется при входе на экран N.

PRESS_FIRE AT ANY: Эта секция выполняется при нажатии на кнопку действия, не важно, в каком окне мы находимся.

FRESS_FIRE AT SCREEN n: Эта секция выполняется при нажатии на кнопку действия, если мы находимся в окне N, и когда мы встаем на врага. Тоже никакой логики, но это удобно.

ON_TIMER_OFF: Эта секция выполняется, если у нас есть таймер, который дошел до 0, и мы прописали это в config.h.

Вперед!
Перед тем как начать, вспомним, почему важно точно знать, что мы делаем. Так что вспомним сценарий нашей игры Dogmole Tuppowsky:

Сначала дверь университета закрыта, и чтобы ее открыть, надо убить всех тварей. Всего по всей карте разбросано 20 этих говнюков, особенно в нижней части (2 самых нижних уровня), и надо их всех замочить. Когда ты их всех убил, надо убрать камень, который мы разместили на карте перед входом в университет.

Дальше нам надо запрограммировать логику подиума, находящегося внутри университета. Если дотронуться до подиума, доставляя туда ящик, ящик вычитается из нашего арсенала, а флаг, считающий количество доставленных предметов, увеличивается. Когда это количество доходит до 10, игра выиграна.

Скрипт этой игры будет очень простой. Прежде всего, нам надо разместить несколько флагов для сохранения. В нашем случае, так как движок сам считает убитых, нам надо только считать доставленные ящики, и нам надо помнить, убран ли камень или нет. Мы будем использовать 2 флага: 1 и 3. Почему эти два, а не какие-нибудь другие? Да потому что. На самом деле, это абсолютно все равно.

Мы помним из прошлой главы, что было бы интересно определить, что делает каждый флаг в начале нашего скрипта:

# флаги:

# 1 – общий подсчёт предметов

# 3 – 1 = дверь университета открыта.

Считаем мертвяков
Видел название, а? Прежде всего, посмотрим, как считать мертвяков, чтобы избавиться от камня во втором окне. Для начала посмотрим, что нам надо убрать. Вот второе окно, и я показал камень, который нам надо убрать через скрипт:

http://zxaaa.net/store/images/piedro-02501.png

Если посчитаем, увидим, что камень занимает координаты (12, 7). Ставим их.

Мы говорили, что будем использовать флаг 3, чтобы помнить, убили ли мы уже всех врагов. Если флаг 3 равен 1, то это значит, что мы убили всех врагов, и в этом случае окно должно быть изменено: камень должен исчезнуть из точки, которую мы уже определили. Почему бы отсюда и не начать? Создаем условие, которое выполняется при входе на экран 2:

# Вход в университет
ENTERING SCREEN 2
# контроль двери университета.
IF FLAG 3 = 1
   THEN
        SET TILE (12, 7) = 0
   END
END
Особенно ничего нового в этом условии сценария мы не написали: речь идет о проверке значения флага. В случае IF TRUE, который мы до этого момента использовали, IF FLAG3 = 1, что позволяет проверить, что значение нашего флага 3 равно 1. В этом случае выполнится содержание условия: SET TILE (12, 7) = 0  – на месте, которое занимал камень, появится пустой тайл, заменив его. Таким образом, когда мы входим в это окно с флагом 3 = 1, камень исчезнет, и препятствия не будет. Концепция понятна?

Ну, тогда продолжаем. Мы сказали, что флаг 3 = 1 означает, что все враги убиты, но флаг 3 не станет равен 1 сам по себе. Нам необходимо создать правило, которое проставит это значение.

Так как в окне, где появляется камень, врагов нет, у нас не будет такой ситуации, в которой последний колдун будет убит в окне с камнем. То есть, мы всегда будем в другом окне, когда убьем последнего негодяя. Это значит, что лучшее место для проверки, все ли колдуны убиты, – это вход в любое окно, то есть наша секция ENTERING ANY. С той замечательной особенностью, что эта команда выполняется и когда мы наступаем на врага. Каждый раз как заходим на новый экран, проверяем, что количество убитых врагов равняется 20, и, если это условие выполняется, ставим флаг 3 = 1:

# Вход в университет
ENTERING ANY
IF ENEMIES_KILLED_EQUALS 20
IF FLAG 3 = 0
    THEN
    SET FLAG 3 = 1
        SOUND 7
        SOUND 8
        SOUND 9
        SOUND 7
        SOUND 8
        SOUND 9
    END
END
Благодаря этому получаем ровно то, что хотели. Посмотри на новую проверку: IF ENEMIES_KILLED_EQUALS 20 – она проверяет, равно ли количество убитых врагов (трупаков) двадцати. Если это верно, то следующим действием проверяем значение флага 3 (равно ли оно 0). Таким образом, мы удостоверяемся, выполняется ли это условие 1 раз, или, наоборот, при входе в любое окно.

Если условия выполнены, ставим флаг 3 = 1 (чего мы, собственно и добивались), а игра исполняет серию радостных звуков. Да, команда SOUND n исполняет звук n. Здесь речь идет о звуках движка. Можешь посмотреть, чему соответствует каждый номер в архиве beeper.h, в конце.

Так мы получили список первой части нашего сценария: если все враги убиты, ставим значение флага 3 равное 1. В окне 1, если флаг 3 равен 1, убираем камень.


Логика ящиков
Теперь нам осталось только прописать вторую часть сценария. Если помнишь, наш движок имеет конфигурацию ONLY_ONE_OBJECT. Это значит, что максимальное количество предметов, которые можем собрать за один раз = 1, т.е. можно взять только один ящик.

Цель игры – доставить 10 ящиков на подиум университета, соответственно, мы должны прописать в скрипте логику, которая позволяет нам применить следующий сценарий: если мы собираем предмет и активируем подиум, объект там остаётся, а счетчик доставленных предметов увеличивается, –  и в этом нам поможет флаг 1.

Если помнишь, наш подиум находится в окне 9: мы нарисовали его с помощью SET TILE нашего скрипта в секции ENTERING SCREEN 0. Он занимает координаты (3, 7) и (4, 7).

Теперь мы напишем часть скрипта, которая, при нажатии кнопки действия в окне 0, будет проверять, касается ли персонаж подиума, и есть ли в его арсенале предмет, чтобы «отнять» его и засчитать.

Прежде всего, мы должны определить касание подиума. Если он занимает один тайл (x, y), то все просто:

IF PLAYER_TOUCHES x, y
Если один из пикселей игрока касается тайла (х, у), это условие выполняется. Но проблема в том, что наш подиум занимает 2 тайла. Решением могло бы быть написание двух идентичных условий, одно PLAYER_TOUCHES 3, 7, и другое PLAYER_TOUCHES 4, 7, но это не будет нужно, так как у нас есть другие инструменты.

Чтобы проверить, что мы находимся внутри какой-либо области, у нас есть специальные проверки:

IF PLAYER_IN_X x1, x2
IF PLAYER_IN_Y y1, y2

http://zxaaa.net/store/images/coordenadas1-04151.png

Первая проверяет, находится ли координата х, в пикселях, верхнего левого угла квадрата спрайта нашего персонажа между х1 и х2. Вторая проверяет, находится ли координата у, в пикселях, верхнего левого угла квадрата спрайта нашего персонажа между у1 и у2.

Рассмотрим это на рисунке. Здесь мы видим область, определенную x1, x2 и y1, y2. Игрок будет «внутри» этой области, если пиксель, отмеченный красным (левого верхнего угла спрайта), находится «внутри» этой зоны.

Когда мы хотим проверить, что наш персонаж находится внутри прямоугольника, который занимают тайлы, мы используем следующую формулу, чтобы определить значения x1, x2, y1 и y2. Если (tx1,ty1) – координаты (в тайлах) верхнего левого угла прямоугольника и (tx2, ty2) – координаты (тоже в тайлах) нижнего правого угла, то получается вот что:

http://zxaaa.net/store/images/coordenadas2-04361.png

10.05.2015 // Статьи // Нет комментариев // Автор: Epsiloncool

Вот наконец-то ожидаемая и наводящая ужас глава Семинара Чурреры: Базовые скрипты. В девятой главе мы рассмотрим в забавной и детализированной форме систему скриптов, позволяющую нам максимально персонализировать нашу игру с применением различных функций. За нашими клавиатурами открывается целый новый мир. Используйте эту «силу» с умом. И помните, что с великой силой приходит и великая ответственность.

Глава 9: Базовые скрипты
meemaid

Базовые скрипты?
Да, так точно. А этой главе мы пропишем сценарий Dogmole Tuppowski и научимся некоторым базовым принципам скриптов.

Система скриптов Чуррера очень простая, и кажется сильно ограниченной, но приложив немного умения, ты сможешь делать и более сложные системы. К тому же, в каждой новой версии Чуррера мы добавляем новые функции, так что при некотором опыте ты сможешь делать для своих игр довольно мудреные сценарии. Правила Dogmole специально созданы простыми, чтобы показать простое поведение и на них научиться. Дальше мы увидим скрипты различных мохоновских игр, чтобы ты увидел, какие штуки нам удалось сделать.

Система скриптов содержит множество команд и различных проверок. Так как я не хочу из этого урока делать нескончаемый список, я предлагаю тебе обратиться к архиву motor_de_clausulas.txt, который находится в папке /script Чурреры: там есть список всего того, что msc может скомпилировать. Ни одного чурроса там не забыли.

Освежим наши знания
Мы помним, что скрипт состоит из секций, и каждая секция включает условия. Условие – это просто список проверок и команд: если все проверки получают положительный результат, команды выполняются.

Мы контролируем выполнение условий, прописывая их в ту или иную секцию. Мы помним, какие есть секции, и когда они выполняются:

ENTERING GAME: Эта секция выполняется только при начале игры.

ENTERING ANY: Эта секция выполняется при входе на каждый экран, и когда мы встаем на врага. Да, никакой логики тут нет, но это так, потому что так удобнее для некоторых явлений.

ENTERING SCREEN n: Эта секция выполняется при входе на экран N.

PRESS_FIRE AT ANY: Эта секция выполняется при нажатии на кнопку действия, не важно, в каком окне мы находимся.

FRESS_FIRE AT SCREEN n: Эта секция выполняется при нажатии на кнопку действия, если мы находимся в окне N, и когда мы встаем на врага. Тоже никакой логики, но это удобно.

ON_TIMER_OFF: Эта секция выполняется, если у нас есть таймер, который дошел до 0, и мы прописали это в config.h.

Вперед!
Перед тем как начать, вспомним, почему важно точно знать, что мы делаем. Так что вспомним сценарий нашей игры Dogmole Tuppowsky:

Сначала дверь университета закрыта, и чтобы ее открыть, надо убить всех тварей. Всего по всей карте разбросано 20 этих говнюков, особенно в нижней части (2 самых нижних уровня), и надо их всех замочить. Когда ты их всех убил, надо убрать камень, который мы разместили на карте перед входом в университет.

Дальше нам надо запрограммировать логику подиума, находящегося внутри университета. Если дотронуться до подиума, доставляя туда ящик, ящик вычитается из нашего арсенала, а флаг, считающий количество доставленных предметов, увеличивается. Когда это количество доходит до 10, игра выиграна.

Скрипт этой игры будет очень простой. Прежде всего, нам надо разместить несколько флагов для сохранения. В нашем случае, так как движок сам считает убитых, нам надо только считать доставленные ящики, и нам надо помнить, убран ли камень или нет. Мы будем использовать 2 флага: 1 и 3. Почему эти два, а не какие-нибудь другие? Да потому что. На самом деле, это абсолютно все равно.

Мы помним из прошлой главы, что было бы интересно определить, что делает каждый флаг в начале нашего скрипта:

# флаги:

# 1 – общий подсчёт предметов

# 3 – 1 = дверь университета открыта.

Считаем мертвяков
Видел название, а? Прежде всего, посмотрим, как считать мертвяков, чтобы избавиться от камня во втором окне. Для начала посмотрим, что нам надо убрать. Вот второе окно, и я показал камень, который нам надо убрать через скрипт:

piedro





Если посчитаем, увидим, что камень занимает координаты (12, 7). Ставим их.

Мы говорили, что будем использовать флаг 3, чтобы помнить, убили ли мы уже всех врагов. Если флаг 3 равен 1, то это значит, что мы убили всех врагов, и в этом случае окно должно быть изменено: камень должен исчезнуть из точки, которую мы уже определили. Почему бы отсюда и не начать? Создаем условие, которое выполняется при входе на экран 2:

# Вход в университет
ENTERING SCREEN 2
# контроль двери университета.
IF FLAG 3 = 1
   THEN
        SET TILE (12, 7) = 0
   END
END
Особенно ничего нового в этом условии сценария мы не написали: речь идет о проверке значения флага. В случае IF TRUE, который мы до этого момента использовали, IF FLAG3 = 1, что позволяет проверить, что значение нашего флага 3 равно 1. В этом случае выполнится содержание условия: SET TILE (12, 7) = 0  – на месте, которое занимал камень, появится пустой тайл, заменив его. Таким образом, когда мы входим в это окно с флагом 3 = 1, камень исчезнет, и препятствия не будет. Концепция понятна?

Ну, тогда продолжаем. Мы сказали, что флаг 3 = 1 означает, что все враги убиты, но флаг 3 не станет равен 1 сам по себе. Нам необходимо создать правило, которое проставит это значение.

Так как в окне, где появляется камень, врагов нет, у нас не будет такой ситуации, в которой последний колдун будет убит в окне с камнем. То есть, мы всегда будем в другом окне, когда убьем последнего негодяя. Это значит, что лучшее место для проверки, все ли колдуны убиты, – это вход в любое окно, то есть наша секция ENTERING ANY. С той замечательной особенностью, что эта команда выполняется и когда мы наступаем на врага. Каждый раз как заходим на новый экран, проверяем, что количество убитых врагов равняется 20, и, если это условие выполняется, ставим флаг 3 = 1:

# Вход в университет
ENTERING ANY
IF ENEMIES_KILLED_EQUALS 20
IF FLAG 3 = 0
    THEN
    SET FLAG 3 = 1
        SOUND 7
        SOUND 8
        SOUND 9
        SOUND 7
        SOUND 8
        SOUND 9
    END
END
Благодаря этому получаем ровно то, что хотели. Посмотри на новую проверку: IF ENEMIES_KILLED_EQUALS 20 – она проверяет, равно ли количество убитых врагов (трупаков) двадцати. Если это верно, то следующим действием проверяем значение флага 3 (равно ли оно 0). Таким образом, мы удостоверяемся, выполняется ли это условие 1 раз, или, наоборот, при входе в любое окно.

Если условия выполнены, ставим флаг 3 = 1 (чего мы, собственно и добивались), а игра исполняет серию радостных звуков. Да, команда SOUND n исполняет звук n. Здесь речь идет о звуках движка. Можешь посмотреть, чему соответствует каждый номер в архиве beeper.h, в конце.

Так мы получили список первой части нашего сценария: если все враги убиты, ставим значение флага 3 равное 1. В окне 1, если флаг 3 равен 1, убираем камень.

Логика ящиков
Теперь нам осталось только прописать вторую часть сценария. Если помнишь, наш движок имеет конфигурацию ONLY_ONE_OBJECT. Это значит, что максимальное количество предметов, которые можем собрать за один раз = 1, т.е. можно взять только один ящик.

Цель игры – доставить 10 ящиков на подиум университета, соответственно, мы должны прописать в скрипте логику, которая позволяет нам применить следующий сценарий: если мы собираем предмет и активируем подиум, объект там остаётся, а счетчик доставленных предметов увеличивается, –  и в этом нам поможет флаг 1.

Если помнишь, наш подиум находится в окне 9: мы нарисовали его с помощью SET TILE нашего скрипта в секции ENTERING SCREEN 0. Он занимает координаты (3, 7) и (4, 7).

Теперь мы напишем часть скрипта, которая, при нажатии кнопки действия в окне 0, будет проверять, касается ли персонаж подиума, и есть ли в его арсенале предмет, чтобы «отнять» его и засчитать.

Прежде всего, мы должны определить касание подиума. Если он занимает один тайл (x, y), то все просто:

IF PLAYER_TOUCHES x, y
Если один из пикселей игрока касается тайла (х, у), это условие выполняется. Но проблема в том, что наш подиум занимает 2 тайла. Решением могло бы быть написание двух идентичных условий, одно PLAYER_TOUCHES 3, 7, и другое PLAYER_TOUCHES 4, 7, но это не будет нужно, так как у нас есть другие инструменты.

Чтобы проверить, что мы находимся внутри какой-либо области, у нас есть специальные проверки:

IF PLAYER_IN_X x1, x2
IF PLAYER_IN_Y y1, y2

coordenadas

Первая проверяет, находится ли координата х, в пикселях, верхнего левого угла квадрата спрайта нашего персонажа между х1 и х2. Вторая проверяет, находится ли координата у, в пикселях, верхнего левого угла квадрата спрайта нашего персонажа между у1 и у2.

Рассмотрим это на рисунке. Здесь мы видим область, определенную x1, x2 и y1, y2. Игрок будет «внутри» этой области, если пиксель, отмеченный красным (левого верхнего угла спрайта), находится «внутри» этой зоны.

Когда мы хотим проверить, что наш персонаж находится внутри прямоугольника, который занимают тайлы, мы используем следующую формулу, чтобы определить значения x1, x2, y1 и y2. Если (tx1,ty1) – координаты (в тайлах) верхнего левого угла прямоугольника и (tx2, ty2) – координаты (тоже в тайлах) нижнего правого угла, то получается вот что:

coordenadas

С областью, определенной таким образом, значения x1, x2  у1, y2, которые мы должны использовать в скрипте,  определяются по следующим формулам:

x1 = tx1 * 16 - 15
x2 = tx2 * 16 + 15

y1 = ty1 * 16 - 15
y2 = ty2 * 16 + 15

Чтобы это увидеть, еще один рисунок. Обрати внимание, что я дорисовал спрайт поверх, чтобы ты увидел, что для «касания» тайлы должны быть в прямоугольнике, определенном координатами (x1, y1) и (x2, y2):

http://zxaaa.net/store/images/coordenadas3-05001.png

Да, если ты не привык программировать эти значения, это кажется тебе чертовой мешаниной, но на самом деле все будет проще, когда ты запомнишь формулу, а еще лучше – поймешь ее. Мы умножаем на 16, когда переходим от координат тайлов к координатам пикселей, потому что тайлы состоят из 16х16 пикселей. Суммирование и вычитание значения 15 делается, чтобы обеспечить «столкновение ячейки» спрайта.

Я знаю, что мы могли бы создать скрипт, чтобы несколько скрасить эти действия, но здесь, пусть и заставляя программиста самостоятельно выполнить пару математических действий, мы все же значительно упрощаем код, давая движку «замаскированные» данные.

Чтобы с этим покончить, перейдем к нашему случаю и выполним необходимые действия, используя данные из нашей игры. Здесь прямоугольник образуется только значениями тайлов в координатах (3, 7) и (4, 7). Угловые тайлы – это как раз эти 2 тайла, поэтому tx1 будет равняться 3, ty1 будет равняться 7, будет равняться 4 и ty2 будет равняться также 7. Таким образом, получаем формулы:

x1 = 3 * 16 - 15 = 33
x2 = 4 * 16 + 15 = 79

y1 = 7 * 16 - 15 = 97
y2 = 7 * 16 + 15 = 127

Итак, чтобы коснуться подиума, спрайт должен находиться между 33 и 79 по оси X и между  97 и 127 по оси Y. Теперь посмотрим, как это будет выглядеть на этом сложном графике: чтобы спрайт дотронулся до подиума, верхний левый пиксель квадрата его спрайта (отмечен красным) должен быть внутри зоны, которую мы определили:

http://zxaaa.net/store/images/coordenadas4-05361.png

Мы также должны проверить, что у нас есть ящик в инвентаре. Будет как-то так:

PRESS_FIRE AT SCREEN  0
        # Определяем подиум.
        # Определяем положение прямоугольника из пикселей
        # Затем проверяем, имеет ли игрок код предмета
        # Если все условия выполняются, снижаем количество объектов в инвентаре
        # и увеличиваем значение Флага 1
        IF PLAYER_IN_X 33, 79
        IF PLAYER_IN_Y 97, 127
        IF PLAYER_HAS_OBJECTS
        THEN
            INC FLAG 1, 1
            DEC OBJECTS 1
            SOUND 7
        END
END
Здесь все, что мы уже с вами видели раньше: сначала проверяем положение Dogmole, выполняя IF PLAYER_IN_X и IF_PLAYER_IN_Y. Если все условия выполняются, проверяем, что имеем собранный объект, выполняя IF PLAYER_HAS_OBJECTS. Если это верно, то делаем три вещи: сначала увеличиваем на 1 значение флага 1 путем выполнения FLAG 1, 1. Затем вычитаем 1 из количества предметов в наличии (оно вернется к 0, и мы снова можем собирать ящики) функцией DEC OBJECTS 1. И проигрываем звук под номером 7.

Когда все сделано, нам остается только одно: проверить, собрали ли мы 10 ящиков. Отличное место для выполнения этой проверки – как раз после предыдущего условия. Так как все условия секции выполняются по порядку, как раз за подсчетом ставим проверку, что мы уже доставили 10 ящиков, чтобы закончить игру. Таким образом, дополняем секцию PRESS_FIRE AT SCREEN 0 новым условием. Будет так:

PRESS_FIRE AT SCREEN 0
    # Определяем подиум.
    # Определяем положение прямоугольника из пикселей
    # Затем проверяем, имеет ли игрок код предмета
    # Если все условия выполняются, снижаем количество объектов в инвентаре
    # и увеличиваем значение Флага 1
    IF PLAYER_IN_X 33, 79
    IF PLAYER_IN_Y 97, 127
    IF PLAYER_HAS_OBJECTS
        THEN
            INC FLAG 1, 1
            DEC OBJECTS 1
            SOUND 7
    END
    # Конец игры
    # Если собрано 10 коробок, мы выиграли!
    IF FLAG 1 = 10
        THEN
            WIN GAME
    END IF
END
Снова все просто: если мы доставили 10 ящиков (т.е. если флаг 1 = 10), мы выиграли. Команда WIN GAME успешно завершает игру и показывает финальное окно.

Видишь, все было не так страшно? Да, согласен, про координаты все же запутано, но рыдать не из-за чего. Ну конечно, если ты не сильно чувствительный.

Интересное дополнение

Ну что, мы сконфигурировали нашу игру, так что игроку остается только нажать на кнопку действия, чтобы активировать подиум и положить туда ящик. Это не проблема, но было бы еще круче, если бы игроку вообще ничего не надо было бы нажимать. Как раз для этого мы и добавили в движок то, что назвали «зоной огня», т.е. fire zone. Эта зона огня – просто прямоугольник в окне, определенный пикселями. Если игрок входит в этот прямоугольник, движок ведет себя так, как будто была нажата кнопка действия. Зона огня автоматически дезактивируется при смене экрана, так что если мы определим ее в ENTERING SCREEN n, она будет активна, только пока мы будем находиться в этом окне.

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

Зона огня определяется командой SET_FIRE_ZONE, которая получает координаты x1, y1, x2, и y2 периметра, который хотим использовать в качестве зоны огня. Если мы хотим, чтобы зона огня совпадала с прямоугольником, заданным тайлами, как в нашем случае, применяются те же формулы, которые мы объясняли раньше. Так что мы будем использовать ровно те же значения.

Прежде всего, говорим движку, что мы будем использовать зоны огня. Для этого активируем команду, соответствующую нашему config.h:

Поле этого нам остается только изменить секцию ENTERING SCREEN 0, добавив команду SET_FIRE_ZONE x1, y1, x2, y2 в самом конце.

# Вестибюль университета
ENTERING SCREEN 0
# декорации и подиум
IF TRUE
    THEN
        # Подиум
        SET TILE (3, 7) = 22
        SET TILE (4, 7) = 23
        # Декорации
        SET TILE (1, 5) = 29
        SET TILE (1, 6) = 20
        SET TILE (1, 7) = 21
        SET TILE (6, 6) = 20
        SET TILE (6, 7) = 21
        SET TILE (7, 7) = 28
        SET TILE (1, 2) = 27
        SET TILE (1, 3) = 28
        SET TILE (2, 2) = 29
        SET TILE (2, 3) = 27
        SET TILE (3, 2) = 32
        SET TILE (3, 3) = 33
        SET TILE (9, 1) = 30
        SET TILE (9, 2) = 30
        SET TILE (9, 3) = 31
        # Fire zone (x1, y1, x2, y2):
        SET_FIRE_ZONE 33, 97, 79, 127
    END
END
Вопрос, который ты себе сейчас задаешь: «Какого #@!! я не внес это в игру?» Да потому что эта характеристика, изначально созданная для версии 4.0 (игра Hobbit), была снова применена в версии 3.99.1.

Чувак, я малость запутался
Беру вину на себя. Надо еще вбить себе в башку работу скрипта. Я думаю, что лучше всего  начинать с чего-то очень простого, в том числе более простого, чем Dogmole, который мы видели, и потихоньку увеличивать сложность.

Мне пришла в голову гениальная идея: мы закончим здесь главу о базовых скриптах, но мы могли бы вместе рассмотреть скрипты некоторых наших игр. Я выберу несколько игр с простым скриптом, и мы объясним их шаг за шагом. Было бы интересно, чтобы вы параллельно играли в эти игры, чтобы посмотреть, как выполняются различные условия.

12

Cheril Perils
Премьера движка скриптов состоялась с выпуском игры Cheril Perils.

http://viva-games.ru/game/cheril-perils

Конечно, это все было на уровне детского сада и очень просто. Скрипт Cheril Perils – это самый простой скрипт из всех наших игр со скриптом: здесь выполняется только 1 вещь: когда мы убили всех врагов, мы можем вынести добычу с первого окна. Вот так:

http://zxaaa.net/store/images/mojon-twinscheril-perils-06021.png

В принципе, все похоже на то, что мы сделали в Dogmole: при входе на экран, проверяем, что мы убили всех врагов (всего их 60). Если это условие выполняется, на месте нашей добычи рисуем пустые тайлы:

ENTERING SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
    THEN
        SET TILE (2, 7) = 0
        SET TILE (2, 8) = 0
    END
END
Но здесь происходит то, чего нет в Dogmole: в окне, откуда мы должны вынести добычу, есть враги. Так что эта проверка на входе на экран нам ничего не даёт, и если мы убиваем последнего жучару в этом окне (что может случиться), то нам надо выйти и снова зайти в это окно, чтобы движок сработал. Нам нужен дополнительный код, который определяет, что мы убили последнего врага, и который сработает, когда мы его убиваем. Мы помним особенность движка: когда мы прыгаем на врага, выполняется секция PRESS_FIRE AT SCREEN, относящаяся к текущему окну. Так что получилось гениально: поставив в этой секции тот же код, что в ENTERING SCREEN, решаем проблему.

Не откладывая в долгий ящик:

PRESS_FIRE AT SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
    THEN
        SET TILE (2, 7) = 0
        SET TILE (2, 8) = 0
    END
END
Теперь нам надо определить выход с экрана. Если ничего не менять, то при выходе влево с экрана 20, попадем в экран 19… Который, к тому же, находится на другом конце карты. В оригинальной игре это было решено грязным хаком, но для текущей версии Чурреры мы смогли все сделать по-честному.

Прежде всего, надо определить зону огня, которая займет левую часть окна, чтобы выполнялась секция PRESS_FIRE AT SCREEN 20, когда мы в нее зайдем. Затем добавим определение зоны огня в секции ENTERING SCREEN 20 (также не забываем активировать эту функцию в config.h). Вот что получается:

ENTERING SCREEN 20
    IF ENEMIES_KILLED_EQUALS 60
    THEN
        SET TILE (2, 7) = 0
        SET TILE (2, 8) = 0
    END
    IF TRUE
    THEN
        SET_FIRE_ZONE 0, 0, 15, 159
    END
END
Все понятно? При входе на 20 экран происходят 2 вещи: прежде всего, проверяется, равно ли количество убитых врагов 60, и в таком случае исчезают тайлы, которые блокируют выход. Затем в любом случае (IF TRUE) определяется зона огня, занимающая всю левую сторону шириной 15 пикселей. И когда игрок заходит в эту зону (он не сможет это сделать, если не убрал загородку: он просто не сможет пройти), выполнится секция PRESS_FIRE AT SCREEN 20. Теперь надо добавить код в секцию PRESS_FIRE AT SCREEN 20 , чтобы определить, что игрок собирается выйти с левой стороны и, в этом случае, закончить с успехом игру. Вот что получается:

PRESS_FIRE AT SCREEN 20
    IF ENEMIES_KILLED_EQUALS 60
    THEN
        SET TILE (2, 7) = 0
        SET TILE (2, 8) = 0
    END
    IF PLAYER_IN_X 0, 15
    THEN
        WIN
    END
END
Повторим, чтобы было понятно. Рассмотрим что будет происходить шаг за шагом. Представим, что заходим на 20 экран после того, как убили всех злодеев. Это последовательность событий:

При входе в окно 20, после его прорисовки и т.д., выполняется секция ENTERING SCREEN 20. Она проверяет, имеем ли мы 60 убитых врагов, что подтверждается – и решетка открывается. К тому же определяется зона огня в 15 пикселей шириной в левой части игры.
Выполняется основной сценарий игры. Игрок продолжает играть, видит открытую решетку и идет влево.
Когда игрок заходит в зону огня, выполняется секция PRESS_FIRE AT SCREEN 20. В ней проверяется, что мы имеем 60 убитых врагов, и убирается решетка. Это повторяет предыдущие действия и может быть заменено на флаг, но нам все равно… это не сильно заметно. Важно то, что происходит потом: проверка координаты Х игрока, в пикселях: находится ли она между 0 и 15, и, когда получается подтверждение (что мы уже включили в эту секцию, когда вошли в зону огня, определенную как раз в этой зоне), выполняется команда WIN: появляется финальный экран игры.
Все поняли? Посмотрим еще один? Хочешь посмотреть на скрипт с флагом, чтобы избежать повторения? Отлично.

У нас все флаги свободны, поэтому будем использовать первый. Метод простой: ставим его на значение 0 при входе в экран и на 1, когда убираем решетку, а решетку мы можем командой PRESS_FIRE AT SCREEN 20, только если флаг равен 0. Теперь посмотрим на это всё вместе, всё должно быть понятно:

ENTERING SCREEN 20
    IF TRUE
    THEN
        SET_FIRE_ZONE 0, 0, 15, 159
        SET FLAG 1 = 0
    END
    IF ENEMIES_KILLED_EQUALS 60
    THEN
        SET TILE (2, 7) = 0
        SET TILE (2, 8) = 0
        SET FLAG 1 = 1
    END
END

PRESS_FIRE AT SCREEN 20
    IF ENEMIES_KILLED_EQUALS 60
    IF FLAG 1 = 0
    THEN
        SET FLAG 1 = 1
        SET TILE (2, 7) = 0
        SET TILE (2, 8) = 0
    END
    IF PLAYER_IN_X 0, 15
    THEN
        WIN
    END
END
Так, давайте посмотрим еще один.

Sgt. Helmet Training Day
Сейчас рассмотрим чуть более длинный скрипт, но тоже легкий. В этой игре (Sgt. Helmet Training Day)

http://viva-games.ru/game/sgt-helmet-training-day

задание – собрать 5 бомб, отнести их к экрану с компьютером (окно 0) и снова вернуться в начало (экран 24).

Если много способов сделать это. Тот, который используем мы, очень простой:

Мы можем посчитать количество доставленных предметов через скрипт, потому что бомбы – нормальные и часто встречающиеся объекты в движке. Размещаем их с помощью Разместителя в качестве хотспота 1-го типа.

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

Используем флаг 1 для проверки, что мы расположили бомбы. В начале игры он равен 0, значение изменится на 1, когда мы разместим бомбы.

Когда мы заходим в окно 24, являющееся основным окном, проверяем значение флага 1, и если оно равно 1, игра завершается.

К тому же добавим текст в окно с указанием того, что теперь надо сделать. Вспомним, что в config.h есть три команды, которые мы уже упоминали в некоторых главах:

#define LINE_OF_TEXT        0    // If defined, scripts can show text @ Y = #
#define LINE_OF_TEXT_X        1    // X coordinate.
#define LINE_OF_TEXT_ATTR    71    // Attribute
Они определяют, где появляется текст, который мы можем прописать в скрипте командой TEXT. Для этого оставляем пустое место в зоне маркировки: посмотри, в верхней строчке есть место, потому что мы уже запрограммировали текстовую строку в координатах (x, y) = (1, 0).

http://zxaaa.net/store/images/helmet-title-06321.png

Первое, что делает наш скрипт, это определяет несколько сообщений, которые появляются по умолчанию при входе в каждое окно, в зависимости от значения флага 1. Это мы делаем в секции ENTERING ANY. Мы помним, что эта секция выполняется при входе на любой экран, сразу перед секцией ENTERING SCREEN n с соответствующим номером. Внимание: мы можем определить общий текст, который будет появляться при необходимости в любом конкретном окне, а тот текст, которые будет написан ENTERING SCREEN n заменит предыдущий текст, так как эта команда выполняется последней.

Чтобы написать текст в определенной таким образом строчке, используем команду ТЕХТ. Текст пишется без кавычек. Используем нижнее подчеркивание вместо пробелов. Также важно заполнять текст дополнительными пробелами, для ситуация в которых более короткий текст должен появиться поверх более длинного.

Максимальная длина текстов будет зависеть от твоего экрана маркировки игры, и от того, каким образом мы определил его позицию. В нашем случае мы его расположили в (x, y) = (1, 0), т.к. слева и справа у нас есть граница, так что максимальная длина будет 30 символов.

Пишем нашу секцию ENTERING ANY. Мы говорили, что сделаем 2 разных текста, в зависимости от значения флага 1:

ENTERING ANY
IF FLAG 1 = 0
    THEN
        TEXT НАЙДИ 5 БОМБ И КОМПЬЮТЕР!
    END
IF FLAG 1 = 1
    THEN
        TEXT МИССИЯ ВЫПОЛНЕНА! ВОЗВРАЩАЙСЯ НА БАЗУ!
    END
END
Никакого волшебства, правда? Если флаг 1 = 0, т.е. идентичен начальной ситуации игры (в начале все флаги равны 0), при входе на каждый экран в зоне маркировки будет появляться текст «НАЙДИ 5 БОМБ И КОМПЬЮТЕР», определённый для текстовой строки. Если флаг 1 = 1, что  произойдет, когда мы разместим бомбы возле компьютера, текст по умолчанию, который появится при входе на экраны, будет «МИССИЯ ВЫПОЛНЕНА! ВОЗВРАЩАЙСЯ НА БАЗУ!».

Сделаем дурацкий набросок окна, чтобы увидеть, как будут располагаться компьютер и бомбы:

http://zxaaa.net/store/images/esquema-07171.jpg

Теперь перейдем к серьезным вещам. Первое, что мы сделаем, это пропишем условия для окна с компьютером, под номером 0. В этом окне мы должны сделать несколько вещей. Прочисти мозги прежде чем начинать. При каждом входе мы должны рисовать компьютер, который состоит из тайлов с 32 по 38 тайлсета. Делаем это, как уже говорили, через команду SET TILE.

Мы также должны определить зону огня вокруг компьютера, чтобы игра автоматически определяла наше приближение.

Если мы снова зайдем в это окно, после того как разместили бомбы (все возможно), мы должны пририсовать еще и бомбы.

Если заходим на экран в первый раз (еще не оставили бомбы), пишем сообщеньице-подсказку, которое говорит: «ЗАЛОЖИ 5 БОМБ И УЛЕПЕТЫВАЙ».

Если мы подойдем к компьютеру, нужно сделать красивую анимацию для закладки бомб, и, к тому же, задать значение 1 для флага 1.

Теперь мы с сами опытные ребята и соображаем, что первые 4 действия выполняются при входе на экран, а последняя при нажатии на кнопку действия (или при входе в зону огня). Разберем все по отдельности. Начнем с тех действий, которые совершаются при входе в это окно. Мне нравится начинать с тех вещей, которые будут повторяться при любом стечении обстоятельств: нарисуем компьютер и определим зону огня:

ENTERING SCREEN 0
# Всегда: рисовать компьютер
IF TRUE
    THEN
        SET TILE (6, 3) = 32
        SET TILE (7, 3) = 33
        SET TILE (8, 3) = 34
        SET TILE (6, 4) = 36
        SET TILE (7, 4) = 37
        SET TILE (8, 4) = 38
        SET_FIRE_ZONE 80, 32, 159, 95
END
Видишь, мы использовали формулы, которые объяснили раньше, чтобы определить широкую область вокруг компьютера. Конкретно? Эта зона соответствует прямоугольнику, формируемому тайлами (x, y) = (5, 2) и (9, 5). Т.е. область в 1 тайл шириной вокруг 6 тайлов, означающих компьютер. Если не слишком занят, нарисуй это на листочке в клетку.

Продолжаем: если мы заходим на экран после того, как расположили бомбы (ну мало ли), нам надо добавить бомбы к рисунку. Ничего проще:

# Если мы уже расположили бомбы, нарисовать их
IF FLAG 1 = 1
    THEN
        SET TILE (4, 4) = 17
        SET TILE (4, 2) = 17
        SET TILE (7, 1) = 17
        SET TILE (10, 2) = 17
        SET TILE (10, 4) = 17
END
Мы всё зарисовали, чтобы знать, куда разложить бомбы. Бомба находится в 17-ом тайле, это тайл, использующийся для рисования предметов, если помнишь.

Теперь осталось только добавить текст-подсказку, если мы еще не разместили бомбы. Смотри, получилось, как мы и говорили: так как эта секция выполняется после ENTERING ANY, этот текст замещает тот, что был до этого. Поэтому мы используем пробелы вокруг текста, чтобы заместить все символы предыдущего текста, который длиннее нового:

# Если нет, сообщеньице
IF FLAG 1 = 0
    THEN
        TEXT ЗАЛОЖИ 5 БОМБ И УЛЕПЁТЫВАЙ
    END
END
Готово. Теперь осталось настроить реагирование на зону огня в секции PRESS_FIRE AT SCREEN 0. Добавим проверки и анимацию:

PRESS_FIRE AT SCREEN 0
    IF PLAYER_IN_X 80, 159
    IF PLAYER_IN_Y 32, 95
    IF OBJECT_COUNT = 5
    IF FLAG 1 = 0
    THEN
        SET FLAG 1 = 1
        SET TILE (4, 4) = 17
        SHOW
        SOUND 0
        SET TILE (4, 2) = 17
        SHOW
        SOUND 0
        SET TILE (7, 1) = 17
        SHOW
        SOUND 0
        SET TILE (10, 2) = 17
        SHOW
        SOUND 0
        SET TILE (10, 4) = 17
        SHOW
        SOUND 0
        TEXT МИССИЯ ВЫПОЛНЕНА! ТЕПЕРЬ ВОЗВРАЩАЙСЯ НА БАЗУ!
    END
END
Теперь спокойно рассмотрим это, потому что есть некоторые новые вещи:

Прежде всего, проверяем, что мы находимся там, где должны быть (игрок всегда может просто нажать на кнопку действия вместо того, чтобы войти в зону огня, и будет не здорово, если команда выполнится, если игрок находится где-то еще). Выполняем это, как уже говорили раньше: с помощью PLAYER_IN_X и PLAYER_IN_Y с координатами зоны огня.

Следующий шаг – проверить, что в арсенале имеется 5 бомб, или, что то же самое, 5 предметов. Это выполняется через OBJECT_COUNT, который представляет собой количество предметов, которые собрал игрок.

И наконец, самое важное, проверяем что мы уже не оставили бомбы, или может произойти всё что угодно.

Если все эти условия выполняются, ставим значение 1 у флага 1 (мы уже установили бомбы) и добавляем анимацию, которая состоит в прорисовке бомб по одной и звуках. Обрати внимание на команду SHOW, необходимую, чтобы те изменения, которые мы делаем на этом экране, не были видны до актуализации, что обычно происходит при возвращении к основному сценарию игры, но не посреди выполнения условия. Так как нам надо, чтобы каждая бомба появилась после того, как мы ее нарисовали, обращаемся к SHOW. К тому же каждый звук задержит выполнение сценария на некоторое время (мы в режиме 48К), что отлично для нас. В конце печатаем текст подсказки, снова с пробелами вокруг, чтобы заполнить 30 символов и заменить предыдущий текст.

И таким образом мы закончили всё, что надо было сделать в окне 0.

Если мы продолжим наш сценарий, следующее, что мы должны сделать, это вернуться в начальное окно под номером 24.  То, что нам осталось сделать, очень просто: надо проверить при входе на экран 24, что флаг 1 = 1. Это условие может быть выполнено, только если до этого мы разместили бомбы, для чего нам нужно было выполнить еще много всего… Просто проверяем это, и если условие выполняется, завершаем с успехом игру… Нет ничего проще:

ENTERING SCREEN 23
    IF FLAG 1 = 1
    THEN
        WIN
    END
END
Ура! Мы запрограммировали игру. В скрипте Sgt. Helmet есть еще одна штуковина: наше привычное «Продаю подержанный мотоцикл». Но это пока оставим, в этом нет ничего особенного: нарисовать тайлы, определить зону огня, определить позицию и написать текст. Ты все это уже умеешь.

Гав-гав

Можно было бы продолжать, но лучше мы тут остановимся. В следующей главе мы продолжим разбирать примеры шаг за шагом, но уже с более сложными скриптами, как, например, скрипт Cadàveriön. И потом продолжим изучать такие интересные вещи, как игры 128K, изменение музыки и эффектов, сжатые фазы, уф, так мы никогда не закончим.

Между тем, напоминаю тебе, что в архиве motor_de_clausulas.txt в /script можно найти список доступных команд и проверок, на случай, если тебе стало любопытно.

До скорого!

13 (изменено: Random Great, 06.11.2017 15:26:22)

Можно. Правда под винду smile http://blog.nodeus.ru/all/artificial/

Эта демосистема называется TOOLL2 и доступна для некоммерческих проектов всем, абсолютно бесплатно. Эта система позволяет в интерактивном режиме создавать реалтаймовые аудио-визуальные работы, практически без специальных знаний из области программирования. Эта система была создана командой разработчиков и дизайнеров из Берлина — Framefield.

Уверен, для Спектрума тоже можно нечто подобное создать, язык для написания дем smile

14

Random Great сказал:

Можно. Правда под винду smile

Эта демосистема называется TOOLL2 и доступна для некоммерческих проектов всем, абсолютно бесплатно. Эта система позволяет в интерактивном режиме создавать реалтаймовые аудио-визуальные работы, практически без специальных знаний из области программирования. Эта система была создана командой разработчиков и дизайнеров из Берлина — Framefield.

http://blog.nodeus.ru/all/artificial/

Под винду даже дети учащиеся 3 классов могут, там нет никаких ограничений. пентагон + ассемблер + знаоместо спека вот истинное наслаждение. Когда каждый шаг это "не получится" а ты делаешь шедевр. Под винду же ты просто складываешь ЛЕГо конструктор.

15 (изменено: Random Great, 06.11.2017 15:33:56)

Конечно оптимизация каждого такта и байта как у великих сценеров на ширпотребном движке не получится, но ряд основных команд типа "загрузить и запустить музыку", "показать картинку", "подождать 5 секунд", "стартануть анимацию" - покроет большинство потребностей начинающих демо-спектрумистов а там глядишь и свое начнут писать,  если сделать возможность дополнения ширпотребного движка своими командами...

16

Random Great сказал:

Конечно оптимизация каждого такта и байта как у великих сценеров на ширпотребном движке не получится, но ряд основных команд типа "загрузить и запустить музыку", "показать картинку", "подождать 5 секунд", "стартануть анимацию" - покроет большинство потребностей начинающих smile

Было больше, но мне говорили что этого мало. Я говорю о запиляторе.