Информация предоставлена с официального сайта Elecbyte
Формат CNS
Введение
Файл CNS игрока выполняет две цели:
1. Он определяет переменные этого игрока, такие как скорость ходьбы, графика рисования и т.д.
2. Он содержит состояния игрока, которые описывают все движения, которые игрок может сделать. States - это строительные блоки, которые можно использовать для создания простых, а также сложных ходов.
Как и многие другие файлы персонажа, CNS - это текстовый файл, который вы можете редактировать с помощью любого текстового редактора.
В CNS файле точка с запятой (;) считается символом «для комментариев» персонажа. Любой текст в той же строке после точки с запятой будет проигнорирован программой. CNS в основном не учитывает регистр, т. Е. «MyName» обрабатывается так же, как «myname» и «mYnAMe». Единственным исключением является командный триггер (подробно описанный в документации CMD).
Некоторая терминология
Когда мы говорим «группа», мы подразумеваем любой блок из строк текста, начинающийся с того, что выглядит как [groupname], и заканчивается перед следующей группой. Например, группа Foo состоит из первых трех строк в следующем:
[Foo]
линия1
линия2
[Group 2]
еще больше линий
Внутри группы параметры могут отображаться в любом порядке. Например, так:
[SomeGroup]
value1 = 1234
value2 = "строка"
Эквивалентно:
[SomeGroup]
value2 = "строка"
value1 = 1234
Переменные персонажа
Пока нет полной документации. См. Chars/kfm/kfm.cns для комментариев к каждой переменной.
Некоторые важные примечания:
- В [Size] вы можете использовать xscale и yscale для изменения ширины и высоты вашего персонажа. Это избавляет от необходимости масштабировать каждый из спрайтов.
- Настройте скорости игрока в разделе [Velocity]
- Установите ускорение игрока вниз - yaccel в [Movement]
Состояния States
Анимации и звуки являются наиболее заметными проявлениями персонажа MUGEN, но истинным «сердцем» этого символа является его CNS файлы. Файл CNS, также известный как файл состояний персонажей, содержит коды, которые фактически дают персонажу его функциональность - позволяя ему выполнять ходы при командовании, ударять своего противника или подчиняться закону силы тяжести.
Структура файла CNS проста. Код организован в логические группы, называемые [StateDef]s. Блоки [StateDef] нумеруются, а типичный персонаж может содержать сотни из них. Внутри каждого [StateDef] имеется ряд блоков [State], также известных как контроллеры состояний. Каждый контроллер State представляет собой пару trigger - действий: он определяет некоторые действия для персонажа и принимает условия, при которых это действие должно быть выполнено.
В каждый момент (tick) игрового времени, персонаж выполняет код в некотором [StateDef] блоке. Например, если персонаж лениво стоит, то он обычно выполняется в блоке [StateDef 0]. Для краткости мы говорим, что персонаж «находится в состоянии 0». При каждом tick (счет игрового времени), когда персонаж находится в состоянии 0, он будет оценивать контроллеры состояния в блоке [StateDef 0] сверху вниз, проверять условия и принимать любые действия, которые там указаны. Если персонаж должен измениться на какой-либо другой блок [StateDef], скажем, чтобы указать состояние state 417, поскольку он выполняет перемещение, он может выполнить контроллер состояния ChangeState, чтобы переключиться. Затем персонаж начнет выполнять код в [StateDef 417] точно таким же способом.
Каждый персонаж MUGEN дополнительно имеет три специальных состояния с номерами -1, -2 и -3. Это единственные допустимые состояния с отрицательными числами. Состояние state -1 обычно содержит контроллеры состояния, которые определяют правила перехода состояния на основе пользовательского ввода команды (commands). Состояние state -2 содержит другие контроллеры состояния, которые необходимо проверять каждый tick. Состояние state -3 содержит контроллеры состояния, которые проверяются каждый тик, если игрок временно не использует данные состояния другого игрока (например, когда игрока бросают).
Чтобы собрать все вместе: для каждого tick игрового времени MUGEN делает один проход через каждое из специальных состояний сверху вниз, в порядке увеличения номера состояния (-3, -2, затем -1). Для каждого столкновения контроллера состояния, его типовые (type) триггеры условия оцениваются и, если они выполнены, контроллер выполняется. Затем обработка переходит к следующему контроллеру состояния в состоянии state. Переход состояния (ChangeState) в любом из специальных состояний обновит текущий номер state состояния игрока и прервет обработку оставшейся части этого состояния. После того, как все контролеры состояния в специальных состояниях были проверены, текущее состояние игрока обрабатывается снова сверху вниз. Если переход состояния выполняется из текущего состояния, остальные контроллеры состояния (если есть) в текущем состоянии пропускаются, а обработка продолжается с начала нового состояния. Когда достигнут конец текущего состояния и не происходит переход состояния, обработка останавливается для этого тика (tick).
Существует одно исключение из приведенного выше сценария. Если персонаж является «вспомогательным» (helper) персонажем, то есть порожденным контроллером состояния Helper, этот персонаж не будет иметь особых состояний state -3 и -2. Персонаж helper не будет иметь специального состояния state -1, если только оно не включено. (Это контролируется контроллером состояния Helper при создании персонажа.)
Введение в States
Программирование состояний states является самой сложной частью создания персонажа. Это влечет за собой много работы, тестирования, а иногда и проб и ошибок. В этом разделе мы часто будем говорить про программирование игрока, а также и его противника. Назовем игрока, чьи состояния мы будем редактировать P1, и его противника P2.
Не озадачивайте себя, если вы многого не понимаете из этого документа в своем первом чтении. Лучший способ узнать о состояниях states - сначала поиграть со значениями (values) в CNS завершенного персонажа и посмотреть, какие последствия есть у него или у неё. Не стоит бояться «настройки» CNS; M.U.G.E.N предназначен для обнаружения ошибок синтаксиса и сообщает о них.
В комплект поставки дистрибутива M.U.G.E.N входит персонаж с именем Kung Fu Man (короткая версия KFM). Его можно найти в каталоге chars/kfm.
Файл CMD содержит декларации имен команд и определение состояния State -1, специального состояния, которое используется для управления тем, как персонаж отвечает на ввод пользователя.
Ниже приведены некоторые концепции, которые будут полезны для вас.
Жизнь и энергия
Жизни игрока (lifebar) - это полоса в верхней части экрана на его стороне. Когда lifebar достигает нуля, игрок погибает. Его энергия - другая полоса (ниже или выше полосы жизней), она увеличивается с каждой атакой, которую игрок дает или принимает. Когда индикатор энергии достигает определенных значений, он может делать супер-приемы.
Контроль
Когда мы говорим, что игрок «имеет контроль», мы имеем в виду, что он готов ходить или прыгать или атаковать. Игрок, у которого нет контроля, не будет реагировать на ваши нажатия (с клавиатуры или джойстика). Например, когда P1 находится в состоянии ожидания, он имеет контроль и будет двигаться вперед, если вы нажмете кнопку «вперед». Игрок, как правило, не имеет контроля, когда он находится в состоянии атаки, иначе вы могли бы просто уйти на полпути во время удара.
Однако существует исключение из правила. Иногда вы можете позволить игроку реагировать на определенные ходы, даже если у него нет контроля. Это называется «прерыванием перемещения» или «отменой хода».
Мы будем часто ссылаться на «контрольный флаг» игрока. «Flag» - это значение (value), которое является либо true, либо false.
Игровое время и время состояния state
M.U.G.E.N отслеживает время, прошедшее в игре. Каждый раз, когда игра обновляется (это включает в себя обновление игроков, проверку блоков ударов и изображения на экране), мы говорим, что время игры увеличилось на единицу. Время, которое игрок провел в состоянии state, называется «временем состояния». Время состояния начинается с 0 в начале состояния state и увеличивается на один тик за каждый тик игрового времени.
Положение, скорость и ускорение
Те из вас, кто имеет базовые знания математики, должны понимать эти понятия. M.U.G.E.N использует следующую систему координат. Чем больше X-позиция, тем правее игрок. Чем меньше X-позиция, тем ближе он находится к левому игроку. Y-позиция нуля равна уровню земли. По мере того как Y-позиция игрока увеличивается, он движется вниз. Например, отрицательное положение оси Y означает, что игрок находится в воздухе. Точно так же, когда мы говорим, что игрок имеет положительную X-скорость, это означает, что он движется вперед, а если он имеет отрицательную X-скорость, то движется назад. Игрок с положительной Y-скоростью движется вниз, а отрицательная Y-скорость означает, что он движется вверх. Положительное X-ускорение означает, что X-скорость игрока увеличивается, отрицательное X-ускорение означает, что его X-скорость уменьшается. Аналогично и для Y-ускорения.
"Жонглирование"
M.U.G.E.N допускает определенные движения «жонглировать», то есть ударять противников, которые были поражены в воздухе, или лежат на земле. Система жонглирования работает так: каждый человек начинает с заданного количества жонглирующих «очков», начиная с первого удара, который заставляет противника падать, "очков" обычно 15.
Быстрая терминология: когда мы говорим, что игрок «падает», значит, он не восстанавливает контроль в воздухе и упадет на землю.
Если игрок ударил, когда он падал в воздухе или лежал на земле, его очки "жонглирования" уменьшаются на величину, зависящую от атаки. Когда атака требует больше очков жонглирования, прежде чем противник вышел, атака будет пропущена. Любой ход, который заставляет противника упасть, сразу же вычитает свои жонглирующие очки при первом попадании.
Например, атака, требующая 7 жонглирующих очков, теоретически может использоваться для жонглирования противника дважды (при условии, что вы начали с 15 очков), оставив противнику 1 очко на выход. Последующие атаки будут пропущены.
Причиной этой жонглирующей системы является предотвращение бесконечных комбо в воздухе.
Основные части состояния States
Примечание. В этом разделе предполагается, что вы, по крайней мере, просмотрели документацию по файлам формата AIR и поняли понятия анимации, так как знаете смысл ключевых слов и фраз, таких как действие и элемент действия.
Вот краткое примерное состояние для P1:
[Statedef 200]
type = S
physics = S
movetype = I
ctrl = 0
anim = 200
velset = 0
[State 200, 1]
type = ChangeState
trigger1 = AnimTime = 0
value = 0
ctrl = 1
Это состояние воспроизводит действие 200 анимации P1 и возвращает P1 в свое состояние после окончания анимации. В этом случае предположим, что действие 200 имеет конечное время цикла. То есть в действии 200 нет элементов со временем, равным -1.
На данный момент вам не нужно беспокоиться о деталях. Начнем с знания того, из чего состоит state.
Все States должны иметь один раздел Statedef и один или несколько State разделов.
Statedef содержит начальную информацию о состоянии, такую как состояние (стойка, приседание, в воздухе) и какой ход он делает (атакующий, бездействующий).
Каждый раздел состояния называется state контроллером или кратковременным контроллером. Контроллеры сообщают программе, что делать с P1, и когда это делать. Существует много видов контроллеров, каждый со своей собственной функцией. Например, есть контроллеры для изменения положения или скорости игроков, определения эффектов атак, создания снарядов, переключения между действиями анимации, состояниями изменения и т.д. Каждый контроллер должен иметь по крайней мере один триггер. Триггер - это событие, которое вызывает активацию контроллера. Примерами являются: триггер в начале состояния, триггер в конце анимации (как показано в примере выше), триггер по элементу анимации Action, триггер, когда P2 находится в пределах определенного диапазона P1, и так далее.
Подробная информация о StateDef
Каждый state должен начинаться с одной группы StateDef, также известной как раздел Statedef. Группа StateDef должна выглядеть так (укажите один или несколько параметров, где находятся точки):
[Statedef state_number]
. state_parameters
.
.
Замените state_number номером состояния state, которое вы программируете. За исключением номеров специальных групп (см. приложение A), вы можете использовать любой номер state, который вы выберете. Чтобы избежать выбора номера специальной группы, не выбирайте числа от 0-199 и между 5000-5999.
Следующие строки должны включать следующие основные параметры:
- type
- movetype
- physics
- anim
Существуют также дополнительные необязательные параметры, которые могут быть включены:
- velset
- ctrl
- poweradd
- juggle
- facep2
- hitdefpersist
- movehitpersist
- hitcountpersist
- sprpriority
type
Это type состояния P1 в состоянии state. Он определяет, будет ли игрок стоять, приседать, быть в воздухе или лежать. Соответствующими значениями являются «S», «C», «A» и «L» соответственно (без кавычек). Чтобы оставить тип неизменным из предыдущего состояния, используйте значение «U». Если эта строка отключена, предполагается, что тип «S». Обычно вы будете использовать «S», «C» и «A». Например, для состояния type crouching (приседание) требуется строка:
Type используется для определения нескольких факторов, что наиболее важно, как P1 будет реагировать на попадание. Например, находясь в состоянии type «stand» (стойка), P1 будет реагировать так, как будто он стоит на земле. Если type «air» (воздух), то P1 будет реагировать на попадание соответственно.
S - Standing (стойка), C - Crouching (приседание), A - in Air (в воздухе), L - Lying down (лежать), U - Unchanged (без изменений).
movetype
Это тип перемещения P1: «A» (attack) для атаки «I» (idle) для простоя и «H» (hit) для попадания (получения удара). Чтобы оставить movetype неизменным из предыдущего состояния, используйте значение «U» (unchanged). Значение считается «I», если эта строка отсутствует. «A» и «H» должны быть понятными. «I» используется для состояний, в которых P1 не атакует и не получает урон. Например, состояние атаки должно иметь строку:
Вам нужно указать тип movetype, чтобы программа знала, как обрабатывать состояние. Неправильное указание movetype может привести к некорректной работе P1.
physics
Вам нужно указать, какую физику использовать в этом состоянии. Допустимые значения: «S» (stand) для стойки, «C» (crouching) для приседания, «A» (air) для воздуха, а «N» (none) - нет. Чтобы оставить физику без изменений из предыдущего состояния, используйте значение «U» (unchanged). Если отсутствует или отключено, предполагается значение «N». Тип физики используется для определения поведения P1.
- Для физики «S» P1 будет испытывать трение с землей. Значение коэффициента трения задается в Переменных персонажа.
- Для физики «C» P1 будет испытывать трение, как в состоянии «S».
- Для физики «А» P1 будет ускоряться вниз, и если его Y-позиция больше 0 (то есть он касается земли), он сразу же войдет в свое состояние приземления.
- Если вы используете «N», P1 не будет использовать какую-либо из этих предварительно запрограммированных физик.
Не путайте «physics» со состоянием «type». Они, как правило, одинаковы, но вам предоставляется выбор, если вы хотите больше контроля движений. Например, вы можете использовать «N» (без физики) и указать свое собственное определение ускорения и посадки для воздушного состояния.
anim
Этот параметр изменяет действие анимации P1. Укажите номер действия в качестве значения. Если вы не хотите, чтобы P1 менял анимацию в начале состояния, отключите этот параметр.
Таким образом, чтобы иметь состояние с номером 400, где игрок совершает атаку в положении сидя с действием 400, типичными параметрами будут:
[Statedef 400]
type = c
movetype = a
physics = c
anim = 400
velset
Вы можете использовать velset для установки скорости P1 в начале состояния. Формат представляет собой числовую пару, представляющую скорость X и Y-скорость соответственно. Отключая эту линию, скорость P1 останется неизменной. Например,
P1 начинает перемещаться по диагонали вверх и вперед.
Есть исключение из этого. Даже если у вас есть velset = 0, атака P2 в углу будет отталкивать P1.
ctrl
Этот параметр установит управление P1. Значение «0» устанавливает флаг в false, «1» устанавливает его значение true. Если этот параметр отключен, флаг управления P1 остается неизменным. Например, чтобы дать управление P1, используйте
poweradd
При включении параметра poweradd, добавляется энергия в панель энергии игрока. Значение - это число и может быть положительным или отрицательным. Этот параметр обычно используется в атаках, где вы хотите, чтобы игрок мог получить энергию, просто выполняя атаку. Например, чтобы добавлялось 40 энергии при атаке, введите
juggle
Параметр жонглирования полезен только для атак. Он определяет, сколько точек жонглирования требуется. Если пропустить для атаки, эта атака будет жонглировать, если предыдущее атакующее состояние успешно жонглировало. Вы должны включить параметр juggle для всех атак. Если атака охватывает более одного состояния state, включите параметр juggle только в первом состоянии этой атаки. Для подробностей см. выше в этом посте "Жонглирование".
facep2
Когда вы включаете линию facep2 = 1, игрок будет повернут, если необходимо, лицом к противнику в начале состояния. Facep2 имеет значение по умолчанию «0», если оно отключено или отсутствует.
hitdefpersist
Если установлено значение 1, любые HitDefs, которые активны во время перехода состояния в это состояние, будут оставаться активными. Если установлено значение 0, значение по умолчанию, любые такие HitDefs будут отключены, когда будет выполнен переход состояния.
movehitpersist
Если установлено значение 1, информация о переходе из предыдущего состояния (независимо от того, атакована или пропущена, защищена и т.д., см. триггеры «Move*» в документе триггеров), будет перенесена в это состояние. Если установлено значение 0 (по умолчанию), эта информация будет сброшена при входе в это состояние.
hitcountpersist
Если установлено значение 1, счетчик ударов (количество ударов этой атаки) будет перенесен из предыдущего состояния в это состояние. Если установлено значение 0 (по умолчанию), счетчик сбрасывается при переходе состояния. Этот параметр не влияет на combo счетчик, который отображается на экране. См. документацию триггера HitCount и UniqHitCount о том, как проверить счетчик попаданий.
sprpriority
Если этот параметр присутствует, приоритет наслаивания спрайтов игрока будет установлен на указанное значение. Если отключено, приоритет спрайта останется без изменений. Common1.cns (файл CNS, который унаследован каждым игроком) определяет приоритет спрайта для постоянных или приседающих игроков равным 0, а прыгающие игроки имеют 1. Для большинства состояний атаки вам нужно установить sprpriority = 2, чтобы атакующий появился впереди.
См. sprprriity в документации state контроллеры о том, как изменить приоритет спрайта с помощью контроллера.
Подробная информация о State контроллерах
Формат контроллера
Все состояния должны иметь как минимум один контроллер состояния State Controller, иначе это приведет к ошибке. Группы state controller имеют следующий формат:
[State state_номер, некоторое_число]
type = controller_type
trigger1 = condition_exp
<универсальные необязательные параметры>
<дополнительные параметры в зависимости от контроллера>
State_номер должен быть одним и тем же номером состояния из StateDef. Некоторое_число может быть любым количеством, которое вы выберете; Это число, которое сообщается при обнаружении ошибки, поэтому вы знаете, какой контроллер необходимо устранить.
Универсальными (применимыми ко всем state controller) дополнительными параметрами являются параметры ignorehitpause и persistency. Если ignorehitpause установлен в 1, MUGEN проверяет этот контроллер состояния, даже если персонаж приостановлен ударом. В противном случае этот контроллер состояния не будет проверяться во время паузы при нажатии. По умолчанию 0, что рекомендуется для всех, кроме исключительных ситуаций. Для объяснения параметра persistency см. «Триггер постоянства» в этом посте.
Controller_type - это имя используемого контроллера. Каждый тип контроллера имеет разный эффект и требует разных параметров. См. state контроллеры для полного списка контроллеров состояния.
Порядок контроллеров значителен. Контроллеры, перечисленные первыми, являются проверенными и, если необходимо, активируются первыми.
Ниже приведен пример контроллера, который дает управление P1 в начале состояния (тот же эффект, что и установка ctrl = 1 в качестве параметра в StateDef):
[State 300, 1] ;State 300. 1 - просто произвольное число.
type = CtrlSet ;Изменяет флаг управления.
trigger1 = Time = 0
value = 1
В этом примере тип CtrlSet позволяет вам изменить флаг управления P1. Строка, которая считывает trigger1 = Time = 0, означает, что этот контроллер активируется, когда время состояния равно 0, то есть в начале этого состояния. Значение строки value = 1 говорит о том, что мы хотим установить значение флага управления равным 1, что означает true. Если мы хотим, чтобы P1 запустил состояние без управления, нам просто нужно изменить последнюю строку на value = 0.
Давайте посмотрим на другой пример. Этот контроллер перемещает P1 вперед на 10 пикселей дважды: на второй и третий элемент его текущей анимации. Не беспокойтесь, если вы не знаете, какие параметры идут с помощью каких типов контроллеров. Вы можете узнать больше о них из документации state controller (здесь).
[State 300, 2]
type = PosAdd ;Добавляет к позиции P1
trigger1 = AnimElem = 2 ;Триггер второго элемента.
trigger2 = AnimElem = 3 ;Триггер на 3-м элементе.
x = 10
Как вы видите выше, каждый контроллер должен иметь по крайней мере один триггер. Триггер - это условие, при котором контроллер активируется. В этом примере два триггера, и контроллер активируется, когда один из них является true.
Триггеры
Логика триггера
Первый триггер должен всегда быть trigger1, а последующие триггеры должны быть trigger2, затем trigger3 и так далее. Логикой для принятия решения о том, должен ли быть активирован контроллер, является:
1. Все ли условия триггера истинны (true)? Если да, то да, активируйте контроллер.
2. В противном случае повторите тест для trigger2 и т.д., пока не будет найдено больше триггеров.
Это можно рассматривать как «ИЛИ» логики.
Будьте осторожны; пропуск числа приведет к игнорированию некоторых триггеров. Например, если у вас есть триггеры trigger1, trigger2 и trigger4 без trigger3, то trigger4 будет проигнорирован.
Теперь, если вы хотите, чтобы перед запуском контроллера было выполнено более одного условия? Вот часто используемый пример для тестирования, если игрок в воздухе, достиг земли. Используемые триггеры:
trigger1 = Vel Y > 0 ; True если Y-скорость > 0 (спускается)
trigger1 = Pos Y > 0 ; True если Y-позиция > 0 (под землёй)
На этом этапе вас может смутить формат триггера. На счет этого вопроса не беспокойтесь. Мы скоро доберемся до него.
Как вы можете видеть выше, оба триггера имеют одинаковое число. Когда несколько триггеров имеют одинаковое число, он реализует «И» логику. То есть, контроллер активируется, если каждый из триггеров с одинаковым числом является true, но не когда один или несколько из них являются false.
Вы можете объединить обе идеи. Например:
trigger1 = Vel Y > 0 ; True Если Y-скорость равна > 0 (спускается)
trigger1 = Pos Y > 0 ; True если Y-позиция > 0 (под землёй)
trigger2 = Time = 5 ; True, если время состояния равно 5
Контроллер для этого был бы активирован, если игрок приземлился на землю (Y-скорость и Y-позиция оба равны > 0), ИЛИ, если его состояние было 5.
Вот резюме:
- Триггеры с одинаковым номером активируют контроллер только в том случае, если все они являются true.
- Триггеры с разными номерами активируют контроллер, если один или несколько из них являются true.
Формат триггера:
Condition_exp это арифметическое выражение для проверки на равенство 0. Если condition_exp равно 0, то триггер имеет значение false. Если condition_exp отличное от нуля, то триггер имеет значение true. Condition_exp обычно является простым реляционным выражением, как в приведенных выше примерах, но может быть как простым, так и сложным, если необходимо.
Можно использовать логические механики между выражениями. Например, это эквивалентно предыдущему примеру выше.
trigger1 = ((Vel Y > 0) && (Pos Y > 0)) || Time = 5
См. «Выражения» далее в этом посте, для подробного объяснения арифметических выражений.
Полезным ярлыком, который вы можете использовать, является triggerall. Он задает условие, которое должно быть истинным для всех триггеров. Например, рассмотрим:
triggerall = Vel X = 0
trigger1 = Pos Y > -2
trigger2 = AnimElem = 3
trigger3 = Time = [2,9]
Для любого из trigger1 до trigger3, которые должны быть проверены, условие triggerall должно быть true. В этом случае, пока X-скорость не равна 0, контроллер состояния не будет активирован. Если вам нужно, вы можете иметь более одного условия triggerall. Обратите внимание, как минимум один trigger1 должен присутствовать, даже если вы укажете triggerall.
Триггер постоянства
Если вы не хотите, чтобы триггер активировался каждый раз, когда условие true, вам нужно будет добавить persistent параметр. Начнем с примера:
[State 310, 1]
type = PosAdd
trigger1 = Vel Y > 1
x = 10
Этот контроллер состояния перемещает P1 вперед на 10 пикселей для каждого тика игрового времени, когда Y-скорость P1 больше 1. То есть, контроллер активируется каждый раз, когда условие триггера true. Если мы хотим, чтобы контроллер был активирован только один раз, нам нужно будет добавить строку:
[State 310, 1]
type = PosAdd
trigger1 = Vel Y > 1
persistent = 0 ;<-- Добавьте эту строку
x = 10
Peristent имеет значение по умолчанию 1, что означает, этот контроллер активируется каждый раз, когда триггер является true. Установка persistent 0 позволяет активировать контроллер только один раз во время этого состояния. Это верно, пока P1 не покинет это состояние. Если P1 вернется к этому состоянию позже, контроллер может быть активирован еще раз.
Постоянный параметр также может принимать значения, отличные от 0 и 1:
[State 310, 1]
type = PosAdd
trigger1 = Vel Y > 1
persistent = 2 ;<-- Измените эту строку
x = 10
В этом случае установка persistent на 2 означает, что контроллер будет активирован один раз каждые 2 раза, когда триггер будет true. Настройка persistent на 3 активирует контроллер каждые 3 раза и т.д.
Trigger перенаправление
Возможно, вы захотите проверить время жизни цели игрока или исходного игрока (если игрок является помощником) и т.д. Это возможно с помощью так называемого триггерного перенаправления. Подробнее см. в разделе «Выражения» этого поста.
Часто используемые контроллеры
Контроллер null будет полезен для отладки. Этот контроллер в принципе ничего не делает. Вы можете использовать его для временного отключения некоторых контроллеров, вместо того, чтобы закомментировать весь раздел. Например, вы можете отключить это:
[State 300, 1] ;Контроллер, который ускоряет P1 вперед
type = VelAdd
trigger1 = Time >= 0
x = .8
Просто закомментируйте type и поставьте null:
[State 300, 1] ;Контроллер, который ускоряет P1 вперед
type = null ;VelAdd
trigger1 = Time >= 0
x = .8
Позже, когда вы хотите повторно использовать контроллер, просто измените тип на то, что было раньше.
Теперь давайте рассмотрим пример:
[Statedef 200]
type = S
physics = S
movetype = I
ctrl = 0
anim = 200
velset = 0
[State 200, 1]
type = ChangeState
trigger1 = AnimTime = 0
value = 0
ctrl = 1
[State 200, 1] является контроллером ChangeState. Как следует из названия, оно изменяет номер состояния P1 (т.е. блок [StateDef], из которого выполняется P1). Параметр value должен иметь номер состояния для изменения. Необязательный параметр ctrl может быть установлен на флаг управления P1, когда он изменяет состояния.
Теперь давайте сделаем это состояние атакой. Прежде всего, действие анимации требует атаки коллизионных полей. Быстрый обзор документации AIR (см. 1 пост в этой теме): Clsn1 предназначен для атаки, а Clsn2 - это место, куда игрок может попасть. Таким образом, P1 попадет в P2, если любой из блоков P1 Clsn1 будет пересекаться с любым из блоков P2 Clsn2.
В качестве примера предположим, что действие анимации в файле AIR P1 выглядит следующим образом:
[Begin Action 200]
200,0, 0,0, 3
200,1, 0,0, 4
200,2, 0,0, 4
200,3, 0,0, 3
После определения ограничивающих полей это выглядит так:
[Begin Action 200]
Clsn2: 1
Clsn2[0] = -10,0, 10,-80
200,0, 0,0, 3
Clsn1: 1
Clsn1[0] = 10,-70, 40,-60
Clsn2: 2
Clsn2[0] = -10, 0, 10,-80
Clsn2[1] = 10,-70, 40,-60
200,1, 0,0, 4
Clsn2Default: 1 ;Используйте это поле для последних двух кадров
Clsn2[0] = -10,0, 10,-80
200,2, 0,0, 4
200,3, 0,0, 3
Как вы можете видеть, каждый элемент имеет форму Clsn2, определенную для него (последние два элемента используют одни и те же поля). Второй элемент - единственный с полем Clsn1.
Примечание. Все поля Clsn1 для любых элементов в действии анимации можно использовать, но если вы поместите поле Clsn1 в самый первый элемент, атака будет мгновенной и станет неблокируемой. Поэтому рекомендуется, чтобы вы определяли поля Clsn1 только для элементов после первого.
Теперь мы готовы настроить состояние в CNS. Объясним приведенные ниже изменения.
[Statedef 200]
type = S
physics = S
movetype = A ;<-- измените "I" на "A"
ctrl = 0
anim = 200
velset = 0
[State 200, 1] ;<-- добавьте этот state controller
type = HitDef
trigger1 = AnimElem = 2
attr = S, NA
animtype = Light
damage = 10
guardflag = MA
pausetime = 12,12
sparkxy = 0,-55
hitsound = 5,0
guardsound = 6,0
ground.type = High
ground.slidetime = 12
ground.hittime = 15
ground.velocity = -5
air.velocity = -2.5,-3.5
[State 200, 2]
type = ChangeState
trigger1 = AnimTime = 0
value = 0
ctrl = 1
Параметр movetype в StateDef имеет значение A для «совершения атаки». Не забудьте сделать это для всех состояний атаки. Как и прежде, P1 возвращается в свое состояние после того, как его анимация закончилась.
Этот контроллер HitDef выглядит как монстр! Не волнуйтесь, мы рассмотрим его медленно.
type = HitDef
trigger1 = AnimElem = 2
Это указывает тип контроллера как HitDef, что означает «Определение удара». Он запускается (trigger) во втором элементе анимации. Любой блок Clsn2 с момента активации триггера примет определение этого удара.
Если, например, у вас был Clsn1 как во втором, так и в третьем элементе анимации, запуск одного HitDef во втором элементе делает его применимым к обоим элементам анимации. Таким образом, P1 ударит не более одного раза: если второй элемент ударит, третий промахнется. Если второй элемент промахивается, третий может по-прежнему ударить. Чтобы атака совершалась дважды, вы должны вызвать trigger HitDef для каждого из двух элементов.
Это атрибут атаки. Он используется для определения того, может ли атака попасть в P2. В этом случае это стойка нормальная атака.
attr имеет формат attr = arg1, arg2, где:
- arg1 - либо S, C, либо A. Подобно типу statetype для StateDef, это говорит о том, является ли атака стоячей (S), приседающей (C) или воздушной атакой (A).
- arg2 - 2-символьная строка. Первый символ либо N (normal) для «нормального», либо S (special) для «специального», либо H (hyper) для «гипер» (или «супер», как это обычно принято). Второй символ должен быть либо A (attack) «для атаки» (обычный удар атаки), Т (throw) для «броска», либо Р (projectile) для снаряда.
Это относится к типу анимации, в которую попадает P2 при совершение ему атаки. Выбирайте из light (легкая), medium (средняя), hard (тяжелая) или back (задняя). Первые три должны быть понятны. Back - это анимация, в которой P2 сбит с ног.
Это урон, который P2 получает при попадании, и не получает урон, если он защищается (блокирует). Если мы изменим эту строку на damage = 10, 1, тогда это будет наносить 1 пункт урона, когда игрок будет обороняться.
Guardflag определяет, как P2 может защитить атаку. Здесь он может быть защищен высоким High (стойка), низким Low (приседающим) и в воздухе. Аргумент должен быть строкой символов, которая включает любое из следующего: H для «high», L для «low» или A для воздуха. M Mid (середина) эквивалентна выражению HL.
Это время, когда каждый игрок останавливается на ударе. Первый аргумент - время заморозки P1, измеренное в tick игры. Второй момент - это время, когда P2 ошеломлен, прежде чем отступить от удара.
Это - то, где происходит вспышка удара/обороны. Аргументы должны быть в форме X, Y. X относительно фронта P2. Отрицательный X делает вспышку глубже внутри P2. Y относительно P1. Отрицательный Y делает вспышку выше.
Это звук, который можно воспроизвести при ударе (из fighter.snd). Включенный fight.snd позволяет вам выбирать от 5,0 (легкий звук удара) до 5,4 (болезненный удар). Чтобы воспроизвести звук из собственного файла SND игрока, перед первым номером следует указать S. Например, hitsound = S1,0.
Этот звук играет при обороне (из fight.snd). Сейчас у нас только 6,0. Чтобы воспроизвести звук из собственного файла SND игрока, перед первым номером следует ввести S.
Это тип атаки для наземных атак (это также по умолчанию относится и к воздушным атакам, если вы не указали параметр air.type). В данном случае это высокая атака. Выберите High для атак, которые отталкивают голову назад P2, Low для атак, которые выглядят так, как будто они попали в живот, Trip для атаки низкого размаха или None, чтобы ничего не делать с P2. Атаки с High и Low уровнями одинаковы на P2, если AnimType - Back.
Это время в игровых tick, которое P2 отскакивает назад после удара (на этот раз не включено время паузы для P2). Применимо только для ударов, которые удерживают P2 на земле.
Время, когда P2 остается в состоянии удара после атаки. Применимо только для ударов, которые удерживают P2 на земле.
Начальная скорость X для P2 после получения удара, если P2 находится в состоянии стойки или приседания на земле. Вы можете указать Y-скорость в качестве второго аргумента, если вы хотите, чтобы P2 был выбит в воздух, например ground.velocity = -3, -2.
Начальная скорость, которая задается P2, если P2 попал в воздух.
Есть больше вещей, которые вы можете контролировать в HitDef, тут мы всего лишь разобрали приведенный выше пример. Подробнее см. документацию по sctrls.
Общие состояния (common1.cns)
Если вы посмотрите на файл DEF игрока, то увидите строку:
stcommon = common1.cns ;Общие состояния
Каждый игрок распределяет некоторые общие состояния, которые являются основными элементами игрового движка. Эти общие состояния находятся в data/common1.cns. Некоторые примеры - состояния для запуска и получения удара. Полный список имеется в Номерах специальных состояний дальше этого поста.
Если существует общее состояние, которое вы хотели бы переделать для конкретного игрока, все, что вам нужно сделать, это сделать состояние в CNS этого игрока с тем же номером, что и тот, который вы хотели бы переделать. Затем, когда игрок переходит к определенному номеру состояния, он вводит это новое состояние, а не одно в common1.cns.
Вы должны помнить, что при изменении определенных состояний, которые имеют специальные свойства, закодированные внутри M.U.G.E.N, новые состояния, которые вы делаете, будут по-прежнему иметь те же особые свойства, что и те, которые вы переделали. Например, состояние бега (state 100) задает скорость игрока любым значениям, указанным в его переменных игрока. Если вы измените state 100, новое состояние будет по-прежнему иметь свойство установки скорости игрока.
Общим примером является переопределение состояния ходьбы. Поведение M.U.G.E.N по умолчанию для текущего состояния состоит в том, чтобы игрок продолжал двигаться вперед с постоянной скоростью, пока вы не отпустите клавишу «вперед». В этот момент он возвращается в состояние ожидания.
Теперь предположим, что мы хотим, чтобы этот игрок (назовем его P1) вместо этого перепрыгнул вперед, точно так же, как и совершил двойной прыжок назад по умолчанию. Вы можете сделать состояние в P1 файла CNS:
; {RUN_FWD (перезаписан на type-рывок)
[Statedef 100]
type = S ;Ходьба по земле
physics = N ;Мы определим нашу собственную физику
anim = 100 ;Анимационное действие 100
ctrl = 0 ;Нет контроля за продолжительностью рывка
[State 100, 1] ;Чтобы начать рывок вперед
type = VelSet
trigger1 = Time = [0,5]
x = 6
[State 100, 2] ;Трение после первоначального рывка
type = VelMul
trigger1 = Time > 5
x = .85
[State 100, 3] ;
type = ChangeState
trigger1 = AnimTime = 0
value = 0
ctrl = 1
Здесь мы предполагаем, что Action 100 имеет конечное время цикла. Скорость в run.fwd под [Velocity] переменных игрока не игнорируется, но [State 100,1] переопределяет эту деталь, установив скорость X равным 6.
Номера специальных состояний
Если вы не планируете изменять общее состояние, избегайте выбора номеров состояний в диапазоне 0-199 и 5000-5999. Вот список состояний в common1.cns.
Номер | Описание |
0 | Стойка |
10 | Встать на корточки |
11 | Приседание |
12 | Встать с корточек |
20 | Походка |
40 | Подготовка к прыжку |
45 | Начало прыжка в воздух |
50 | Подпрыгнуть |
52 | Приземление |
100 | Бег вперёд |
105 | Скачок назад |
106 | Рывок назад (по земле) |
120 | Оборона (запуск) |
130 | Стойка обороны (удержание) |
131 | Оборона сидя (удержание) |
132 | Оборона в воздухе (удержание) |
140 | Оборона (окончание) |
150 | Удар в блок (встряска) |
151 | Удар в блок (отброшен назад) |
152 | Удар в блок сидя (встряска) |
153 | Удар в блок сидя (отброшен назад) |
154 | Удар в блок в воздухе (встряска) |
155 | Удар в блок в воздухе (сбит) |
170 | Проиграл (время кончилось) |
175 | Ничья (время кончилось) |
190 | Предварительное вступление |
191 | Вступление (измените это состояние, чтобы дать персонажу вступление) |
5000 | Стойка, получить удар (встряска) |
5001 | Стойка, получить удар (отброшен назад) |
5010 | Сидя, получить удар (встряска) |
5011 | Сидя, получить удар (отброшен назад) |
5020 | В воздухе, получить удар (встряска) |
5030 | В воздухе, получить удар (отброшен) |
5035 | В воздухе, получить удар (переходное состояние) |
5040 | В воздухе, получить удар (восстановится, не падение) |
5050 | В воздухе, получить удар (падение) |
5070 | Споткнуться, получить удар (встряска) |
5071 | Споткнуться, получить удар (отброшен) |
5071 | Споткнуться, получить удар (отброшен) |
5080 | Сбитый, получить удар (встряска) |
5081 | Сбитый, получить удар (отброшен назад) |
5100 | Сбитый, получить удар (удар о землю после падения) |
5101 | Сбитый, получить удар (отчеканить от земли) |
5110 | Сбитый, получить удар (лечь) |
5120 | Сбитый, получить удар (подниматься) |
5150 | Сбитый, получить удар (умереть) |
5200 | В воздухе, получить удар (восстановление после падения на землю; продолжение падения) |
5201 | В воздухе, получить удар (восстановление после падения на землю) |
5210 | В воздухе, получить удар (восстановление падения в воздухе) |
5500 | Экран анимации Continue |
5900 | Инициализация (в начале раунда) |
Продолжение в следующем сообщении этой темы...
Материал перевел и подготовил Sceletron