Перейти к содержанию

x64 Проектный Minecraft делаем полёт по повороту камеры


Рекомендуемые сообщения

В этой теме можно узнать о том, как сделать полет по повороту камеры в 3D пространстве (лететь туда куда смотришь) и как сделать перевод числа в 360, если оно превышаем 360 или наоборот, ниже нуля. Перед просмотром видео лучше ознакомится с предыдущими темами, так как там показано как найти адрес персонажа.
Скрипт- функция расчета ускорения из поворота:

Спойлер

[ENABLE]
alloc(FlyToCam,360)
//createthread(FlyToCam)
registersymbol(FlyToCam)
label(Angle)
label(upravlen)
label(multiplayer)
label(Veloctory)
registersymbol(Angle)
registersymbol(upravlen)
registersymbol(multiplayer)
registersymbol(Veloctory)


FlyToCam: //Старт функции ---
//Проверка с помощью FPU
fld dword [Angle+8] //Сюда будет писать вызывающий скрипт
fcom dword [StestChisl+4] //Сравниваем st(0) с нулём
fstsw ax //В регистр ax
sahf //Выталкиваем флаги в флаги обычного процессора ()_()
ja NoInvert //Если больше

fabs //Изменяем знак 360 после
fsubr dword [StestChisl] //Вычитаем из 360 наше число и получаем альтернативное положительное, fsubR вычитает не источник из приёмника а наоборот.

NoInvert:
fst dword [Angle+4] //Сохраняем не выгружая из стека
fdiv dword [StestChisl] //Делим на 360 и узнаем сколько раз оно там
//Вычитаем 0,5 и потом округляем, что бы округление происходило до целого нижнего
fsub dword [StestChisl+8]
frndint //Округление до ближайшего целого
//fst dword [Angle] //Делаем выноску что бы узнать нормальное число
fmul dword [StestChisl] //Умножаем на 360
fsubr dword [Angle+4] //Вычитаем из нашего числа 360 умноженое на округленное целое
{Это все должно дать нам поворот в 360 градусной системе,
даже если число будет 2763 или -315, поворот будет расчитан точно.}
fstp dword [Angle] //Выгружаем в поворот, нам же надо проверить работоспособность скрипта

fld dword [Angle]
fcom dword [StestChisl2] //Сравниваем st(0) с 90
fstsw ax //В регистр ax
sahf
ja p90 //Если больше
//Тут если от 0 до 90
fchs //Меняем знак
fst qword [Veloctory] //Записываем в 8 байт тип doble 1 часть от 90
fchs //Возвращаем знак
fsubr dword [StestChisl2] //Вычитаем из 90 наше число поворота
fst qword [Veloctory+8] //Записываем в 8 байт тип doble 2 часть от 90

jmp goend

p90:
fcom dword [StestChisl2+4] //Сравниваем st(0) с 180
fstsw ax //В регистр ax
sahf
ja p180 //Если больше
//Тут если от 90 до 180
fsub dword [StestChisl2] //Вычитаем 90
fchs //Меняем знак
fst qword [Veloctory+8] //Записываем в 8 байт тип doble 1 часть от 90
fchs //Возвращаем знак
fsubr dword [StestChisl2] //Вычитаем из 90 наше число поворота
fchs //Меняем знак
fst qword [Veloctory] //Записываем в 8 байт тип doble 2 часть от 90

jmp goend

p180:
fcom dword [StestChisl2+8] //Сравниваем st(0) с 270
fstsw ax //В регистр ax
sahf
ja p270 //Если больше
//Тут если от 180 до 270
fsub dword [StestChisl2+4] //Вычитаем 180
fst qword [Veloctory] //Записываем в 8 байт тип doble 1 часть от 90
fsubr dword [StestChisl2] //Вычитаем из 90 наше число поворота
fchs //Меняем знак
fst qword [Veloctory+8] //Записываем в 8 байт тип doble 2 часть от 90

jmp goend

p270:
//Тут если от 270 до 360
fsub dword [StestChisl2+8] //Вычитаем 180
fst qword [Veloctory+8] //Записываем в 8 байт тип doble 1 часть от 90
fsubr dword [StestChisl2] //Вычитаем из 90 наше число поворота
fst qword [Veloctory] //Записываем в 8 байт тип doble 2 часть от 90

jmp goend //Вот такие проверочки, если больше 90, больше 180, больше 270. на 4 отрезка окружности.

goend:
emms //Очистка стека FPU
fld qword [Veloctory]
fst qword [Veloctory] //1
fdiv dword [StestChisl2] //Делим на 90
fst qword [Veloctory] //2
fdiv qword [multiplayer] //Делим на делитель скорости
fstp qword [Veloctory]
fld qword [Veloctory+8]
fdiv dword [StestChisl2] //Делим на 90
fdiv qword [multiplayer] //Делим на делитель скорости
fstp qword [Veloctory+8]
ret //Конец функции ---


//Метки
upravlen:
dd 0

StestChisl:
dd (float)360 0 (float)0.5 //360, 0, 0.5
StestChisl2:
dd (float)90 (float)180 (float)270 //Части проверки для круга

Angle:
dd 0 0 0

multiplayer:
dq 4024333333333333 //10.1 doble

Veloctory:
dq 0 0

[DISABLE]
unregistersymbol(FlyToCam)
unregistersymbol(Veloctory)
unregistersymbol(multiplayer)
unregistersymbol(upravlen)
unregistersymbol(Angle)
dealloc(FlyToCam)

 

 

Скрип записывающий в ускорение игрока и вызывающий функцию выше:

Спойлер

[ENABLE]
alloc(callFlyTo, 120)
createthread(callFlyTo)

callFlyTo:
cmp byte ptr [upravlen],5
je retmetka
cmp byte ptr [upravlen],1
jne callFlyTo

mov esi,[playeradress+4]
mov eax,[esi+88] //Поворот
mov [Angle+8],eax

call FlyToCam //Вызов инструкции
movq xmm0,[Veloctory]
movq [esi+48],xmm0
movq xmm0,[Veloctory+8]
movq [esi+58],xmm0

//Вызов инструкции для X,Z осей поворота
mov eax,[esi+8C] //Поворот
mov [Angle+8],eax

call FlyToCam //Вызов инструкции
movq xmm0,[Veloctory]
movq [esi+50],xmm0



jmp callFlyTo

retmetka:
ret


[DISABLE]
dealloc(callFlyTo)

 


Видео:
Часть 1:

Спойлер

 


Часть 2:

Спойлер

 


Часть 3:

Спойлер

 

 

Изменено пользователем inaginary
  • Понравилось 2
  • Плюс 3
Ссылка на комментарий
Поделиться на другие сайты

Нормализовать угол поворота камеры можно также и следующим образом

Спойлер

fld dword ptr [Value_360]
fld dword ptr [Original_Game_Angle]
fabs
fprem
fstp st(1)
fstp dword ptr [Normalized_Angle]

 

 

fcos и fsin работают с радианами, поэтому для корректного их использования, необходимо конвертировать значение угла из градусов в радианы

Спойлер

fld dword ptr [Value_360]
fld dword ptr [Original_Game_Angle]
fabs
fprem
fstp st(1)
fdiv dword ptr [Degress_Converting_Value]
fstp dword ptr [Normalized_Angle_Radians]


Value_360:
dd (float)360
Degress_Converting_Value:
dd (float)57.29577951308232

 

 

Интересно было посмотреть на реализацию этого и предыдущего замыслов. Наверно это оттого что я и сам некогда недавно занимался этими же вопросами.

 

*Что если необходимо сделать плавное перемещение (полёт) игрока до некоторой точки в пространстве, используя при этом лишь только 3 координаты положения игрока и 3 координаты положения точки, при условии что скорость перемещения должны быть всегда одной и той же, как для малых дистанция, так и для больших.  Так же по возможности необходимо сделать плавное увеличение и плавное уменьшение скорости полёта, например от 0 до 10 % пути, сделать плавное увеличение скорости, а от 90-100% пути сделать плавное уменьшение скорости, до 0.

Осилил бы такую задачу?

  • Спасибо 1
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Antonshka сказал:

*Что если необходимо сделать плавное перемещение (полёт) игрока до некоторой точки в пространстве, используя при этом лишь только 3 координаты положения игрока и 3 координаты положения точки

То есть ты предлагаешь не использовать ускорение?
Мною были запущены fsin и fcos и с радианами и с градусами в отдельном скрипте для тестов, получалась какая то ерунда что в радианах, что в градусах, возможно я просто не правильно их использую.
Вообще, спасибо за упрощённые методы, а в математике я не очень (особенно с этими градусами) То что в моём скрипте находит части не окружности а ромба, но разницы особо нету, разве что в немного неровном ускорении

То что ты предлагаешь - полет с постоянной скоростью, реализовывается просто с прибавлением фиксированных значений к координатам
 

 

Изменено пользователем inaginary
Ссылка на комментарий
Поделиться на другие сайты

1 час назад, inaginary сказал:

То что ты предлагаешь - полет с постоянной скоростью, реализовывается просто с прибавлением фиксированных значений к координатам

Если есть желание, то сделай наглядный пример написанного

 

Условия вот такие:

1 - Использовать можно только координаты X,Y,Z игрока и X,Y,Z точки назначения

2 - Скорость полёта должна быть одна и та же, для разных дистанций

3 - По возможности, сделать плавное увеличение скорости в начале, и плавное уменьшение скорости в конце

 

Плавное увеличение скорости должно происходить на протяжении первых (к примеру) 30 метрах пути, а плавное уменьшение скорости должно происходить на протяжении последних (к примеру) 30 метрах пути.

30 метров пути в начале и в конце - расстояние статичное, для любых дистанций.

Изменено пользователем Antonshka
Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, Antonshka сказал:

30 метров пути в начале и в конце - расстояние статичное, для любых дистанций.

И как по твоей схеме должны обрабатываться расстояния меньше чем 60 метров?
В таком случае будет просто ускорение или замедление будет обрываться не заканчиваясь по прилету на точку, если уж ты мне условие написал то учти и этот аспект

Изменено пользователем inaginary
Ссылка на комментарий
Поделиться на другие сайты

10 минут назад, Antonshka сказал:

Использовать можно только координаты X,Y,Z игрока и X,Y,Z точки назначения

Я конечно сделаю ради интереса, но все же не вижу смысл так изгаляться, и меня не отпускает стойкое ощущение что ты то уже знаешь как по твоему проще сделать, и задаешь мне вопрос что бы увидеть как это у меня получится, а потом написать мне свой способ и если он проще, указать на это :lol:

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, Antonshka сказал:

Если есть желание, то сделай наглядный пример написанного

Делаю я, делаю наглядный пример, и тут до меня доходит что координаты в структуре визуальные, а сервер будет откидывать без ускорения, это произошло как раз в тот момент как моего персонажа колбасило по всей комнате из за неправильного скрипта.
Мною была использована команда fprem для нахождения остатка при делении на 1. Еще была идея сделать с кучей проверок, это я могу запросто, правда вот 100% уверенность что все делается намного проще.

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, inaginary сказал:

И как по твоей схеме должны обрабатываться расстояния меньше чем 60 метров?

Верно подмечено

 

Но, пусть будет так:

Если расстояние будет (к примеру) всего 20 метров, то игрок, не закончив плавное ускорение, остановиться.

Если расстояние будет (к примеру) всего 40 метров, то игрок, не закончив плавное замедление, остановиться.

 

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

 

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

Ссылка на комментарий
Поделиться на другие сайты

43 минуты назад, Antonshka сказал:

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

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

Изменено пользователем inaginary
Ссылка на комментарий
Поделиться на другие сайты

Antonshka

Вот на примере 1 координаты, если больше то вычитаем, меньше то добавляем, и так двигаем персонажа (с постоянной скоростью) к точке где будет 0, то есть к нашей сохраненной точке, такое делается на все координаты.
Я думаю можно сделать как то проще.
 

Спойлер

movetocoords: //Полет на позицию
fld qword [savecoords1] //Сохраненная позиция Х
fsubr qword [eax+30] //Координаты игрока Х
fcomp qword [multiplayer] //Сравниваем st(0) с нулём
fstsw ax //В регистр ax
sahf //Выталкиваем флаги в флаги обычного процессора
ja subcoordX //Если больше

//Если меньше - вычитаем
fld qword [eax+30]
fadd dword [multiplayer2+4] //Добавляем еденичку (к примеру)
fstp qword [eax+30]

jmp next

subcoordX: //Если больше - прибавляем
fld qword [eax+30]
fsub dword [multiplayer2+4] //Вычитаем еденичку (к примеру)
fstp qword [eax+30]

 

 

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

Понял твою идею, у меня немного другая.

Если доделаешь до конца и запишешь видео с результатом, по желанию конечно, - то будет очень даже неплохо.

Я также, в случае успеха, постараюсь записать видео и выложить скрипт.

 

Ссылка на комментарий
Поделиться на другие сайты

При способе, который ты используешь, не будет ли движение не прямолинейное?

 

Спойлер

123jpg_3338126_29430011.jpg

 

Здесь на рисунке, координаты игрока X = 0, Z = 0, координаты точки назначения X = 10, Z = 2. Если начать одновременно прибавлять 1 к Z координате, и 1 к X координате, то после того как значение Z уже станет равным 2, прибавление к X координате всё ещё будет продолжаться, и как следствие получится не прямолинейное движение.

Ссылка на комментарий
Поделиться на другие сайты

53 минуты назад, Antonshka сказал:

При способе, который ты используешь, не будет ли движение не прямолинейное?

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

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, Antonshka сказал:

При способе, который ты используешь, не будет ли движение не прямолинейное?

Если так хочется сделать, то почему бы не найти угол между точками, и потом сделать так же как в теме в которой мы сейчас пишем, я имею ввиду: (твой рисунок с моими дорисовками)

Спойлер

5a8b407cf3f47_.thumb.png.cb0c2e6c3fbdfa56ef116b4a869c391a.png


При этом можно просто записывать полученные значения не в ускорение а сразу в координаты (добавлять), но сначала их сильно уменьшить с помощью деления, и опять же - деление будет скоростью.
А на счет замедления и ускорения просто проверять расчетное расстояние между точками.

Изменено пользователем inaginary
Ссылка на комментарий
Поделиться на другие сайты

10 часов назад, inaginary сказал:

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

Конечно так проще, но в том то и есть весь спортивный интерес, чтобы попытаться сделать примерно тоже, но без использования Velocity

 

9 часов назад, inaginary сказал:

Если так хочется сделать, то почему бы не найти угол между точками, и потом сделать так же как в теме в которой мы сейчас пишем, я имею ввиду: (твой рисунок с моими дорисовками)

Если будет желание, то напиши полностью рабочий скрипт + видео к нему. Свой скрипт я уже почти дописал, и также в случае  работоспособности, я выложу его здесь.

Ссылка на комментарий
Поделиться на другие сайты

На самом деле мне кажется тема достаточно интересная, - плавное прямолинейное перемещение объекта из одной точки в другую в 3D пространстве с постоянной скоростью, не зависящей от расстояния (+ по желанию плавное ускорение в начале и плавное замедление в конце).

 

22 часа назад, inaginary сказал:

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

Ускорение, оно же Velocity, не что иное как обычный множитель для координат, что с ним, что без него, - особой разницы нет. В обоих случаях эти 3 множителя (искусственно созданные или имеющиеся уже в игре) необходимо будет видоизменять и подстраивать под поставленную задачу.

 

Как у тебя обстоят дела, есть ли какие-либо продвижения?

Я закончил писать скрипт, проверил, работает.

Ссылка на комментарий
Поделиться на другие сайты

44 минуты назад, Antonshka сказал:

есть ли какие-либо продвижения?

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

Ссылка на комментарий
Поделиться на другие сайты

13 минут назад, Antonshka сказал:

Вот примерный пример эффекта, о котором я говорил

Ну у тебя что то вроде арбрейка без коллизии, как в samp. Получилось весьма интересно у тебя. И спасибо еще раз за упрощенные функции нахождения угла, и про твою информацию о том что fsin,fcos работают с радианами, это мне уже пригодилось

Изменено пользователем inaginary
Ссылка на комментарий
Поделиться на другие сайты

Только что, inaginary сказал:

Что ты имеешь ввиду?

@Antonshka, не новичек и у него всегда шикарно все получалось. Очень хорошо знает LUA.

 

Ссылка на комментарий
Поделиться на другие сайты

1 минуту назад, inaginary сказал:

А я LUA вообще не знаю, так что :-D

Дело не в LUA. Он очень ни хило разбирается во всем в игре, что связано с координатами.  Вот посмотри его видео, которое нам удалось сохранить - ТЫК (Правда видео не маленькое - может терпения не хватит).

 

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.