Конференция "Игры" » Движение точки
 
  • Б (06.01.09 21:58) [0]
    Точка движется по след. формулe:

      x:= round(x + cos(Angle) * Speed);
      y:= round(y + sin(Angle)  * Speed);

      где Angle измеряется в градусах.
     
    Но почему то вся эта система не работает.
    При Angle = 0, точка двигается как надо, т.е. по горизонту в правую сторону.
    При других значениях Angle точка летит чёрт знает куда.
  • antonn © (06.01.09 22:06) [1]
    переводи в радианы
  • Б (06.01.09 22:11) [2]
    Хм... заработало. Но по часовой стрелке, а нужно против.
  • Б (06.01.09 22:20) [3]
    Всё разобрался. Передел функцию вычисления угла, чтобы считала угол по часовой стрелке.

    Но возник друго вопрос: почему то точка немного промахивается, когда летит. Это из-за округления? Если да, то как это предотвратить. Координаты точки должны быть целыми.
  • Denis__ © (06.01.09 22:29) [4]
    в каком смысле "промахивается"?
  • Б (06.01.09 22:37) [5]
    > в каком смысле "промахивается"?

    Объясняю:
    Имеется на форме точка с координатами X,Y;
    При клике на форму в переменную GotoPoint записываются координаты клика.
    Затем находится угол между этими точками.
    Далее во включенном таймере, где вставлена эта формула, вычисляется траектория движения точки.
    По смыслу точка должна двигаться в место последнего клика, но, если расстояние между этими точками велико, то точка немного промахивается и пролетает мимо.
    Кажется это из-за постоянного округления - накапливается погрешность.
    Как с ней бороться?
  • KilkennyCat © (07.01.09 00:10) [6]
    округляй только для вывода.
  • Б (07.01.09 15:13) [7]
    > округляй только для вывода.

    Не получится. Точка (Она, для теста, представлена как панель) всегда должна округляться, для вывода.
  • @!!ex © (07.01.09 16:14) [8]
    > [7] Б   (07.01.09 15:13)

    Для расчета храни реальные. для вывода - округлай. и будет шастье.
  • Б (07.01.09 16:46) [9]
    > Для расчета храни реальные. для вывода - округлай. и будет шастье.

    Сделал. Немного всё равно промахивается, но и так сойдёт.
    Иногда почему-то точка не долетает до нужной, порой на значительные расстояния.
    В таймере стоит проверка: если перемещаемая точка равна той, к которой стремиться, то она останавливается.
  • @!!ex © (07.01.09 17:08) [10]
    > [9] Б   (07.01.09 16:46)

    1) Для чисел с плавающей точкой нет понятия "равно", есть понятие "равно с некоторым допустимым Epsilon"
    2) Где-то в коде косяк, недолжно ничего промахиваться.
  • Б (07.01.09 17:48) [11]
    Вот код:


    Var Angle: double;
        X, Y: double;
        GotoPoint: TPoint;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      GotoPoint:= Point(Panel1.Left, Panel1.Top);
      X:= Panel1.Left;
      Y:= Panel1.Top;
    end;

    procedure TForm1.FormMouseDown(Sender:TObject;Button:TMouseButton;Shift: TShiftState; X, Y: Integer);
    begin
      GotoPoint:= Point(x,y);
      Angle:= GetAngle(Point(Panel1.Left, Panel1.Top), GotoPoint);
    end;

    procedure TForm1.Timer1Timer(Sender: TObject);
    Const Speed = 3;
    begin
         If (Panel1.Left = GotoPoint.X) and (Panel1.Top = GotoPoint.Y) then EXIT;

      X:= X + Cos(DegToRad(Angle)) * Speed);
      Y:= Y + Sin(DegToRad(Angle)) * Speed);

      Panel1.Left:= round(X);
      Panel1.Top:= round(Y);
    end;

    ;
  • Putnik © (07.01.09 18:45) [12]
    А функция getangle где?
  • Putnik © (07.01.09 19:31) [13]
    Прошу прощения, функция getangle должна использовать арктангенс с учетом знака это раз.
    А во-вторых, поставив скорость равной 3, вы получаете положение точки с точночтью до этой скорости, т.е.
    Б   (07.01.09 16:46) [9]
    > Сделал. Немного всё равно промахивается, но и так сойдёт
    Промахивается в пределах устанавливаемой вами скорости
  • Б (07.01.09 20:03) [14]
    > Прошу прощения, функция getangle должна использовать арктангенс с учетом знака это раз.
    Моя функция работает шикарно.

    > Промахивается в пределах устанавливаемой вами скорости...
    Проверил. Это не так. По словам @!!ex "недолжно ничего промахиваться".
    Поставил Speed в 30 интервал таймера в 3. Диапазон промаха всегда одинаковый, при любых скоростях, он равен < 1.
  • Б (07.01.09 20:08) [15]
    > Иногда почему-то точка не долетает до нужной, порой на значительные > расстояния.
    Разобрался. Потому что вместо AND стоял OR:

     If (Panel1.Left = GotoPoint.X) and (Panel1.Top = GotoPoint.Y) then EXIT;

  • Б (07.01.09 20:09) [16]
    Теперь осталось добавить таблицу косинов и синусов... :)
  • Б (07.01.09 20:23) [17]
    Хм... при некоторых параметрах - точка пока летит, что-то очень сильно дёргается в стороны.
  • Putnik © (07.01.09 20:38) [18]
    Ваш код даже не откомпилируется:
    [code]  X:= X + Cos(DegToRad(Angle)) * Speed);
     Y:= Y + Sin(DegToRad(Angle)) * Speed);[/code]
    Вы работаете с одним кодом, а сюда выкладываете другой.
  • Б (07.01.09 20:50) [19]
    > Вы работаете с одним кодом, а сюда выкладываете другой.

    Подумаешь... стёрлась пара скобой. Беда какая. :)
    Код такой же.
  • KilkennyCat © (08.01.09 00:54) [20]

    > Подумаешь... стёрлась пара скобой. Беда какая. :)

    Эти скопки можно поставить двумя вариантами с разным результатом
    Может, тебе тогда стоит не озадачивать других своими вопросами? Подумаешь... беда какая.
  • Дуб © (08.01.09 07:52) [21]
    Проще не диф уравнением, а сразу выводить в координатах окружности вычисляяя нужную дугу. Тогда никаких прмахов не будет.
  • Б (08.01.09 11:24) [22]
    > Эти скопки можно поставить двумя вариантами с разным результатом
    И кто же, таким образом, сделает? :) .

    > Может, тебе тогда стоит не озадачивать других своими вопросами?  
    Не надо путать вопрос от опечатки. Тем более там стоит смайл.

    2 Дуб
    Можно поподробней?
  • tButton © (08.01.09 11:35) [23]
    не удержался и не дочитал примерно половину
    но если есть исходные координаты и конечные координаты
    то на кой черт нужен угол?
    разве нельзя обойтись линейной интерполяцией?
  • Дуб © (08.01.09 12:26) [24]
    > Можно поподробней?

    У тебя движение по окружности(при угле не краном пипополам). Ну и надо ставить точку в нужное место окружности.
  • Дуб © (08.01.09 12:31) [25]

    > Дуб ©   (08.01.09 12:26) [24]

    Тьфу ты. Не по окружности - по прямой. Вот и надо по этой прямой двигаться. Не дифференцировано на каждом шаге, а в общем.
  • tButton © (08.01.09 12:37) [26]
    есть мысль... при определенном стечении обстоятельств
     X:= X + Cos(DegToRad(Angle)) * Speed);
     Y:= Y + Sin(DegToRad(Angle)) * Speed);
    окажется дальше по азимуту чем конечная точка...
    и условие
    If (Panel1.Left = GotoPoint.X) and (Panel1.Top = GotoPoint.Y) then EXIT
    не выполнится никогда...
    хотя, конечно, это только при speed > 0.5
    но нам об этом ничего неизвестно...
  • Б (08.01.09 14:48) [27]
    > то на кой черт нужен угол? разве нельзя обойтись линейной > интерполяцией?

    В данном случае конечно можно, когда дана конечная точка.  
    А если её нет?
    Представим себе игрока. Движение осуществляется по этой формуле. Теперь, нам нужно просто изменить угол и всё. Спрайт будет двигаться всегда туда, куда смотрит. (Нужно незабывать его вращать на заданный угол, естественно).

    > не выполнится никогда...

    Да, условие не всегда выполнится, если скорость будет слишком большая.
    Помотому что, точка будет совершать скачкообразные движения и может просто немного перепрыгнуть конечную точку.
  • Дуб © (09.01.09 05:49) [28]

    > Движение осуществляется по этой формуле.

    Надо значит не по этой. А всегда иметь в памяти предполагаемую точку попадания (реальную или взятую какм ожно дальше), которую вычисляем исходя из начальной точки и угла. Тогда никуда мы не съедем и попадем куда надо. Всегда.

    > Помотому что, точка будет совершать скачкообразные движения
    > и может просто немного перепрыгнуть конечную точку.

    Если все так плохо, то можно строить проекции на отрезок перемещения. Если пересекла - было попадание.
  • Б (12.01.09 11:27) [29]
    Всё. Тема Закрыта. Спасибо.
  • Б (20.01.09 19:45) [30]
 
Конференция "Игры" » Движение точки
Есть новые Нет новых   [119368   +25][b:0][p:0.002]