Вектор движения
| |
Saitei | Дата: Понедельник, 23 Июня 2014, 15:08 | Сообщение # 1 |
старожил
Сейчас нет на сайте
| Как построить вектор с опр. углом? Совсем вылетело из головы, а надо. Задача: из точки A(x1,y1) попасть в точку В(x2,y2), но при этом если космический корабль не повернут в сторону точки B он должен медленно ускоряться и при этом разворачиваться (с ускорением проблем нет, проблема в построении вектора).
По сути имею: координаты корабля; константу, которая прибавляется при ускорении; скорость корабля;"потолок" скорости; угол поворота корабля; точку, в которую нужно попастьДобавлено (23.06.2014, 15:08) --------------------------------------------- наверное стоит ещё ввести скорость поворота
Сообщение отредактировал Saitei - Понедельник, 23 Июня 2014, 15:05 |
|
| |
falcoware | Дата: Понедельник, 23 Июня 2014, 15:09 | Сообщение # 2 |
старожил
Сейчас нет на сайте
| Saitei, я думаю алгоритм такой. Сначало создать матрицу, повернуть ее на угол. И умножать на вектор движения!: Код void ident_matrix(matrix *mat) { mat->m[0][0] = 1.0f; mat->m[0][1] = 0.0f; mat->m[0][2] = 0.0f; mat->m[0][3] = 0.0f;
mat->m[1][0] = 0.0f; mat->m[1][1] = 1.0f; mat->m[1][2] = 0.0f; mat->m[1][3] = 0.0f;
mat->m[2][0] = 0.0f; mat->m[2][1] = 0.0f; mat->m[2][2] = 1.0f; mat->m[2][3] = 0.0f;
mat->m[3][0] = 0.0f; mat->m[3][1] = 0.0f; mat->m[3][2] = 0.0f; mat->m[3][3] = 1.0f; }
void rotate_matrix(matrix *m, double xtheta, double ytheta, double ztheta) { float xscale, yscale, zscale; float sinx, cosx; float siny, cosy; float sinz, cosz;
xscale = m->m[0][0]; yscale = m->m[1][1]; zscale = m->m[2][2]; sinx = (float) sin(xtheta); cosx = (float) cos(xtheta); siny = (float) sin(ytheta); cosy = (float) cos(ytheta); sinz = (float) sin(ztheta); cosz = (float) cos(ztheta);
m->m[0][0] = (float) ((cosz * cosy) * xscale); m->m[0][1] = (float) ((cosz * -siny * -sinx + sinz * cosx) * yscale); m->m[0][2] = (float) ((cosz * -siny * cosx + sinz * sinx) * zscale);
m->m[1][0] = (float) (-sinz * cosy * xscale); m->m[1][1] = (float) ((-sinz * -siny * -sinx + cosz * cosx) * yscale); m->m[1][2] = (float) ((-sinz * -siny * cosx + cosz * sinx) * zscale);
m->m[2][0] = (float) (siny * xscale); m->m[2][1] = (float) (cosy * -sinx * yscale); m->m[2][2] = (float) (cosy * cosx * zscale); }
void transform_point(point3d *ptout, point3d *ptin, matrix *mat) { double x, y, z;
x = (ptin->x * mat->m[0][0]) + (ptin->y * mat->m[0][1]) + (ptin->z * mat->m[0][2]) + mat->m[0][3];
y = (ptin->x * mat->m[1][0]) + (ptin->y * mat->m[1][1]) + (ptin->z * mat->m[1][2]) + mat->m[1][3];
z = (ptin->x * mat->m[2][0]) + (ptin->y * mat->m[2][1]) + (ptin->z * mat->m[2][2]) + mat->m[2][3];
ptout->x = (float) x; ptout->y = (float) y; ptout->z = (float) z; }
|
|
| |
OpenGOO | Дата: Понедельник, 23 Июня 2014, 15:45 | Сообщение # 3 |
почти ветеран
Сейчас нет на сайте
| x = cos угла * длину вектора y = sin угла * длину вектора
Мои проекты: - Свободный и открытый клон World Of Goo - TrueEngine2D (2D игровой фреймворк основанный на FreeBASIC)
[GameMaker: Studio v1.4.9999]
|
|
| |
Edison6 | Дата: Понедельник, 23 Июня 2014, 15:52 | Сообщение # 4 |
TRUE Programmer
Сейчас нет на сайте
| Цитата Saitei ( ) По сути имею: координаты корабля; константу, которая прибавляется при ускорении; скорость корабля;"потолок" скорости; угол поворота корабля; точку, в которую нужно попасть
POINT1(x1,y1); POINT2(x2,y2);
Vector2 dir = POINT1 - POINT2;
dir.nor(); // нормализация dir.mul(speedShip); // умножаем на скорость с которой хотим чтобы корабль двигался
ship.position += dir; // Двигаем корабль
Берил сбрей усы
Сообщение отредактировал Edison6 - Понедельник, 23 Июня 2014, 15:52 |
|
| |
Saitei | Дата: Понедельник, 23 Июня 2014, 16:01 | Сообщение # 5 |
старожил
Сейчас нет на сайте
| Цитата Edison6 ( ) POINT1(x1,y1); POINT2(x2,y2);
Vector2 dir = POINT1 - POINT2;
dir.nor(); // нормализация dir.mul(speedShip); // умножаем на скорость с которой хотим чтобы корабль двигался
ship.position += dir; // Двигаем корабль Если правильно понял, то здесь корабль сразу же полетит от А в B. А мне надо учитывать угол поворота корабля - он же должен развернуться :) Цитата OpenGOO ( ) x = cos угла * длину вектора y = sin угла * длину вектора Это вроде вращение точки от начала координат? И длину какого вектора, собственно, брать? :( falcoware, десятый раз код перечитываю... Пока что сложно понять... Код синтаксически ясен, а вот суть уловить сложно... Но в любом случае спасибо. Ещё бы объяснение какое-нибудь - было бы шикарно =)
|
|
| |
falcoware | Дата: Понедельник, 23 Июня 2014, 16:06 | Сообщение # 6 |
старожил
Сейчас нет на сайте
| Saitei, это в 3Д пространстве.
Тебе подойдет код ОпенГу.
1. Находишь угол между точками. 2. Делишь угол на н-частей. 3. Поворачиваешь вектор с помощью:
x = cos угла * длину вектора y = sin угла * длину вектора
|
|
| |
Saitei | Дата: Понедельник, 23 Июня 2014, 16:11 | Сообщение # 7 |
старожил
Сейчас нет на сайте
| falcoware, в моем случае длина вектора - это текущая скорость корабля?
P.S.: Спасибо всем огромное, в голове родилась возможная реализация идеи. Буду пробовать
|
|
| |
Fill_Freeman | Дата: Понедельник, 23 Июня 2014, 16:14 | Сообщение # 8 |
почетный гость
Сейчас нет на сайте
| Лично я делал примерно так:
у корабля есть cur_dir - текущее направление и dest_dir - направление к заданной точке
при клике определяешь dest_dir (угол от оси абсцисс)
потом каждый степ cur_dir += rotation_speed (пока не станет равен dest_dir) x += speed * cos(cur_dir) y += speed * sin(cur_dir)
понятно что еще надо определить в какую сторону вращаться, чтобы корабль вращался в наименьшую сторону. Но думаю ты и сам догодаешься
UPD: Я сейчас общую логику написал. В GameMaker может можно проще, просто я сейчас не вспомню всех свойств объекта.
Сообщение отредактировал Fill_Freeman - Понедельник, 23 Июня 2014, 16:18 |
|
| |
Saitei | Дата: Понедельник, 23 Июня 2014, 16:20 | Сообщение # 9 |
старожил
Сейчас нет на сайте
| Цитата Fill_Freeman ( ) при клике определяешь dest_dir (угол от оси абсцисс) Т.е. надо построить вектор по двум точкам (где находится корабль и место клика), а потом найти угол вектора относительно Ox? Т.е. надо найти угол между полученным вектором и вектором (1,0)?
|
|
| |
Snuux | Дата: Понедельник, 23 Июня 2014, 16:57 | Сообщение # 10 |
постоянный участник
Сейчас нет на сайте
| Тоже внесу свой вклад в обсуждение (хотя уже все и так понятно...): Код //У нас есть: player.x, player.y, player.speed, player.angle //А так же точка в которую надо прийти: target.x, target.y
void update(float dt) { ///.../// //находим угол между игроком и целью player.angle = math.atan2((target.y - player.y), (target.x - player.x));
//обновляем координаты игрока player.x += player.speed * math.cos(player.angle) * dt; player.y += player.speed * math.sin(player.angle) * dt; ///.../// }
Если нужно, чтоб корабль постепенно поворачивал, то нужно угол немного по другому находить: Код bool checkN(float a, float b, float x){ //a, b - числа, x - на сколько числам можно различаться return (a>b&&a-x<=b)||(b>a&&b-x<=a); }
void update(float dt) { ///.../// //находим угол между игроком и целью (он пока не равен player.angle как в первом случае!) float an = math.atan2((target.y - player.y), (target.x - player.x));
//если модуль полученного угла и угол игрока различаются больше чем на 5 градусов, //то продолжаем поворачиваться if (!checkN(math.abs(an),math.abs(player.angle),5)) { if (player.angle < 0) //если угол отрицательный, то поворачиваем в одну сторону player.angle -= 5; else //иначе в другую player.angle += 5; }
player.x += player.speed * math.cos(player.angle) * dt; player.y += player.speed * math.sin(player.angle) * dt; ///.../// //какой-же хреновый код... печаль, но мне лень думать }
Без тестов сложно все это представить, так что за правильность не ручаюсь. Вообще это просто тригонометрия (школьный курс). Если что, хорошие видео, на примере задания С1 для егэ, с объяснением тригонометрического круга: тыр (не смотрите, что 2012 год. Там ооочень хорошо все объяснено!)
Сообщение отредактировал Snuux - Понедельник, 23 Июня 2014, 17:10 |
|
| |
Fill_Freeman | Дата: Понедельник, 23 Июня 2014, 17:01 | Сообщение # 11 |
почетный гость
Сейчас нет на сайте
| Цитата Saitei ( ) Т.е. надо построить вектор по двум точкам (где находится корабль и место клика), а потом найти угол вектора относительно Ox? Т.е. надо найти угол между полученным вектором и вектором (1,0)?
Да именно так. По-моему в GameMaker это можно сделать одной функцией (что -то с dir) посмотри помощь или погугли, я точно не помню. На крайний случай можно воспользоваться старой доброй математикой.
|
|
| |
Saitei | Дата: Понедельник, 23 Июня 2014, 17:14 | Сообщение # 12 |
старожил
Сейчас нет на сайте
| Цитата Fill_Freeman ( ) Да именно так. По-моему в GameMaker это можно сделать одной функцией (что -то с dir) посмотри помощь или погугли, я точно не помню. На крайний случай можно воспользоваться старой доброй математикой. Я принципиально не использую GM. Предпочитаю С++ и другие языки программирования. В любом случае спасибо!
Snuux, ох! Благодарствую за такой развёрнутый ответ! =)
|
|
| |
Snuux | Дата: Понедельник, 23 Июня 2014, 18:00 | Сообщение # 13 |
постоянный участник
Сейчас нет на сайте
| Цитата Saitei ( ) Snuux, ох! Благодарствую за такой развёрнутый ответ! =) Второй блок кода не оч. Можно сделать без костылей. Но в общем смысл в том, чтоб изменять угол игрока, пока он не станет таким же как угол между игроком и целью. Собственно о чем и писал Fill_Freeman)
Сообщение отредактировал Snuux - Понедельник, 23 Июня 2014, 18:01 |
|
| |
wcpt | Дата: Понедельник, 23 Июня 2014, 19:48 | Сообщение # 14 |
постоянный участник
Сейчас нет на сайте
| немного непонятно, что тебе непонятно - не знаешь, как определить угол, на который надо повернуться? Пусть у тебя есть координаты точки (х0,у0) и координаты корабля (х,у). Нужно указать направление (ну, вектор) от корабля до искомой точки. Указать можно, задав координаты вектора. Координаты вектора суть есть разница между между соответствующими его координатами начала и конца, т.е. нужным вектором будет (x0-x,y0-y). Далее, есть вектор, задающий текущее направление корабля, и вектор направления. Как найти между ними угол? Есть такая вещь, скалярное произведение векторов называется. Через него находишь угол. Как вектор направления развернуть? Также есть замечательная вещь - матрица поворота в двухмерном пространстве. Перемножаешь её на координаты вектора, трансформируешь его тем самым образом, вот и всё. Осталось только добиться плавности. Просто вращай вектор понемногу за шаг, да и хватит. Может, есть способ проще, тут уж не подскажу. И нормализовать вектор направления не забудь, чтоб бедный кораблик не растянулся...
Сообщение отредактировал wcpt - Понедельник, 23 Июня 2014, 19:57 |
|
| |
Saitei | Дата: Вторник, 24 Июня 2014, 13:52 | Сообщение # 15 |
старожил
Сейчас нет на сайте
| Захотелось, чтобы объект летел четко по вектору(объект - пуля). Не выходит
Код void Update(Time& dt) { x += speed*cos(angle)*dt.asMilliseconds(); y += speed*sin(angle)*dt.asMilliseconds(); sprite.setPosition(x,y); if(x>500 || y>500 || x < 0 || y < 0) { active = 0; } } Код angle = (180/PI)*atan2((mouse.getPosition(*window).y - y),(mouse.getPosition(*window).x - x));
|
|
| |
wcpt | Дата: Вторник, 24 Июня 2014, 14:02 | Сообщение # 16 |
постоянный участник
Сейчас нет на сайте
| может, глупость скажу, но ты уверен, что угол необходимо в градусную меру переводить? Просто вероятнее всего, что cos и sin настроены на работу с радианами. Да и можно вектор скорости пули один раз повернуть, чтобы потом не считать sin и cos каждый шаг (это так, вдруг не знаешь)
Сообщение отредактировал wcpt - Вторник, 24 Июня 2014, 14:05 |
|
| |
Saitei | Дата: Вторник, 24 Июня 2014, 14:14 | Сообщение # 17 |
старожил
Сейчас нет на сайте
| wcpt, ЧЁРТ! Вы гений))))) Целый день думал что не так.... А я забыл перевести в радианы))) Спасибо ОГРОМНОЕ!
|
|
| |
Snuux | Дата: Вторник, 24 Июня 2014, 14:24 | Сообщение # 18 |
постоянный участник
Сейчас нет на сайте
| Цитата wcpt ( ) Также есть замечательная вещь - матрица поворота в двухмерном пространстве. Перемножаешь её на координаты вектора, трансформируешь его тем самым образом, вот и всё. wcpt, можешь скинуть ссылку, пожалуйста, где более подробно это расписанно (желательно с точки зрения математики).. Или объясни)
Добавлено (24.06.2014, 14:24) --------------------------------------------- http://habrahabr.ru/post/131931/ вот отличная статья. Мда... Нашел позже, чем запостил на форум вопрос. Сорри.
Сообщение отредактировал Snuux - Вторник, 24 Июня 2014, 14:25 |
|
| |
Saitei | Дата: Вторник, 24 Июня 2014, 14:50 | Сообщение # 19 |
старожил
Сейчас нет на сайте
| А что если корабль уже немного повернут, а я хочу чтобы снаряды летели не из центра? Надо как-то найти другую точку, но при этом учитывая угол поворота корабля Цитата Snuux ( ) http://habrahabr.ru/post/131931/ вот отличная статья супер
|
|
| |
wcpt | Дата: Вторник, 24 Июня 2014, 14:52 | Сообщение # 20 |
постоянный участник
Сейчас нет на сайте
| объясни подробней, ведь я же не знаю, что такое центр (ну, что ты под этим подразумеваешь)
Сообщение отредактировал wcpt - Вторник, 24 Июня 2014, 14:53 |
|
| |
|