Пятница, 29 Марта 2024, 15:23

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 2
  • 1
  • 2
  • »
Форум игроделов » Программирование » Общие обсуждения программистов » Вектор движения
Вектор движения
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/ вот отличная статья

супер ok
wcptДата: Вторник, 24 Июня 2014, 14:52 | Сообщение # 20
постоянный участник
Сейчас нет на сайте
объясни подробней, ведь я же не знаю, что такое центр (ну, что ты под этим подразумеваешь) smile

Сообщение отредактировал wcpt - Вторник, 24 Июня 2014, 14:53
Форум игроделов » Программирование » Общие обсуждения программистов » Вектор движения
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг