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

C# навигационный бот или привет математикам...


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

20 часов назад, temtriss сказал:

P.S. Извеняюсь, что-то не обратил внимания на C# в заголовке, пример на C++ хотя может тоже поможет. Сори.

Из-за того, что я в С++ вообще не бумбум, но вроде бы код предоставленных вами не сильно заморочен, то попытаюсь для начала прочитать его правильно.

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

Скрытый текст

int main()
{
  ///Объявляем переменные и присваиваем им нулевое значение?
	float X = 0;
	float Y = 0;
	float nX = 0;
	float nY = 0;
  ///Почему следующая переменная полный круг double? И что значит M_PI? или мне это не нужно?
	double halfcircle = M_PI;
	// Ввод/Вывод нужной информации
	cout << "Angel Calculator by Wi11ka" << endl; //Это я тоже не знаю зачем. Какое то значение =)
	// Проверяем наши переменные
	cout << "Math PI: " << M_PI << endl; // not needed :D
	
	// Получаем нужные значение от пользователя
	// и сразу же выводим значение для проверки правильности.
	cout << "Input X:" << endl; //Это Х по факту?
	cin  >> X;
	cout << "X =" << X << endl; //Сравнивается с чем? Чему должне быть равен Х?
	cout << "Input Y:" << endl; //Y по факту?
	cin >> Y;
	cout << "Y =" << Y << endl; //Чему он должен быть равен?
	cout << "Input needed X:" << endl; //Х конечной точки?
	cin >> nX;
	cout << "Needed X = " << nX << endl; //Чему он должен быть равен?
	cout << "Input needed Y:" << endl; //Y конечной точки?
	cin >> nY;
	cout << "Needed Y = " << nY << endl; //Чему он должен быть равен?

	// Вызываем функцию Калькулирующую наш угол и выводим результат.
	float res = CalcAngle(X, Y, nX, nY);
	cout << "Result: " << res << endl;
	float fResult = CalcRadians(res);
	cout << "Finish Result: " << fResult << endl;
	system("PAUSE");
  //Как я понял, мы вызвали функция калькуляции угла и калькуляции окружности и вывели это дело на экран
}

float CalcAngle(float X, float Y, float nX, float nY)
{

	// Различие между нами и целью по оси X и Y
	double Xdiff; //Почему в этой функции все переменные double? Я же могу их заменить на float?
	double Ydiff;
	// Угол 
	double AngleA;

	// Времянка :D
	double tmp;

	// Разбиваем работу на 4 секции
	// Section 1
	if (nY > Y && nX <= X)
	{
		Ydiff = nY - Y;
		Xdiff = X - nX;
		// Умножаем на 57.29578 для перевода из радиан в градусы.
		AngleA = atan(Xdiff / Ydiff) * 57.29578; //В MSDN вижу, что в atan используется double, не возникнет ли конфликта при вычислениях Ydiff и Xdiff
      											 //ведь X и Y у нас в флоат, да и значение поворота камеры у меня тоже флоат.		
		tmp = 0 - AngleA;

	}
	// Section 2 
	if (nY <= Y && nX < X)
	{
		Ydiff = Y - nY;
		Xdiff = X - nX;

		AngleA = atan(Xdiff / Ydiff) * 57.29578;
		
		tmp = (180 - AngleA)*-1;
	

	}
	// Section 3
	if (nY < Y && nX >= X)
	{
		Ydiff = Y - nY;
		Xdiff = nX - X;

		AngleA = atan(Xdiff / Ydiff) * 57.29578;
		

		tmp = 180 - AngleA;

	}
	// Section 4
	if (nY >= Y && nX > X)
	{
		Ydiff = nY - Y;
		Xdiff = nX - X;

		AngleA = atan(Xdiff / Ydiff)  * 57.29578;
		

		tmp = 0 + AngleA;

	}
	return tmp;
}

float CalcRadians(float angle)
{
	// Возвращаем в радианы
	angle = angle / 57.29578; 

	return angle;
}

 

Я надеюсь, что хоть приблизительно понял код правильно =)

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

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

///Объявляем переменные и присваиваем им нулевое значение?

Да правильно. Инициализировали нулем, что бы не столкнутся с багами(хрен знает что там в памяти)

 

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

///Почему следующая переменная полный круг double? И что значит M_PI? или мне это не нужно?

Это полукруг, он не как не используется M_PI - дефайн из math.h 

M_PI = 3.14 - число Пи

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

//Это я тоже не знаю зачем. Какое то значение =)

Это просто вывод в консоль. 

 

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

cout << "Input X:" << endl; //Это Х по факту?

Это вывод сообщения на экран с прозьбой ввести X

14 минуты назад, pachela сказал:

cin >> X;

А вот это получение переменной от пользователя. Х по факту. Аналогично с Y

15 минут назад, pachela сказал:

cout << "Input needed X:" << endl; //Х конечной точки?

Вывод сообщения в консоль с прозьбой ввести конечную точку.

16 минут назад, pachela сказал:

//Как я понял, мы вызвали функция калькуляции угла и калькуляции окружности и вывели это дело на экран

Да так и есть. 

В это части кода был только вывод на экран и получение параметров. Основная функция ниже

 

17 минут назад, pachela сказал:

//Почему в этой функции все переменные double? Я же могу их заменить на float?

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

 

20 минут назад, pachela сказал:

//В MSDN вижу, что в atan используется double, не возникнет ли конфликта при вычислениях Ydiff и Xdiff

Вот мои слова выше подтвердились, нужен дабл, но в дабл можно скормить флоат значение. :)

 

20 минут назад, pachela сказал:

//ведь X и Y у нас в флоат, да и значение поворота камеры у меня тоже флоат.

Конфликтов не будет :)

 

Вроде на все вопросы ответил :))

 

P.s. Не уверен надо ли что-то тут прятать под сполер, если что прошу понять и простить! :)

 

 

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

15 часов назад, MasterGH сказал:

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

Во валит! ))) Шучу ) Из всего вышеперечисленного понял только про матрицы и шейдеры ) 

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

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

Во валит! ))) Шучу ) Из всего вышеперечисленного понял только про матрицы и шейдеры ) 

Забавно)

Эйлеровы углы  x,y,z, а кватернион x,y,,z,w.

В ассетах Unity есть проект  с готовыми персонажами и скриптами. Если NPC двигается вперед со скоростью X к примеру, просто надо развернуть к цели.

Разворот к цели через эйлеровы углы = дальняя точка - точка npc.

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

 

В Unity движке очевидно проще движения отработать. Можно тут же запустить и проверить.

 

В примере выше уважаемых форумчан расчеты как при взгляде сверху  в ортографической проекции. Я только поддерживаю. Просто я так ковырялся для 2д игр с аркатнгенсами, часа два наверно и опух. А когда в Unity работаешь с её функциями, чувство интуиции включается на все движения и углы. Это не объяснить. Уже функции готовые даны, их можно развернуть в декомпиляторе. Только вот, блин, незадача. В новой Unity тело функции стали прятать в InteralCall.

Скрытый текст

image.png

Так что тут мой вариант не подходит для новой версиии Unity 2017.xx. Это кому интересно нужно будет более раннюю версию скачивать.

 

 

 

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

Повылазили косячки, повылазали родные. Что то да делается не так.

Значение всегда в районе 0.8-0.7. Я так подозреваю, что возможно дело все в мат.методе? Я использую Метод Math.Atan (Double).

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

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

Такс, имеем результат!

Перво наперво хочу сказать, что приходится дабл преобразовывать в флоат. Но так, как я использую при записи в память стороннюю библиотеку, в которой запись происходит как стринг, то проблем не возникает =).

Вся запарка была в сторонах! Ведь у меня есть поворот тела от 0 до 6.28 и нет отрицательного числа. И наличие отрицательного числа, меня путало =).

Так же в примере мы переводили градусы в радианты угол, а не полученное значение.

Имею вот такой вот код, это если вдруг понадобится кому. Возможно где и косякнул, но вроде бы пашет =)

Скрытый текст

Пока что сделано в 2 функции, но функцию нахождения нужного угла, я думаю перенести в отдельный класс(пока что не шарю как).

Первая функция это присвоение переменных и запуск второй функции


private void button7_Click(object sender, EventArgs e) //Жмакаем кнопку и понеслась
        {
            X = ReadMemory(addressX); //Сюда считывайте свое текущее положение Х. я написал от балды для примера =)
            Y = ReadMemory(addressY); //Сюда считываете текущее Y
            nX = 501.9024963f; //Конечная точка Х
            nY = -437.4102173f; //Конечная точка Y
            CalcAngle();            //Запуск функции по калькулированию угла
        }

Вторая функция это расчет угла


private void CalcAngle() //Функция калькуляции угла
        {      
            //Section 1
            if (nY > Y && nX <= X)
            {
                Ydiff = nY - Y;
                Xdiff = X - nX;
                // Умножаем на 57.29578 для перевода из радиан в градусы.
                AngleA = Math.Atan(Xdiff / Ydiff) * 57.29578;	
                tmp = 180 - AngleA;

            }
            // Section 2 
            if (nY <= Y && nX < X)
            {
                Ydiff = Y - nY;
                Xdiff = X - nX;

                AngleA = Math.Atan(Xdiff / Ydiff) * 57.29578;

                tmp = 0 + AngleA;
            }
            // Section 3
            if (nY < Y && nX >= X)
            {
                Ydiff = Y - nY;
                Xdiff = nX - X;

                AngleA = Math.Atan(Xdiff / Ydiff) * 57.29578;


                tmp = 360 - AngleA;
            }
            // Section 4
            if (nY >= Y && nX > X)
            {
                Ydiff = nY - Y;
                Xdiff = nX - X;

                AngleA = Math.Atan(Xdiff / Ydiff) * 57.29578;

                tmp = 180 + AngleA;
            }

            tmp = tmp / 57.29578;            
            label3.Text = tmp.ToString();
  			//Если нужно будет преобразовать double в float, то делаем так somevalue = (float) tmp;
        }

Продолжаем оптимизацию. Хочу теперь перенести функцию калькуляции угла перенести в отдельный класс.

 

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

2 минуты назад, pachela сказал:

Ведь у меня есть поворот тела от 0 до 6.28 и нет отрицательного

Только что об этом подумал, у меня было от -3.14 до 3.14 двойное в вашем примере аналогично но от нуля до 6.28

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

Можно сделать таким алгоритмом:

 

Необходимые данные:

- Координаты X,Y точки назначения (метка на карте, к примеру)

- Координаты X,Y точки отправления (игрок)

- Velocity X,Y точки отправления (игрок)

- Матрица вращения точки отправления (игрок), или же что лучше - готовый адрес параметра Yaw точки отправления (игрок)

- Матрица вращения камеры, или же что лучше - готовый адрес параметра Yaw камеры

- Адрес параметра, сигнализирующего о прикасании/столкновении точки отправления (игрок) к какому-либо объекту

 

Основной процесс расчёта:

1 - Расчет дистанции до точки назначения (метка на карте, к примеру). Значение дистанции необходима лишь для своевременного автоматического отключения/прерывания опции

2 - Расчет угла между точкой отправления (игрок) и точкой назначения (метка на карте, к примеру)

3 - Изменение Velocity X,Y точки отправления (игрок) по средствам Cos,Sin угла между точкой отправления (игрок) и точкой назначения (метка на карте, к примеру)

4 - Изменение Yaw точки отправления (игрок) по средствам угла между точкой отправления (игрок) и точкой назначения (метка на карте, к примеру)

5 - Изменение Yaw камеры по средствам угла между точкой отправления (игрок) и точкой назначения (метка на карте, к примеру)

 

* если в игре отсутствует готовый параметр Yaw точки отправления (игрок) или камеры, то необходимо будет делать извлечение параметра Yaw из матрицы, затем изменение извлеченного параметра Yaw, затем обратная конвертация параметра Yaw в матрицу

 

Обход препятствий:

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

 

Протестировал эту схему вчера в игре "theHunter: Call of the Wild", работает на 4 из 5. Пробовал устраивать игроку разные препятствия в виде камней, домов и прочего, - со всеми игрок справился успешно.

 

 

 

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

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

со всеми игрок справился успешно.

@Antonshka, записал бы видео - было бы супер. Ну а код, по желанию конечно.

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

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

Можно сделать таким алгоритмом:

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

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

А в дальних планах еще и до передвижения добавить боевку. Но вот с эмуляцией нажатий в Шарпе, я еще не знаком. Так что все по мере поступления.

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

46 минут назад, pachela сказал:

Но вот с эмуляцией нажатий в Шарпе, я еще не знаком. Так что все по мере поступления.

https://stackoverflow.com/questions/30621624/simulating-keyboard-with-sendinput-c-sharp

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

Расчёт дистанции

Скрытый текст

fld dword ptr [Map_Coord_X] //Map_Coord_X
fsub dword ptr [rsi] //Player_Coord_X
fmul st(0) 
fld dword ptr [Map_Coord_Y] //Map_Coord_Y
fsub dword ptr [rsi+8] //Player_Coord_Y
fmul st(0) 
faddp st(1),st(0)
fsqrt
fstp dword [AutoWalk_Distance]

 

Расчёт угла Player/Map

Скрытый текст

fld dword ptr [Map_Coord_X]//Map_Coord_X
fsub dword [rsi]//Player_Coord_X
fstp dword [AutoWalk_BA_X_Diff]
fld dword ptr [Map_Coord_Y]//Map_Coord_Y
fsub dword [rsi+8]//Player_Coord_Y
fstp dword [AutoWalk_BA_Y_Diff]
fld dword ptr [AutoWalk_BA_Y_Diff]
fld dword ptr [AutoWalk_BA_X_Diff]
fpatan
fstp dword ptr [AutoWalk_BA_Yaw]

 

Расчёт Player_Velocity X,Y

Скрытый текст

cmp [Auto_Walk_Checker],#0 //Проверка активности опции
je AutoWalk_not_Act
cmp [AutoWalk_Distance],(float)2 //Проверка минимальной дистанции
jle AutoWalk_not_Act


cmp [Detect_Objects_Checker],#1 // Сигнализатор прикасания к объектам (1 - прикасание имеется, 0 - нет)
jne @f
fld dword ptr [AutoWalk_Yaw_Compensator] // Множитель для угла Yaw
fadd dword ptr [AutoWalk_Yaw_Compensator_Multiply_1] // Множитель_1 множителя для угла Yaw
fstp dword ptr [AutoWalk_Yaw_Compensator]
@@:

cmp [Detect_Objects_Checker],#1
je AutoWalk_Step_1
cmp [AutoWalk_Yaw_Compensator],(float)0
je AutoWalk_Step_1
jle AutoWalk_Step_1_Set_Zero
fld dword ptr [AutoWalk_Yaw_Compensator]
fsub dword ptr [AutoWalk_Yaw_Compensator_Multiply_2] // Множитель_2 множителя для угла Yaw
fstp dword ptr [AutoWalk_Yaw_Compensator]
jmp AutoWalk_Step_1
AutoWalk_Step_1_Set_Zero://AutoWalk_Step_1_Set_Zero
mov [AutoWalk_Yaw_Compensator],(float)0


AutoWalk_Step_1://AutoWalk_Step_1
fld dword ptr [AutoWalk_BA_Yaw] // Угол Yaw между точкой назначения и точкой отправления
fadd dword ptr [AutoWalk_Yaw_Compensator]
fcos
fstp dword ptr [AutoWalk_Yaw_Cos] //Косигус угла Yaw
fld dword ptr [AutoWalk_BA_Yaw]
fadd dword ptr [AutoWalk_Yaw_Compensator]
fsin
fstp dword ptr [AutoWalk_Yaw_Sin] //Синус угла Yaw


fld dword ptr [AutoWalk_Speed] // Скорость ходьбы
fmul dword ptr [AutoWalk_Yaw_Cos]
fstp dword ptr [r9+rcx+40]//Plyer Velocity X
fld dword ptr [AutoWalk_Speed]
fmul dword ptr [AutoWalk_Yaw_Sin]
fstp dword ptr [r9+rcx+48]//Plyer Velocity Y


AutoWalk_not_Act://AutoWalk_not_Act

 

 

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

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

cmp [Detect_Objects_Checker],#1 // Сигнализатор прикасания к объектам (1 - прикасание имеется, 0 - нет)

Интересное значение, через него и коллизию отключить не долго.

 

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

  • 4 недели спустя...
В 16.02.2018 в 14:38, Xipho сказал:

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

public static void Send(short Keycode)
{
    INPUT[] InputData = new INPUT[1];

    InputData[0].type = 1;
    InputData[0].ki.wScan = Keycode;
    InputData[0].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
    InputData[0].ki.time = 0;
    InputData[0].ki.dwExtraInfo = IntPtr.Zero;

    SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
}

по ссылке, вижу ниже комментарий, который гласит, что нужно  сначала слать нажатие клавиши, потом отпускание, с небольшой паузой, как это реализуется или просто сначала KeyDown а затем KeyUp? Как я понимаю, это отправка в активное окно? Или в фоновое тоже можно?

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

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

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

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