Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Движеня шариков


Автор: Elfet 12.5.2004, 16:17
Есть два шарика. Известен радиус и координаты обоих. Нужно чтоб один шарик не мог попасть
в другой.
Помогите пожалуйст!

Автор: maxim1000 12.5.2004, 16:37
учтановить им начальные скорости в противоположных направлениях smile.gif
а вообще не помешало бы нормально поставить вопрос...

Автор: Dr.Drunk 12.5.2004, 17:16
Elfet, Вы, условия нормально поставьте, где они находяться, как должны двигаться? bored.gif

Автор: Elfet 12.5.2004, 17:38
Ну я вообщем пытался вот так сделать на с :
sqrt(pow(x2-x1, 2)+pow(y2-y1, 2))-r2-r1<0

Но так один шарик "прилепает" к другому[s].


Условия есть координаты x1 x2 y1 y2 и радиусы r1 r2
Нуна двигать их но чтоб они не попадали внутрь друг друга и если всё же попадут внутрь друг друга
чтоб могли вылезти smile.gif

Автор: Lan 12.5.2004, 18:05
Забавная постановка задачи.

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

И, спрашивается, в чём тогда проблема? smile.gif

Автор: setq 12.5.2004, 19:53
зафиксировать столкновение наверно

?

если да - то формула вроде правильная.

Автор: Elfet 12.5.2004, 20:50
ага тока они прилепают друг к другу smile.gif

Автор: Elfet 12.5.2004, 21:26
cool.gif ! сам додумался smile.gif я просто теперь отбрасываю шарик на маленькое растояние обратно smile.gif

Теперь задача услажнилась hmmm.gif теперь движутся и шарики и примоугольники (какие извесно) hmmm.gif

sad.gif ума не приложу, как это сделать sad.gif

Автор: dargaard 12.5.2004, 22:56
Если данны x1,y1 x2,y2, x3,y3 x4,y4

---------------------------> X
|
| P1 _____ P2
| | |
| | |
| | |
| P4|_____|P3
v
Y


и Xc,Yc то

чтоб шарик не попал в прямоугольник:
if (xc+R>x1 && xc-R<x3 && yc+R>y1 && yc-R<y3) - отталкиваем

Для того чтоб не врезались 2 прямоугольника
для каждой вершины одного проверяем так же как для круга но с R=0

Кажись такsmile.gif

Автор: Crot 13.5.2004, 05:47
Цитата(Elfet @ 12.5.2004, 22:17)
Есть два шарика. Известен радиус и координаты обоих. Нужно чтоб один шарик не мог попасть
в другой.
Помогите пожалуйст!

А по какому закону двигаются шарики?

Автор: Elfet 13.5.2004, 15:45
Crot , произвольно smile.gif


Цитата
---------------------------> X
|
| P1 _____ P2
| | |
| | |
| | |
| P4|_____|P3
v
Y


ето что? smile.gif


Цитата
Для того чтоб не врезались 2 прямоугольника
для каждой вершины одного проверяем так же как для круга но с R=0


и ето не совсем понял smile.gif

Автор: dargaard 13.5.2004, 18:37
Elfet
1)
Это была попытка нарисовать x,y ось и прямоугольник (p1,p2,p3,p4 - учитывалось что
в такой последовательности даны координаты)
---------------------
2)
Для того чтоб не врезались 2 прямоугольника
для каждой вершины одного проверяем так же как для круга но с R=0
Имелось в виду по формуле
if (xc+R>x1 && xc-R<x3 && yc+R>y1 && yc-R<y3)
при этом берем R=0, x1,y1 и x3,y3 - координаты первого прям. а xc,yc - координаты каждой вершины второго

например:
если даны координаты 2х прямоугольников
(xA1, yA1 xA2,yA2, xA3, yA3, xA4, yA4) и
(xB1, yB1 xB2, yB2, xB3, yB3, xB4, yB4)

то

if (xA1 > xB1 && xA1 < xB3 && yA1 > yB1 && yA1 < yB3) - отталкиваем
if (xA2 > xB1 && xA2 < xB3 && yA2 > yB3 && yA2 < yB3) - отталкиваем
тоже самое для (xA3,yA3) и (xA4, yB4)

Автор: Crot 14.5.2004, 02:47
Цитата(Elfet @ 13.5.2004, 21:45)
Crot , произвольно smile.gif

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

Автор: beif 16.5.2004, 16:10
А если прямоугольники "мысленно" вписать в круги и следить чтобы они не сталкивались... т.е. свести задачу к ранее решенной.. ? smile.gif

Автор: dargaard 16.5.2004, 21:06
beif
Не очень выидет по моему - для прямоугольника со сторонами 5 и 1 к примеру
user posted image
отталкивание будет поисходить от попадания в зеленые участки

Автор: Elfet 5.6.2004, 21:26
А у меня примоугольник 4 и 5 , а шары 30-50 так что незаметно smile.gif

Автор: student0511 22.5.2008, 21:25
      А как лучше всего написать обработку движения шариков, если их не 2, а, предположим, 10 или 16, как сделать чтобы они не пересекались? Я написал функцию, которая не даёт пересечься 2 шарикам при их независимом движении: скажем, один летит под углом 30 гр, а другой 210, если они должны пересечься, то они попросту друг друга обходят.
      Вот функция, которая преобразует координаты, если шар 1 должен пересечься с шаром 2:
Код

void BALL::cross(HDC hdc, BALL* ball, bool& f)
{
 double S = 0.0, alpha = 0.0, beta = 0.0;
 int dX = 0, dY = 0;
 POINT A;
 char buff[256];

 if((ball->Xc) >= Xc && (ball->Yc) < Yc)
 {
  //I)case
  dX = (ball->Xc) - Xc;
  dY = Yc - (ball->Yc);
  S = pow((dX*dX + dY*dY),0.5);

  alpha = atan((double)(dY)/(double)(dX));
  beta = (double)(PI) + atan((double)(dY)/(double)(dX));
 }
 
 if((ball->Xc) < Xc && (ball->Yc) <= Yc)
 {
  //II)case
  dX = Xc - (ball->Xc);
  dY = Yc - (ball->Yc);
  S = pow((dX*dX + dY*dY),0.5);

  alpha = (double)(PI) - atan((double)(dY)/(double)(dX));
  beta = (double)(2*PI) - atan((double)(dY)/(double)(dX));
 }

 if((ball->Xc) <= Xc && (ball->Yc) > Yc)
 {
  //III)case
  dX = Xc - (ball->Xc);
  dY = (ball->Yc) - Yc;
  S = pow((dX*dX + dY*dY),0.5);

  alpha = (double)(PI) + atan((double)(dY)/(double)(dX));
  beta = atan((double)(dY)/(double)(dX));
 }

 if((ball->Xc) > Xc && (ball->Yc) >= Yc)
 {
  //IV)case
  dX = (ball->Xc) - Xc;
  dY = (ball->Yc) - Yc;
  S = pow((dX*dX + dY*dY),0.5);
  
  alpha = (double)(2*PI) - atan((double)(dY)/(double)(dX));
  beta = (double)(PI) - atan((double)(dY)/(double)(dX));
 }

 if(S < (double)((Radius) + (ball->Radius)))
 {  
    TextOut(hdc, 3*cxClient/4, cyClient/2, "Collision", sizeof("Collision") - 1); 
             
    A.x = Xc + (int)((double)(Radius)*cos(alpha));
    A.y = Yc - (int)((double)(Radius)*sin(alpha));

    (ball->Xc) = A.x - (int)((double)(ball->Radius)*cos(beta));
    (ball->Yc) = A.y + (int)((double)(ball->Radius)*sin(beta));
    if(((ball->Xc) + Radius) >= cxClient)
        (ball->Xc) = cxClient - (ball->Radius);
    if(((ball->Xc) - Radius) <= 0)
        (ball->Xc) = (ball->Radius);
    if(((ball->Yc) - Radius) <= 0)
        (ball->Yc) = (ball->Radius);
    if(((ball->Yc) + Radius) >= cyClient)
        (ball->Yc) = cyClient - (ball->Radius);
   
    if(alpha >= double(2*PI))
       alpha -= double(2*PI);

    if(beta >= double(2*PI))
       beta -= double(2*PI);
    
    f = true;
 }
 else
     f = false;
}

       Переменная S отвечает за расстояние м/у центрами, угол alpha - это угол, через который я определяю точку пересечения прямой с 1 шаром, соединяющую центр 1-ого и 2-ого, соответственно beta - это то же самое, но по отношению ко 2-ому шарику. Точка A -  точка пересечения вышеупомянутой прямой с  1-ым шариком, соответственно, в ней и будет пересекаться шарики. Далее, используя точку A, я сдвигаю центр второго шара. Переменные cxClient - ширина экрана, cyClient - высота. Вообщем, будет 4 случая: шар 2 находится либо в 1-ой четверти, либо во 2-ой, либо в 3-ей, либо в 4-ой отностительно 1-ого шара, либо на одном и том же уровне с ним по y-координате или по x-координате. 
        Итак, а как терь лучше, используя данную функцию написать случай с более, чем 2-мя шарами, нужно, чтобы их было > 10 хотя бы. 
        Пока я обрабатываю сообщение WM_PAINT по нажатию клавиатуры вот так:
Код

case WM_PAINT:
     hdc = BeginPaint(hwnd, &ps);
     if(count > 0)
     {
      for(i = 0; i<count; i++)
      {
      B[i]->calc();
       for(k = 0; k<count; k++)
           for(j = 0; j<count; j++)
               if(j != k)
                  B[k]->cross(hdc, B[j], f);
                 //Prn = k;
       B[i]->draw(hdc, i);
      }
     }
     EndPaint(hwnd, &ps);
 return 0;

         Где void BALL::calc() вычисляет координаты шаров, void BALL::draw(HDC, const int) рисует i шар, count - это текущее количество шаров (count < 16), которое увеличивается при нажатии пробела и уменьшается при использовании VK_DELETE:
Код

case WM_KEYDOWN:
     InvalidateRect(hwnd, NULL, true);
     switch(wParam)
     {
      case VK_SPACE:
          if(count < NUM)
              count++;
      return 0;

      case VK_DELETE:
          if(count > 1)
              count--;
      return 0;

      default:
          break;
     }
     return 0;

         Вообщем, если таким образом обрабатывать WM_PAINT, то при большом скоплении шаров некоторые заступают друга на друга, что не есть гуд  smile 
         Может проблема в cross'е?
         Надеюсь на вашу помощь, а то курсач на след. недели сдавать, а ещё надо описать столкновение... Заведомо благодарен, сильно не пинайте за корявый код smile 

Автор: student0511 23.5.2008, 04:39
Неужели никто не писал что-то подобное? ведь должны же быть подобные работы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)