Ага, просто надо разобраться до конца и потом уже кодить...
Цитата
Или ты хочешь, чтобы квадрат с треугольником разлетались по другим законам, нежели два круга?
Из-за этого, наверное, и получилась неразбериха. Да, но я согласен сделать сначала твой способ, а уже потом его расширить..
Цитата
Да и возможности FPC одним выражением складывать/умножать/вычитать/масштабировать вектора тоже нельзя не принимать во внимание - это может очень сильно облегчить работу..
??? Что именно он умеет?
PS значит у меня сейчас не правильно работает объекты, ведь шарик сам просчитывает свою новую траекторию?
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Var v, v1, v2: TVector; ... v := k * (k1 * v1 + k2 * v2);
Сколько тебе понадобится строк в Турбо Паскале, чтобы это реализовать? В FPC пишется именно так, как я показал, это что, не облегчает работу? Ты именно программируешь алгоритм, а не думаешь, "а позволит ли мне ЭТО язык, или надо какой костыль изобрести?"
Hint: operator overloading
Цитата
Значит у меня сейчас не правильно работает объекты, ведь шарик сам просчитывает свою новую траекторию?
Просчет просчету рознь... Если шарик не взаимодействует со внешними объектами, а рассчитывает свое новое местоположение на основе изначально заданных параметров - то все правильно... А вот заставлять сам шарик пересчитывать эти самые параметры, когда было внешнее воздействие (вместо того, чтобы централизованно пересчитать, и передать шарику уже новые параметры) - вот это уже, на мой взгляд, неверно...
Мысли в слух: Ведь мы полностью не сможем скопировать настоящую математическую модель графических объектов (шариков, квадратов и т.п.) - нельзя постоянно проверять каждую точку каждого объекта на наявность столкновения с другим. Остается удовлетворятся только некоторыми точками. Но это надо сделать максимально реалистически и легко изменяемо. Возникает необходимость создание предка-объекта, отвечающего за математическое представление граф. объекта. Я предлагаю сделать этот объекта-предок в виде многоугольника с любым числом вершин (чем больше количество последних - тем более приближенна реализуема модель к ее реальному собрату (настоящему шару)). Вод пример для шара:
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Какие преимущества: больше не надо мучится со способами нахождения точки столкновения, угла разлёта и т.д. Недостатки: интересует не сильно ли это будет тормозить..
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Будет тормозить, конечно... Представь, что у тебя, скажем, 4, а лучше - 8 точек в модели (еще лучше - 16/32, ибо это будет еще ближе к "шару", но тогда процессор просто повесится). И 100 шариков... И каждый раз ты будешь проверять, 4 (или 8) точек, "а одна из этих точек не внутри ли какого-нибудь из оставшихся 99 шаров?"... Представляешь себе объемы вычислений? 100*100 - сразу 10000 проверок (даже по одной точке, по 4-м будет уже с полсотни тысяч) А ведь еще надо отрисовывать картинку, да и проверять столкновение со стенками... Да и сами проверки - не просто 2+2, а нечто более сложное...
Придется принимать доп. меры для сокращения объемов вычислений...
Как вариант - могу предложить следующее (просто набросок, возможно это будет не очень эффективно, на какой-то прирост производительности, определенно даст): Хранить не 1, а 2 списка объектов... Да, да, именно 2 (если даже не больше)... Смотри, что я имею в виду: Когда объект A может столкнуться с объектом B? Только тогда, когда Sign(A.Vx) <> Sign(B.Vx), т.е. проекции оббъектов на ось OX приближаются друг к другу... Вот тебе и задумка: хранить в списке ListOne только те объекты, которые движутся слева направо или по вертикали, т.е. Vx неотрицательна, а в ListTwo - все остальные... Преимущества - для каждого объекта из ListOne надо проверять на коллизии только объекты из ListTwo, в среднем - 2-х кратное уменьшение числа вычислений...
Теперь ты меня, конечно, спросишь: а что будем делать, когда Vx меняет знак (отскок от стены млм друг от друга)? А ничего особенного. Все равно есть вот этот кусок кода:
p := GObjectsList.List; while p <> nil do begin p^.data^.moveto; p := p^.next; end;
Вот, после MoveTo и проверять, изменился ли знак Vx... Если изменился - то удалить указатель на объект из одного списка, и добавить в другой... Для обоих списков (в худшем случае) "+200" операций... По сравнению с экономией примерно 20000-25000, о чем я говорил выше - будет ускорение обработки...
НО: для этого во-первых надо будет перейти на представление скорости через Vx/Vy, о чем я уже тебе говорил, а во-вторых - в класс TItem придется добавить флажок типа Boolean, чтобы для того объекта, для которого уже вызывалась MoveTo, не вызвать ее еще раз... И тогда:
// Вначале, конечно, идем по одному списку p := GFirstObjectsList.List; while p <> nil do begin p^.data^.moveto; // если знак p^.data^.Vx изменился (вполне возможно, что об этом может // сигнализировать и сама moveto, которую просто переделать в функцию) // - то скопировать p^.data в список GSecondObjectsList, и удалить из текущего // !!! special_flag (что это - см. ниже) для перенесенного объекта установить в True
p := p^.next; end;
// А теперь, собственно, по второму: p := GSecondObjectsList.List; while p <> nil do begin
// вот это - тот самый флажок, о котором я говорил // установленный в True он запретил вызывать moveto для объекта, если был // False - то все в порядке, это НЕ только что добавленное в этот список значение
if NOT p^.data^.special_flag then begin { <--- Исправлено !!! } p^.data^.moveto // если знак p^.data^.Vx изменился - все с точностью "до наоборот" тому, // что написано выше - переносим из Second в First список, только special_flag // оставляем False end else p^.data^.special_flag := false; // Все, теперь это - полноценный объект, и к нему будут применяться // все операции, что и к остальным
p := p^.next; end;
Мне такая идея отсечения нравится - как я раньше не додумался, надо будет как-нибудь попробовать...
Сорри, ошибочка... Не будет работать для двух объектов, движущихся вертикально навстречу друг другу... Надо подумать, что с этим сделать - или хранить объекты с Vx = 0 в обоих списках, или при Vx = 0 (я не думаю, что таких случаев будет очень много) проверять на коллизии оба списка...
для этого во-первых надо будет перейти на представление скорости через Vx/Vy, о чем я уже тебе говорил
Уже сделано Правда я оставил угол L для совместимости с предыдущими версиями ... Да нет - шучу, он надо для расчета впереди идущей точке. Т.е. модель графического объекта = эта точка + то, что я описал раньше.
Цитата
Мне такая идея отсечения нравится - как я раньше не додумался, надо будет как-нибудь попробовать..
Сделаем, у меня объект четырехугольника уже готов, остается его переделать в многоугольник. Только один вопросик:
Цитата
Вот, после MoveTo и проверять, изменился ли знак Vx...
А может слежения за изменением ставить для метода ChangeDirection? Ведь знак меняется только в случае вызова этой процедуры.. Т.е. при вызове ChangeDirection флажок изменения ставим в true, при вызове MoveTo - в false.
Цитата
Сорри, ошибочка... Не будет работать для двух объектов, движущихся вертикально навстречу друг другу... Надо подумать, что с этим сделать - или хранить объекты с Vx = 0 в обоих списках, или при Vx = 0 (я не думаю, что таких случаев будет очень много) проверять на коллизии оба списка...
Может тогда сделать четыре списка? Каждый цвет отвечает одному из четырёх списков:
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Т.е. при вызове ChangeDirection флажок изменения ставим в true, при вызове MoveTo - в false.
Ты не понял... Еще раз перечитай... Флажок нужен, чтобы MoveTo (в смысле, пересчет координат) не вызывался еще раз после переноса указателя из одного списка в другой (при обработке второго списка), но ведь не только тот объект, который изменил направление, должен пересчитать координаты? Пересчитывать должны ВСЕ, но ни один не должен этого делать дважды...
Цитата
Т.е. при вызове ChangeDirection флажок изменения ставим в true
С этим согласен... После ChangeDirection устанавливаем флаг в True, и переносим объект в другой список... А вот сбрасывать надо именно так, как я показал - а не по MoveTo...
Цитата
Может тогда сделать четыре списка?
Надо подумать... У тебя тут угол, а не проекция Vx... Все-таки, скорее всего будет достаточно двух, и при нулевом Vx - проверять оба списка...
Реализация Многоугольник окончена. Возник вопрос - где инициализировать вершины полигона? В SuperVisor или в конструкторе графического объекта?
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.