Блог ☯

пятница, 4 ноября 2016 г.

Как сделать скрытность и стелс в игре. Как сделать стелс игру

Привет! Делаю игру я короче ну и захотел добавить элемент стелса. stealth - осторожное или скрытное движение. Самолёт такой есть, Американский. Вспоминая хорошие игры где есть этот элемент, мне приходят на ум Проклятые земли (Аллоды 3), silent storm, ну и немного этого есть в 12 is better than 6. Есть еще много где (и где он еще лучше), но я вспомнил сейчас только эти так-как в них играл дольше остальных.

Делаю игру я в game maker studio, однако где-бы вы не делали, вам всё это может пригодиться в любом случае. Скажу сразу, базу я взял из видео вот этого человека, но оно на английском, так-что тут я расскажу по нашенски.

Как сделать скрытность и стелс в игре. Как сделать стелс игру

Вот примерно так всё работает в моей игре

Сейчас я сделал уже всё, кроме одного - угол обзора. Это тоже можно сделать и тот человек рассказывал как, не так уж и сложно. Но в моём случае проблема со спрайтами. Я не делаю 100%-й вид сверху, я делаю чутка изометрию в плане некоторых спрайтов. Не знаю верно или нет, просто как-то так начал. И даже в моём виде можно сделать угол обзора, может и сделаю, но позже.

Сейчас есть вот что, в плане скрытности, невидимости и стелса:

- Дальность видимости врагов

Это легко и это понятно в общем, как делать

- Враги не видят вас за препятствиями

- Дальность слуха врагов

Примерно тоже самое, что и дальность видимости. Я сделал 50% от дальности видимости базовое значение. 

- Разные действий дают разный шум

Выстрелы, перезарядка, поднятие предметов, открывание дверей (будет) и т.д. 

- Есть специальные объекты для скрытности

Сейчас это лес (деревья) и тень. Тень это отдельная песня... 

- Приседание, режим крадучести

Герой двигается в 2 раза медленнее, издаёт 0 шума, стреляет в 2 раза точнее, но в 2 раза медленнее.  Кроме того у MP5 с глушителем в таком режиме увеличивается урон. С 0-1 до 0-2. По сути дела сейчас у меня только MP5 - оружие, специально для тихого убийства. Выстрелы из него имеют нулевой шум. 

Эти две вещи взаимно независимы. Это значит что если враг вас не видит, то он может вас услышать и наоборот. Если он вас не слышит, то может тупо увидеть. В любом из сценариев он пойдет  в вашем направлении. Что-бы враг на вас не реагировал, нужно что-бы он вас и не видел, и не слышал. 

Давайте посмотрим нагляднее на то, как работает видимость. И как сделать стелс игру.


Дальность обзора это штука понятная. Просто пишем допустим 500, переменную vision у врага. И привязываем реакцию на это. Допустим:

if distance_to_object(o_hero)<vision
{
// что мы хотим делать дальше. Либо идти на героя, либо например просыпаться. 
}

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

Что-бы не видели вас за укрытиями, пишем вот такую функцию - скрипт.

if (!collision_line(x,y,o_hero.x,o_hero.y,o_walls,false,true))

То есть просто достаточно. Эта штука "если да (!)". То есть просто пихаем это в еще одно условие реакции в случае видимости, в итоге будет вот так:

if (!collision_line(x,y,o_hero.x,o_hero.y,o_walls,false,true))
if distance_to_object(o_hero)<vision {// что мы хотим делать дальше. }

Первые х, у - это врага, вторые х, у - это героя. Дальше - объект который загораживает обзор. В моём случае это родительский объект - o_walls. У скал, стен и ящиков он указан как родитель (parent).

Вот в общем-то и всё с видимостью. Эту штуку:

 if (!collision_line(x,y,o_hero.x,o_hero.y,o_walls,false,true))

В этом-же виде можно еще и зафигачить много куда. К примеру и герой может не видеть врагов если они не на линии видимости. Это игру сильно усложнит. на скрине герой видит врага,а в ообще, он не должен его видеть. То есть что-бы всё было честно и герой тоже не должен видеть через стены. Делается это аналогичной функцией, но наоборот. 

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

Видимость я прописал вот так: (в step героя)

if(place_meeting(x, y, o_tree))
{
    global.hiding = 0.25;
}
else if(place_meeting(x, y, o_shadow))
{
    global.hiding = 0;
}
else
{
    global.hiding = 1;
}

Получается что фактор 0.25 (увидит на расстоянии 500*0.25=125) если мы в кустах. И фактор 0 - не увидит никогда, если мы в тени. Тень еще не до конца сделал.

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


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

Как нам пройти это здание снизу вверх, что-бы нас не увидел враг, который там стоит? 

Кстати, не забывайте что в game maker можно растягивать объекты на карте (room), так удобно делать всякие области, как раз область теней, например. 

Есть условно 2 пути. (А еще можно здание просто обойти, лол)

Как сделать скрытность и стелс в игре. Как сделать стелс игру

Зелёный путь - это грамотный

Там где галочка, можно врага будет зарезать. А вот красный - плохой. Так-как свет идёт через окно и он нас увидит. Вообще глупо как-то получается что враг нас не будет видеть на таких близких дистанциях, но уж как есть... Конечно же крадёмся мы тут, а не бежим. Если бежать, то он нас в тени тоже не увидит, но услышит

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

То-есть надо всё продумывать, а иначе можно будет придраться. Плюс еще момент, например ящики. Они тоже по идее должны тень иметь, но вот что делать когда и если ты их сломаешь? Убивать тень, скажете вы, но это тоже не так уж и легко сделать. 

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

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

Со слухом тоже интересно.

Скрытность в играх, как это работает

Вот примерно такая градация дистанции

Например мы начинаем идти из-за камней по лесу, сверху. Можем спокойно пройти пол пути, так-как область слуха 50% от дальности видимости, а фактор видимости в лесу 0.5 (50%). А вот дальше если побежим по лесу - услышит. Дальше можно подкрадываться. При чём, подберёте пули рядом с ним - услышит. Ну и понятно что если выйти снизу от камней, то сразу увидит. Как и если выскочить из леса на любом этапе. 

А если громко жахнуть, например из АК, даже ЗА ДАЛЬНОСТЬЮ видимости, то он может побежать на шум. Фактор шума у АК допустим 3. Это значит что видимость 500, базовый шум 250, а выстрел из АК сделает область шума уже (х3) 750! Понимаете как оно работает? А если оружие с глушителем, то фактор шума можно делать 0-1, например. И можно даже стрелять во врага и он не будет реагировать, если быть в скрытности. 

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

Но что можно сделать как минимум, это точки внимания, так сказать (сам назвал сейчас) и базовые точки. Что это такое и зачем? 

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

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

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

Стоит сказать что делать всю эту механику скрытности и стелса довольно муторно и затратно. Приходится учитывать множество мелочей.

Допустим фактор шума при выстреле я приписал вот так:

if global.weapon=1 then global.noise=2 // пистолет
if global.weapon=2 then global.noise=2.25 // шотган
if global.weapon=3 then global.noise=0 // мп5 с глушителем
if global.weapon=4 then global.noise=2.5 // калаш
if global.weapon=5 then global.noise=3 // снайперка
if global.weapon=7 then global.noise=2 // крутой автоматик

global.noise=2 означает 100% от видимости (слух изначально 50% от видимости). То есть...
Если мы стоит в дальности видимости врага, только что в неё зашли, но враг нас не видит, то:

Выстрел из любого оружия кроме мп5 привлечет его внимание. А факторы 2.25, 2.5 и 3 привлекут даже дальше чем стандартный обзор. Например выстрел из снайперки он услышит на расстоянии 750, в то время как увидеть нас он может только на дистанции до 500, если мы не за препятствием и не в кустах.

И тут же много чего еще нужно делать. Допустим вы стрельнули из снайперки там, где вас никто не услышал, вроде всё ок. Но пуля например попала в метал, где-то уже ближе к врагам. Вот это тоже фактор шума и тоже нужно это учесть.

Или-же, вот подкрались вы к врагу из тени и например начали стрелять по нему с мп5. Сейчас теоретически есть такая дистанция где можно убить врага так и он даже не среагирует. Ибо фактора шума у мп5 нет совсем. Но враг урон то получает. И будет просто стоять как истукан. А как надо сделать? 

А надо что-бы при получении урона он начинал орать что-то типа "на помощь" и пытался уйти за укрытие. Его крик это был-бы тоже фактор шума и он-бы привлекал его друзей. Но если его убить быстрее чем допустим за 1 секунду (например с одного удара ножем) то он и закричать не успеет.

Чуть не забыл сказать о еще одной проблеме. Допустим что у вас прописано вот так:

В step у врагов. 

//VISION
if instance_number(o_hero)>0
if (!collision_line(x,y,o_hero.x,o_hero.y,o_walls,false,true))
if distance_to_object(o_hero)<vision*global.hiding{
mob_sleep=0
}
// NOISE
if distance_to_object(o_hero)<vision*global.noise/2{
mob_sleep=0
}

Тут сразу куча проблем, хотя всё и может с виду работать нормально. Тут 2 разных кода, 1 активирует моба при видимости, другой при шуме. Когда mob_sleep=0 (не спит) то он начинает действовать. Идти на героя или делать что-то еще. Однако!

Проблема номер 1, хотя и странноватая это что слух это просто та-же видимость делить на 2 и фактор шума (global.noise) вместо фактора скрытности (global.hiding). Но что если вы сделайте допустим контузия у врагов (потеря слуха от взрыва), прикольно же такое сделать? Или например слепоту. 

Вы конечно можете в такой ситуации просто изменить global.hiding и global.noise, но ведь не можете! Нам нужны локальные переменные врага. Слепота должна резать его видимость, а не увеличивать вашу скрытность. Поэтому лучше делать отдельно локальные  vision (500) и hearing (250). Плюс тут еще проблема. 

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

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

Вот и всё на этот раз, рассказал всё что знаю про то, как сделать скрытность и стелс в игре. Я не говорю что это идеальная система и что я супер эксперт в стелс играх, скрытности и т.п. Просто рассказал один из вариантов как сделать механику скрытности в 2D игре. 

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

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