Создай свою игру. Часть 9 – Базовые скрипты

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

Глава 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):

coordenadas

Да, если ты не привык программировать эти значения, это кажется тебе чертовой мешаниной, но на самом деле все будет проще, когда ты запомнишь формулу, а еще лучше – поймешь ее. Мы умножаем на 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. Теперь посмотрим, как это будет выглядеть на этом сложном графике: чтобы спрайт дотронулся до подиума, верхний левый пиксель квадрата его спрайта (отмечен красным) должен быть внутри зоны, которую мы определили:

coordenadas4-0536[1]

Мы также должны проверить, что у нас есть ящик в инвентаре. Будет как-то так:

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, который мы видели, и потихоньку увеличивать сложность.

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

Cheril Perils

Премьера движка скриптов состоялась с выпуском игры Cheril Perils. Конечно, это все было на уровне детского сада и очень просто. Скрипт Cheril Perils – это самый простой скрипт из всех наших игр со скриптом: здесь выполняется только 1 вещь: когда мы убили всех врагов, мы можем вынести добычу с первого окна. Вот так:

mojon-twinscheril-perils-0602[1]

В принципе, все похоже на то, что мы сделали в 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 экран после того, как убили всех злодеев. Это последовательность событий:

  1. При входе в окно 20, после его прорисовки и т.д., выполняется секция ENTERING SCREEN 20. Она проверяет, имеем ли мы 60 убитых врагов, что подтверждается – и решетка открывается. К тому же определяется зона огня в 15 пикселей шириной в левой части игры.
  2. Выполняется основной сценарий игры. Игрок продолжает играть, видит открытую решетку и идет влево.
  3. Когда игрок заходит в зону огня, выполняется секция 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) задание – собрать 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).

helmet-title-0632[1]

Первое, что делает наш скрипт, это определяет несколько сообщений, которые появляются по умолчанию при входе в каждое окно, в зависимости от значения флага 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, что  произойдет, когда мы разместим бомбы возле компьютера, текст по умолчанию, который появится при входе на экраны, будет «МИССИЯ ВЫПОЛНЕНА! ВОЗВРАЩАЙСЯ НА БАЗУ!».

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

esquema

Теперь перейдем к серьезным вещам. Первое, что мы сделаем, это пропишем условия для окна с компьютером, под номером 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 можно найти список доступных команд и проверок, на случай, если тебе стало любопытно.

До скорого!

 

[ Перевод на русский язык — сайт viva-games.ru. При перепечатке статьи или любой её части ссылка на viva-games.ru обязательна. Оригинал статьи тут. ]




Понравилась публикация? Поделись с друзьями

Отправить ответ

Уведомлять об
avatar
wpDiscuz
Close