Привет всем! Хотел запостить в нубских вопросах, но, думаю, лучше создать отдельную тему.
Наверняка все видели анимацию приземления в csgo, когда вид от первого лица плавно и слегка пружинит вниз и возвращается обратно. Честно сказать, парюсь уже недели две, если не больше. До последнего не хотел создавать тему и пытался разобраться сам, но ничего не выходит. Надеюсь на какую-нибудь помощь. В общем, вот сам код из исходников csgo, который я нарыл:
Куда вставить этот код (конечно же не в этом виде!) я нашел - это в функцию PM_CheckFalling в playermove.cpp на сервере.
Изначально я сделал все проще и одной строчкой:
Ну такое, ага… Слишком резкое, и наклон идет не вертикальный, а вперед. В целом, вполне сошло бы, но что-то как-то не. Я даже пытался менять функцию punch, делая ее плавнее, но тогда "сломал" другие места, где она используется. Принял решение копать в другую сторону. Мне бы подошла функция из PM_Duck. Потому что если в ксаш-моде быстро нажать и отпустить приседание, камера плавно спускается вниз и тут же плавно возвращается. Но там все завязано, как я понял, на проверке "нажато ли приседание в текущем кадре, если нет - возврат".
Дальше идет полное ламерство. Все изменения, как уже сказал, делал в конце PM_CheckFalling - там, где стоял мой простой punchangle. Не знаю, корректно ли это, но я хотя бы уверен, что именно в этом месте выполняется код после приземления.
Итак: есть, значит, такая штука в коде, как pmove->view_ofs[2], которая отвечает за высоту взгляда игрока. Я логично рассудил, что мне "всего лишь" надо сделать, чтобы это значение после приземления плавно спускалось от дефолтного VEC_VIEW и, достигнув определенного значения, так же плавно вернулось обратно. В итоге я попробовал написать вот такую фигную:
C++ Source Code:
pmove->view_ofs[2] -= 3 * pmove->frametime;
Полный бред, теперь я уже знаю (значение 3 для эксперимента было, может и не 3 там было, уже не суть; по итогу просто после каждого призмеления взгляд просто спускался ниже и ниже. Но, думаю, что начал копать в правильном направлении, т.к. все плавные изменения чего-либо в коде всегда были завязаны на frametime или time, как я заметил.
Пытался еще сделать проверку, что при достижении какого-то уровня взгляда он бы возвращался к VEC_VIEW. После этого вообще ничего не менялось, т.к. все условия, видимо, выполнялись разом. Я рассчитывал увидеть отскок, хотя бы резкий. Увы.
Дальше я пытался завести временную переменную, и как-то отсчитывать от нее, но опять ничего не получилось. Либо изменений не было, либо камера просто резко смещалась вниз, ни о какой плавности речи не было.
Дальше я снова вернулся к коду приседания и попытался как-то впаять эту плавность к себе в PM_CheckFalling:
Теперь при приземлении взгляд резко уходит вертикально вверх. Дальше уже ничего не вышло, либо ломалось все, либо так же взгляд уходил вверх.
Ну а дальше будет полный анекдот, можете просто посмеяться. Решил "адаптировать" функцию из csgo, прям копипастнул и отредактировал. С комментами.
Разумеется, ничего не получилось, кто бы мог подумать.
C++ Source Code:
1
#define clamp(a,b,c) (a = min(max(a, b), c)) // скопипастил сюда, иначе кламп не работал
2
float m_flFallVelocity = pmove->flFallVelocity;
3
float m_flOldFallVelocity = 0.0f; // взял из playerlocaldata.h (csgo)
4
bool m_bInLanding = false; // взял из playerlocaldata.h (csgo)
5
float m_flLandingTime = -1.0f; // взял из playerlocaldata.h (csgo)
6
7
Vector vecBaseEyePosition = pmove->view_ofs[2]; // вместо eyeOrigin, она же позиция глаз, видимо… поставил view_ofs. Ставил " = VEC_VIEW ", но тоже не сработало
8
9
// if we just landed, dip the player's view
10
float flOldFallVel = m_flOldFallVelocity; // m_Local.m_flOldFallVelocity; что такое м_локал, точно выяснить не удалось… поэтому решил переименовать так
// было if ( m_Local.m_bInLanding == true && ( (eyeOrigin.z - 0.001f) >= vecBaseEyePosition.z ) )
63
{
64
m_bInLanding = false;
65
}
66
67
if ( m_bInLanding == false )
68
{
69
// Set the old velocity to the new velocity, we check next frame to see if we hit the ground
70
m_flOldFallVelocity = m_flFallVelocity;
71
}
Компилит, но результата ноль, то есть вообще ничего не происходит. Надо полагать и не должно, т.к. я вообще не уверен, что я тут наделал (но надеялся, эх ).
В общем, ниасилил. Спасибо, что прочитали, может было интересно. Если кто может помочь адаптировать функцию или подсказать, как это сделать проще, буду очень благодарен. Сам в матане/линале не шарю, а уж в кодинге…слишком сложно оказалось. Вот регенерацию хп из Portal стащить получилось, а тут никак. Ну там и строчек-то совсем мало было…
абсолютно такой же прыжок есть в ку3, мб его сорцы помогут, не знаю. Есть ещё похожий эффект, не то, что нужно, но вдруг понравится:
pmove->punchangle[ 0 ] = -8; перед строкой PM_PreventMegaBunnyJumping(); и тоже самое перед строкой for (i =0; i < 2; i++) для прыжка сидя
Там не пунч, там надо высоту камеры немного вниз и плавно вверх. Ну если совсем по ламерски - подержать пару кадров присед при касании земли и отпустить.
JPEG писал: абсолютно такой же прыжок есть в ку3, мб его сорцы помогут, не знаю. Есть ещё похожий эффект, не то, что нужно, но вдруг понравится:
pmove->punchangle[ 0 ] = -8; перед строкой PM_PreventMegaBunnyJumping(); и тоже самое перед строкой for (i =0; i < 2; i++) для прыжка сидя
Ага, точно, в ку3 реально есть такое. Маловероятно, что я разберусь, но уже кажись нашел этот код (офигеть там много строчек), огромное спасибо за наводку!
То, что ты второе предложил, это тот же эффект, что и при прыжке с лонгджампом, ну так себе, да мне нужно именно плавное приземление.
В целом хотелось бы разобраться, как менять любое значение плавно. Везде, где хочется плавно поменять значение, у меня именно здесь все упирается и никогда не работает. Для примера, хочу опустить pmove->view_ofs[2] с 40 до 30. В течении 5 секунд скажем. Активируется функция и взгляд плавно идет вертикально вниз в течении этих 5 секунд. Вот как это сделать? pmove->view_ofs[2] -= 10 * pmove->frametime это все, на что меня хватило. Оно резко спускается и все. И я даже понимаю почему, это ведь по сути одноразовое изменение. Наверное, нужны переменные и формулы, но в математике я не силен.
Добавлено 04-08-2020 в 21:48:
Цитата:
Дядя Миша писал: Ну если совсем по ламерски - подержать пару кадров присед при касании земли и отпустить.
Во-во, я именно так и хотел сделать. Ток не раздуплю как пока что
Итак, я все-таки сделал это. Все-таки заставил работать код приседания, при этом я все равно не понимаю до конца, как он работает.
В общем, результат на видео. https://youtu.be/FCMkUrvSB9M
Я там еще нажимал в паре мест CTRL, проверял на застревания, но вроде все норм. Хочется поправить одну-единственную вещь здесь: просед слишком низкий, может у кого есть идея, как уменьшить его? Сделать не таким явным и более коротким, как в csgo.
Вот сам код, который заработал:
Вставлять его нужно в PM_CheckFalling после строчки
C++ Source Code:
// Knock the screen around a little bit, temporary effect
Кстати, имейте в виду, что у меня стоит threshold поменьше, поэтому у меня функция активируется при любом прыжке. Вам наверное придется спрыгнуть с большей высоты.
Повторюсь, хотелось бы уменьшить эффект немного, сделать его не таким явным. В остальном это то, что нужно! Я копал в сторону хуллов, менял pmove->origin (добавил *0.5 - получился плавный эффект). Подбирал другие числа там и тут, но без изменений.
Может кому пригодится или кто доведет его до ума…
Копаюсь дальше. Вариант выше не прокатит. Выявил баг, что при урона не будет при приземлении с любой высоты.
В общем, решил делать "по-нормальному". Залез в r_view.cpp на ксаше и в исходники quake 3.
Пока ничего не получается. Подскажите хоть, я вообще в правильном направлении иду или нет? Я очень слабо понимаю, что я вообще тут делаю.
ну и да, когда удар об землю есть - прекратить добавлять landtime и считать разность. За счёт чего и происходит временной эффект.
Тупым ковырянием тут можно еще долгие годы не иметь результата.
Ну вот я уже где-то месяц ковыряюсь наверное, все кодеры заняты (я даже не забесплатно предлагал), да и найти их не так-то просто, а тут так, мелкая хотелка.
static float я увидел на smooth stairs функции, только не знаю в чем разница, надо книги читать походу. Просто меня кодинг особо не интересует как класс, но кто еще будет фишки запиливать? Хоть какие-то туторы есть, и тому рад.
И математики много, тоже засада…
P.S. если есть желающие помочь, пишите в приват, в долгу не останусь
то что объявлено внутри функции теряет свои значения по её завершению, а static позволяет это сохранить до следующего вызова. Ну он не совсем для этого конечно.
Там в чём смысл - когда игрок в воздухе - присваиваем время в переменную landtime. Коснулся земли - начинаем считать разность между текущим временем и тем что осталось в landtime. И так получаем возрастающее со временем значение, которое и используется для анимации высоты взгляда.
Можно и по другому сделать конечно.
Я не уверен, что такое simvel, но как мне показалось это скорость ([2] - по вертикали). Значит если игрок летит вниз, начинаем считать. А потом когда onground, то выполняется функция.
В кваке 3 там вообще эта функция, начиная с дельты, просто лежит в FirstPersonOffset. Как они определили, что игрок приземлился, вообще не понимаю. Есть случай EV_FALL_SHORT, больше ничего не нарыл.