-
Точка движется по след. формулe:
x:= round(x + cos(Angle) * Speed);
y:= round(y + sin(Angle) * Speed);
где Angle измеряется в градусах.
Но почему то вся эта система не работает.
При Angle = 0, точка двигается как надо, т.е. по горизонту в правую сторону.
При других значениях Angle точка летит чёрт знает куда.
-
переводи в радианы
-
Хм... заработало. Но по часовой стрелке, а нужно против.
-
Всё разобрался. Передел функцию вычисления угла, чтобы считала угол по часовой стрелке.
Но возник друго вопрос: почему то точка немного промахивается, когда летит. Это из-за округления? Если да, то как это предотвратить. Координаты точки должны быть целыми.
-
в каком смысле "промахивается"?
-
> в каком смысле "промахивается"?
Объясняю:
Имеется на форме точка с координатами X,Y;
При клике на форму в переменную GotoPoint записываются координаты клика.
Затем находится угол между этими точками.
Далее во включенном таймере, где вставлена эта формула, вычисляется траектория движения точки.
По смыслу точка должна двигаться в место последнего клика, но, если расстояние между этими точками велико, то точка немного промахивается и пролетает мимо.
Кажется это из-за постоянного округления - накапливается погрешность.
Как с ней бороться?
-
округляй только для вывода.
-
> округляй только для вывода.
Не получится. Точка (Она, для теста, представлена как панель) всегда должна округляться, для вывода.
-
> [7] Б (07.01.09 15:13)
Для расчета храни реальные. для вывода - округлай. и будет шастье.
-
> Для расчета храни реальные. для вывода - округлай. и будет шастье.
Сделал. Немного всё равно промахивается, но и так сойдёт.
Иногда почему-то точка не долетает до нужной, порой на значительные расстояния.
В таймере стоит проверка: если перемещаемая точка равна той, к которой стремиться, то она останавливается.
-
> [9] Б (07.01.09 16:46)
1) Для чисел с плавающей точкой нет понятия "равно", есть понятие "равно с некоторым допустимым Epsilon"
2) Где-то в коде косяк, недолжно ничего промахиваться.
-
Вот код:
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;
;
-
А функция getangle где?
-
Прошу прощения, функция getangle должна использовать арктангенс с учетом знака это раз.
А во-вторых, поставив скорость равной 3, вы получаете положение точки с точночтью до этой скорости, т.е.
Б (07.01.09 16:46) [9]
> Сделал. Немного всё равно промахивается, но и так сойдёт
Промахивается в пределах устанавливаемой вами скорости
-
> Прошу прощения, функция getangle должна использовать арктангенс с учетом знака это раз.
Моя функция работает шикарно.
> Промахивается в пределах устанавливаемой вами скорости...
Проверил. Это не так. По словам @!!ex "недолжно ничего промахиваться".
Поставил Speed в 30 интервал таймера в 3. Диапазон промаха всегда одинаковый, при любых скоростях, он равен < 1.
-
> Иногда почему-то точка не долетает до нужной, порой на значительные > расстояния.
Разобрался. Потому что вместо
AND стоял
OR:
If (Panel1.Left = GotoPoint.X) and (Panel1.Top = GotoPoint.Y) then EXIT;
-
Теперь осталось добавить таблицу косинов и синусов... :)
-
Хм... при некоторых параметрах - точка пока летит, что-то очень сильно дёргается в стороны.
-
Ваш код даже не откомпилируется:
[code] X:= X + Cos(DegToRad(Angle)) * Speed);
Y:= Y + Sin(DegToRad(Angle)) * Speed);[/code]
Вы работаете с одним кодом, а сюда выкладываете другой.
-
> Вы работаете с одним кодом, а сюда выкладываете другой.
Подумаешь... стёрлась пара скобой. Беда какая. :)
Код такой же.
-
> Подумаешь... стёрлась пара скобой. Беда какая. :)
Эти скопки можно поставить двумя вариантами с разным результатом
Может, тебе тогда стоит не озадачивать других своими вопросами? Подумаешь... беда какая.
-
Проще не диф уравнением, а сразу выводить в координатах окружности вычисляяя нужную дугу. Тогда никаких прмахов не будет.
-
> Эти скопки можно поставить двумя вариантами с разным результатом
И кто же, таким образом, сделает? :) .
> Может, тебе тогда стоит не озадачивать других своими вопросами?
Не надо путать вопрос от опечатки. Тем более там стоит смайл.
2 Дуб
Можно поподробней?
-
не удержался и не дочитал примерно половину
но если есть исходные координаты и конечные координаты
то на кой черт нужен угол?
разве нельзя обойтись линейной интерполяцией?
-
> Можно поподробней?
У тебя движение по окружности(при угле не краном пипополам). Ну и надо ставить точку в нужное место окружности.
-
> Дуб © (08.01.09 12:26) [24]
Тьфу ты. Не по окружности - по прямой. Вот и надо по этой прямой двигаться. Не дифференцировано на каждом шаге, а в общем.
-
есть мысль... при определенном стечении обстоятельств
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
но нам об этом ничего неизвестно...
-
> то на кой черт нужен угол? разве нельзя обойтись линейной > интерполяцией?
В данном случае конечно можно, когда дана конечная точка.
А если её нет?
Представим себе игрока. Движение осуществляется по этой формуле. Теперь, нам нужно просто изменить угол и всё. Спрайт будет двигаться всегда туда, куда смотрит. (Нужно незабывать его вращать на заданный угол, естественно).
> не выполнится никогда...
Да, условие не всегда выполнится, если скорость будет слишком большая.
Помотому что, точка будет совершать скачкообразные движения и может просто немного перепрыгнуть конечную точку.
-
> Движение осуществляется по этой формуле.
Надо значит не по этой. А всегда иметь в памяти предполагаемую точку попадания (реальную или взятую какм ожно дальше), которую вычисляем исходя из начальной точки и угла. Тогда никуда мы не съедем и попадем куда надо. Всегда.
> Помотому что, точка будет совершать скачкообразные движения
> и может просто немного перепрыгнуть конечную точку.
Если все так плохо, то можно строить проекции на отрезок перемещения. Если пересекла - было попадание.
-
Всё. Тема Закрыта. Спасибо.
-