Помощь - Поиск - Пользователи - Календарь
Полная версия: Моделирование движения шаров
Форум «Всё о Паскале» > Pascal, Object Pascal > Написание игр
Страницы: 1, 2
Lapp
Дальше для каждой компоненты записываешь (на бумажке) ЗСИ и ЗСЭ:

m1*Vx1 + m2*Vx2 = m1*Vx1' + m2*Vx2
m1*Vx1^2 + m2*Vx2^2 = m1*Vx1'^2 + m2*Vx2'^2

(Для Vy аналогично).

Дальше решаешь эти две системы (тоже на бумажке). Находишь Vx1' и Vx2' (а также Vy1' и Vy2'). Заводишь в программу эти решения:

Vx1 := {выражение через Vx1 и Vx2 }
Vx2 := {выражение через Vx1 и Vx2 }
Vy1 := {выражение через Vy1 и Vy2 }
Vy2 := {выражение через Vy1 и Vy2 }

После этого находишь модули и углы:

V1 := Sqrt(Vx1*Vx1+Vy1*Vy1);
Angle1 := ArcTan(Vy1/Vx1);
if Abs(Vx1)<1e-5 then begin
Angle1:=Pi/2;
if Vy1<0 then Angle1:=-Angle1
end
else begin
Angle1:=ArcTan(Vy1/Vx1);
if Vx<0 then Angle1:=-Angle1
end;

- и плюс аналогично для второго шарика.
Сделай и выложи тут, я проверю.
Если все еще непонятно - говори.

Теперь ты видишь, сколько мороки с углами? Если бы не они, то все, что нужно было бы в этой процедуре - это те четыре строчки с решениями ЗСИ и ЗСЭ..
18192123
Цитата(Lapp @ 24.04.2007 23:10) *

Находишь Vx1' и Vx2' (а также Vy1' и Vy2'). Заводишь в программу эти решения:

Vx1 := {выражение через Vx1 и Vx2 }
Vx2 := {выражение через Vx1 и Vx2 }
Vy1 := {выражение через Vy1 и Vy2 }
Vy2 := {выражение через Vy1 и Vy2 }


ты имел ввиду
Vx1' := {выражение через Vx1 и Vx2 }
Vx2' := {выражение через Vx1 и Vx2 }
Vy1' := {выражение через Vy1 и Vy2 }
Vy2' := {выражение через Vy1 и Vy2 }
?

Abs(Vx1)< 1e-5 - что такое 1е-5?

А морока с углами - не куда не денешься, как сказали, так и приходиться делать....( имею ввиду в универе)
Lapp
Цитата(18192123 @ 25.04.2007 0:10) *

ты имел ввиду
Vx1' :=
?
Нет, я имел в виду то, что написал. Пересчитываем значения через старые и кладем их в те же самые переменные. Логично? Это программирование уже, математика кончилась..
Цитата(18192123 @ 25.04.2007 0:10) *

Abs(Vx1)< 1e-5 - что такое 1е-5?
Это аналог сравнения с нулем. Математически формула теряет смысл при Vx1=0. Но реально в программе это может произойти и раньше, когда модуль этой величины становится слишком маленьким - и возникнет переполнение, сбой в программе. Для твоей программы вполне достаточно приблизительно сравнения с 0.0001 (то есть 1e-5). Я взял это наобум, но суть выдержана.
Цитата(18192123 @ 25.04.2007 0:10) *

А морока с углами - не куда не денешься, как сказали, так и приходиться делать....( имею ввиду в универе)
Ну, слава Богу - хоть какое-то объяснение есть.. smile.gif
18192123
Цитата(Lapp @ 24.04.2007 23:10) *

Дальше для каждой компоненты записываешь (на бумажке) ЗСИ и ЗСЭ:

m1*Vx1 + m2*Vx2 = m1*Vx1' + m2*Vx2
m1*Vx1^2 + m2*Vx2^2 = m1*Vx1'^2 + m2*Vx2'^2

(Для Vy аналогично).

Дальше решаешь эти две системы (тоже на бумажке). Находишь Vx1' и Vx2' (а также Vy1' и Vy2'). Заводишь в программу эти решения:


ох...что-то я залезла в дебри.....
18192123
перед тем, как шарики сталкиваются, программа вылетает и выдаёт ошибку 207....первое, о чём подумала- стек переполнился из длинных выражений для скоростей, разбила на более простые - не помогло...


procedure after_hit (var speed1, speed2 : integer; var angle1, angle2 : single);
var m1, m2 : real;
Vx1, Vy1, Vx2, Vy2 : real;
t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 : real;
begin
m1 := value®;
m2 := value®;
Vx1 := speed1*cos(angle1);
Vy1 := speed1*sin(angle1);
Vx2 := speed2*cos(angle2);
Vy2 := speed2*sin(angle2);
t1 := m2/(m1*(m2 + m1));
t2 := (Vx1 - Vx2);
t3 := (m1*m1*m2 - m1);
Vx1 := Vx1 + t1*t2*t3;
t4 := (Vy1 - Vy2);
Vy1 := Vy1 + t1*t4*t3;
t5 := Vx1*m1 + m2*Vx2;
t6 := m1*m1*Vx1;
t7 := m1*m1*m2*Vx2;
vx2 := (t5 - t6 + t7)/(m2 + m1);
t8 := Vy1*m1 + m2*Vy2;
t9 := m1*m1*Vy1;
t10 := m1*m1*m2*Vy2;
vy2 := (t8 - t9 + t10)/(m2 + m1);
speed1 := round(sqrt(Vx1*Vx1 + Vy1*Vy1));
Angle1 := Arctan(Vy1/Vx1);
if abs(Vx1) < 1e - 5 then begin
Angle1 := pi/2;
if Vy1 < 0 then Angle1 := - angle1
end
else begin
Angle1 := ArcTan(Vy1/Vx1);
if Vx1 < 0 then Angle1 := - angle1
end;
speed2 := round(sqrt(Vx2*Vx2 + Vy2*Vy2));
Angle2 := Arctan(Vy2/Vx2);
if abs(Vx2) < 1e - 5 then begin
Angle2 := pi/2;
if Vy2 < 0 then Angle2 := - angle2
end
else begin
Angle2 := ArcTan(Vy2/Vx2);
if Vx2 < 0 then Angle2 := - angle2
end;
end;



Lapp
Цитата(18192123 @ 26.04.2007 20:01) *

перед тем, как шарики сталкиваются, программа вылетает и выдаёт ошибку 207....первое, о чём подумала- стек переполнился из длинных выражений для скоростей, разбила на более простые - не помогло...

Почему, собственно, стек?.. blink.gif А, ты что ли о стеке ко-процессора?.. Нет, это маловероятно, а главное - это все равно означает ошибку, а не большие формулы smile.gif.
Короче, либо корень из отрицательного числа, либо перевод в целые (round) очень большого числа..

Я прогнал ее с некими среднепотолочными значениями - все прошло нормально, не повезло мне.
Ищи ошибку в математике. Не найдешь - приходи, будем искать вместе smile.gif.

Кстати, а в какой строке это происходит? Это же ключ к поиску! Обязательно обрати внимание.
18192123
Ошибок в математике не нашла.... (но у меня получилось 2 набора значений для Vx1' и Vx2' (а также Vy1' и Vy2'), подставляла каждое - результат тот же)

в какой строке это происходит - не разберусь...

Lapp
Цитата(18192123 @ 27.04.2007 23:41) *

в какой строке это происходит - не разберусь...

В чем ты работаешь? в ТР/ВР или FPC?
18192123
Цитата(Lapp @ 27.04.2007 23:49) *

В чем ты работаешь? в ТР/ВР или FPC?

ТР
Lapp
Цитата(18192123 @ 28.04.2007 0:05) *

ТР

ТР обычно показывает строку с ошибкой.. Странно.

Хорошо, сделай, пожалуйста, вот, что.
Перед передачей параметров в эту процедуру, распечатай их. И покажи тут результат. Сделаешь?
18192123
Цитата(Lapp @ 28.04.2007 0:33) *


Перед передачей параметров в эту процедуру, распечатай их.

speed1 = 3, speed2 = 12, angle1 = -12.344778061, angle2 = -9,2031850815
18192123
А если не применять з-ны сохранения ( изменение скорости на совести пользователя - с помощью стрелок), то как можно записать углы, на которые должны отклоняться шарики после соударения?

может так:

procedure after_hit (var angle1, angle2 : single);
begin
angle1 := pi-random(628)/40;
angle2 := -random(628)/20;
end;



При такой записи шарики проскакивают через друг друга сравнительно редко (чем раньше), но всё вероятность такая остаётся.... и как эту вероятность убрать smile.gif ?
Чужак
18192123, здравствуй!
Читал НЕ мало твою тему, и прочитав вот это:
Цитата(Lapp @ 18.04.2007 3:19) *

Некто хочет научиться варить суп. Прежде всего он идет на кухню в общаге, хватает с плиты первую попавшуюся кастрюлю, тащит ее к шеф-повару и говорит: "Объясите мне пожалуйста, зачем тут вот эти штуки.." - и показывает на плавающие там обрывки упаковочной бумаги, куски полиэтилена (нет, волосы упоминать не буду, можете не зажмать рты.. smile.gif). Что может сказать шеф-повар? Его спросили не нужно ли это, а именно с какой целью это тут. Прямо показали пальчиком, и заинтересованно и серьезно ждут ответа.. Я думаю, он поступит как в том старом анекдоте из серии про студента кулинарного техникума (у Хазанова было такое амплуа), когда упомянутый студент пришел к врачу с обваренными гениталиями. Он скажет: "вылейте все это на ..."
После этого он прочтет бедному несчастному студенту лекцию на тему о варке супа, и проведет практическое занятие, а также подарит тарелку хорошего супа. А потом скажет, как это свойственно профессорам-шеф-поварам: если что неясно - я к Вашим услугам, милейший.
Но студент, уяснив кое-что (хоть и не много), говорит - а, не хочу я разбираться в его супе. Его суп слишком сложен для меня (и мой семинарист говорит, что мне такой суп никогда не сварить..) Сварю-ка я свой собственный суп.. И варит. Но суп получается горький, пересоленый, мясо в нем не разжевать.. Что делать? Конечно, идти к шеф-повару! И спрашивать: а зачем я сделал так? а почему я сделал этак?..
Понимаешь, если программа небольшая или речь идет о фрагменте, где локализована ошибка - это одно. Но если нужно расхлебывать весь переперченый недосоленный суп...

опечалился сильно, подумав, что супу в твоем приготовлении мы так и не отведаем (а супу надо), потому решил настрогать в твою тему пару "премудрых телег"...
Программу, твою не смотрел, извини, но по кускам кода, в которых ты плаваеш, пытаясь разобраться, диагноз мне стал ясен.
А именно-ТЫ НЕ ПОНИМАЕШЬ ЛОГИКИ ДЕЙСТВИЙ ПРОГРАММЫ, КОТОРАЯ БУДЕТ РЕШАТЬ ТВОЮ ЗАДАЧУ.
Вот смотри: есть шарик, с параметрами (X,Y,R) (пусть R в простейшем случае не меняется) и программа должна постоянно отслеживать их состояние, и причем на основании определенной логики (Если А, то В). Сначала надо было понять эту логику, потом прописать алгоритм, затем уже начинать писать программу, а не наоборот. Ты же сразу пытаешься разобраться в коде (сначала чужом, затем в своем).
(Если все понятно, можешь дальше не читать...)
Да, на первый взгляд простая задача-и чуть ли не на уровень Искуственного Интеллекта тянет...Но не баись-вдвоем не пропадем!-(она чуть проще).
Щас "аз, многогрешный" будет перечить Lapp'у-уже коленки трясуться...
Все советы из раздела "Физика" оставь побоку, поскольку на Паскале можно моделировать не только физическую среду, а какую угодно среду, хватило бы знания программирования, математики и логики, и (главное!) фантазии, творческого воображения и воли...
Я знаю, о чем говорю, потому что изучал Паскаль в рамках предмета "Математич.моделирование электромеханических систем", и там надо было не только написать работающий код, и даже не просто решить систему уравнений, а чтобы эта система уравнений правильно моделировала электродвигатель, и чтобы он работал, т.е. вращался...Так вот: проверка на соответсвие реальной физике в Паскаль не встроена, там можно прописать уравнения и логику, которая моделирует то, чего в природе нет...В твоем случае это означает, что шарики можно заставить пульсировать, отражаться и вообще плясать под балалайку...
Не зацикливайся не на физике процесса (какая захочешь, такая и будет), не на коде-взгляни на проблему шире...(Стереотипное мышление-между нами!-не лучший советчик...)
Это называется "открытый простор"-включи воображение, сначала представь себе идеальный конечный результат (т.е.в твоем случае-какой ты хочешь видеть свою программу), а затем препятствия, которые мешают тебе в его достижении-и не наоборот, иначе твоя мысля отразиться от первого же препятсвия, как шарик от борта, и конечная цель даже в представлении будет неясной...
Приемы раскрытия творческого мышления человека (типа "открытого простора" ), не только известны, но систематизированы. Есть даже ТРИЗ-Теория Решения Изобретательских Задач (если проснулась творческая жилка и решимость самой решить до конца-прочитай об этом всем www.trizland.ru,www.trizminsk.org и др.) и вперед...
(Если все понятно, можешь дальше не читать...)
Теперь о решении твоей задачи-если в Паскале полно возможностей и опций (процедуры, фунции, массивы и др.) для Cod-Master'а типа volvo или Lapp-не пытайся сразу все использовать, используй лишь те, что нужны для решения твоей задачи...Еще раз говорю-задача не на физику, а на корректную логику-вот и рассуждай логически.
Итак, есть шарик, с параметрами (X,Y,R), и для начала один. Есть направления его движения на восемь сторон Верх(V), Верх-Право(VP), Право(P), Низ-Право (NP), Низ (N), Низ-Лево(NL), Лево (L), Верх-Лево(VL).
(Пока берем четырехсторонюю...VP,NP,VL,NL). И изменения направления на границе. Это всё! И все это реализовано в моей простоватой программе:
 program Sharik;
uses graph,crt;
var Gd, Gm, X, Y, R: Integer; Napr: string;
begin
Gd := Detect; InitGraph(Gd, Gm, ' ');
X:=320; Y:=240; R:=10; Napr:='NP';
repeat
setcolor(15);
Line(20, 40,20, 440); Line(20,40,620,40);
Line(620,40,620,440); Line(620,440,20,440);
Circle(X,Y,R);
delay(500);
setcolor(0);
Circle(X,Y,R);
if Napr='VP' then begin
X:=X+1; Y:=Y-1;
end;
if Napr='NP' then begin
X:=X+1; Y:=Y+1;
end;
if Napr='NL' then begin
X:=X-1; Y:=Y+1;
end;
if Napr='VL' then begin
X:=X-1; Y:=Y-1;
end;
if Y=40 then begin
if Napr='VP' then Napr:='NP';
if Napr='VL' then Napr:='NL';
end;
if X=620 then begin
if Napr='VP' then Napr:='VL';
if Napr='NP' then Napr:='NL';
end;
if Y=440 then begin
if Napr='NP' then Napr:='VP';
if Napr='NL' then Napr:='VL';
end;
if X=20 then begin
if Napr='VL' then Napr:='VP';
if Napr='NL' then Napr:='NP';
end;
until keypressed;
CloseGraph
end.

Так вот-это базовая конструкция-хочешь поменять параметры шарика, поменяй X,Y,R, хочешь изменить скорость-вместо X+1 поставь X+N (и для Y тоже, и пропиши N в Var'е), или просто уменьши/увеличь задержку в delay(), хочешь добавь еше шарик-тогда у каждого шарика свои параметры ш1(X1,Y1,R1), ш2(X2,Y2,R2)(И сделай логику для соударения шариков, как я сделал для границ-там все просто), потом сделай ввод переменных скорости и др. с клавиатуры и т.д..Главное-вноси изменения поэтапно, и по изменению за раз-внесла одно-проверила, внесла следующее и т.д. Короче, твори!
"Гуру", Марина, это хорошо, а "своим умом" гораздо лучше. Гуру-он витает в высотах Объектно-Ориентированного Программинга, куда небожителям снизойти до Нас, простых людей...
Будь здорова, Мариночка!
Жму лапку котику на твоем аватарчике!
С нетерпением жду твоего супчика!
Искренне, от души, Чужак.
P.S. а кто посмеяся над сим посланием-тот посмеяся над собой.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.