ACS. Делаем добивания (Fatality). Часть 1.

Предисловие

Все те, кто играл в Brutal Doom, знают, что там есть система фаталити. То-есть, убийство от разных монстров, воспроизводит разную анимацию смерти. Нечто подобное, мы сегодня и реализуем.

Создаем камеру.

Камерой может стать любой актор (декорация, монстр, ракета). Серьзено, поэкспериментируйте, попробуйте создать монстра, привязать к нему tid, и использовать этот tid в ChangeCamera. Наблюдать игру от лица монстра, довольно таки забавно.

Нашей камерой будет, простейший невидимый актор. Пропишите следующий код к себе в DECORATE.

Actor ChaseCam
{
  Height 16
  Radius 8
  +NOGRAVITY
  +NOBLOCKMAP
  States
  {
  Spawn:
    TNT1 A -1
    stop
  }
}

Теперь напишем скрипт, который переместит камеру за спину игрока, и активирует её.

Разбираемся в скрипте.

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

script "FatalityCamera" (void) {
	Thing_Stop(0);
	SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);
	int angle = GetActorAngle(0);
	int radius = 128;
	int x = GetActorX(0);
	int y = GetActorY(0);
	int z = GetActorZ(0) + 41.0;
	while (!Spawn("ChaseCam", x - cos(angle)*radius, y - sin(angle)*radius, z, 1337, angle >> 8)) {
		radius -= 8 >> 16;
	}
	ChangeCamera(1337, 0, 0);
}

Разберем, подробно, данный скрипт.

Подготавливаемся

Thing_Stop(0);

Сбрасываем скорость у игрока

SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);

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

int angle = GetActorAngle(0);

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

int radius = 128;

Задаем расстояние, на котором будет размещена камера, относительно игрока.

int x = GetActorX(0);
int y = GetActorY(0);
int z = GetActorZ(0) + 41.0;

Получаем координаты x, y, z игрока. Координату z я поднял, что-бы она, не лежала на полу.

Спавним камеру

while (!Spawn("ChaseCam", x - cos(angle)*radius, y - sin(angle)*radius, z, 1337, angle >> 8)) {
  radius -= 8 >> 16;
}

За спавн камеры, отвечает комманда Spawn, синтаксис у неё следующий:

Spawn("название_актора", x, y, z, tid, угол)
  • название_актора — задает название актора в DECORATE.
  • x, y, z — задают расположение в 3D пространстве.
  • tid tid нового актора.
  • угол — задает угол актора.

Также, данная функция, возвращает количество созданных акторов (1 — актор заспавнился, 0 — актор, не заспавнился). Это важно, потому-что комманда Spawn, спавнит не везде, а только, внутри карты.

Таким образом, цикл будет продолжаться до тех пор, пока камера не заспавнится.

while (!Spawn("ChaseCam", x - cos(angle)*radius, y - sin(angle)*radius, z, 1337, angle >> 8)) {

Пошли дальше разбирать. Для удобства, я продублирую синтаксис комманды Spawn.

Spawn("название_актора", ???, ???, ???, tid, угол)
  • название_актора — ChaseCam (наша камера).
  • tid — 1337 (tid камеры)
  • угол — угол игрока, сконвертированный в нужный формат angle >> 8

Остановимся подробнее на конвертации угла. Изначально, GetActorAngle возвращает угол игрока (значение от 0.0 до 1.0), то-есть дробное значение. Так вот, в ACS не существует дробных значений, а число 1.0, на самом деле является целочисленным числом 65536 или (2^16). Просто, в голове, нужно держать сдедующее правило 1.0 = 65536.

Функция Spawn, в качестве угла, принимает значение от 0 до 255 (2^8). По этой причине, мы воспользовались битовым сдвигом angle >> 8, на 8 ячеек вправо (>>). Кстати, операция битового сдвига эквивалента делению на 2 в степени «количество ячеек«.

То-есть, angle >> 8, можно представить как angle / 2^8. Тогда как angle << 8, можно представить как angle * 2^8

Дальше, разберем координаты x, y.

x - cos(angle)*radius
y - sin(angle)*radius

Используя данные формулы, мы получаем координаты x,y, в зависимости от поворота игрока, на расстоянии в radius. Кстати, нечто подобное, мы уже использовали для построения круга, в уроке ACS. Управляем частицами (SpawnParticle).

Идем дальше.

while (!Spawn("ChaseCam", x - cos(angle)*radius, y - sin(angle)*radius, z, 1337, angle >> 8)) {
  radius -= 8 >> 16;
}
radius -= 8 >> 16;

Если не получилось заспавнить камеру, то пробуем заспавнить поближе.

Последнее что осталось, переключиться на созданную камеру.

ChangeCamera(1337, 0, 0);

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

Итоговый результат

avatar