Задача такова, чтобы реализовать нецентральное соударение двух шаров (на плоскости) разных масс и скоростей и рисовать все это на канве (в Дельфи). Я так понимаю, что нужно делать в таймере: вычислять новые координаты, перебирать каждый шар (это если их много), не соприкасается ли он с другим. Когда это произошло, нужно перещитывать скорости и направления шаров. Вот это как раз таки и интересует. По каким формулам можно посчитать углы и скорости?? Перепробывал кучу формул, найденных в книгах и интернете. Не работает даже центральный удар. Может что-нибудь неправильно в самой идее реализации..
А ты б хотя бы этот, частный, случай реализовал - прежде чем за общее браться... Пока ни строчки твоего кода (даже неправильного работающего) никто не видел...
Вот код обработчика события таймера. Там почти все закомментировано, т.к содержит несколько вариантов обсчета скоростей. Однако все неправильно считают. Я начал подозревать, что дело не в формулах, а в самой идее реализации.
Насколько я вижу, у тебя не будет обновляться положение шаров, поскольку изменение координат X и Y происходит только при касании границы, а откуда взяться этому касанию?
Вот так попробуй:
procedure TForm1.Timer1Timer(Sender: TObject); var i, j, dx, dy: integer; vxOld, vyOld: integer; begin for i := 1 to Amount do begin with Balls[i] do begin
if (X <= R) or (X >= PaintBox1.Width - R) then Vx := -Vx; x := x + Vx; // Изменение координаты - в любом случае, ВНЕ If-а
if (Y <= R) or (Y >= PaintBox1.Height - R) then Vy := -Vy; y := y + Vy; // аналогично
end;
for j := 1 to Amount do begin if i <> j then begin dx := Balls[i].x + Balls[i].vx - Balls[j].x - Balls[j].vx; dy := Balls[i].y + Balls[i].vy - Balls[j].y - Balls[j].vy; if sqrt(dx*dx + dy*dy) <= Balls[i].R + Balls[j].R then begin
В моем случае строчки "x:=x + Vx;" и "y:=y + Vy;" в конструкциях if нужны для отскока от стенки не теряя "шага" (эксперементально доказано , т.к при действии силы шары будут, отскакивая от стенки, постоянно снижаться). А чтобы текущий объект двигался есть следущие строчки в конце конструкции обработчика в первом for после второго for:
// Изменяет скорость при действии внешней силы: Vx:=Vx + Fx / Mass; Vy:=Vy + Fy / Mass; // Изменяет координату: x:=x + Vx * ddt; y:=y + Vy * ddt;
Кста, ваш вариант просчета скоростей тоже у мя не работает правильно.. Я вот думаю, может общие формулы не подходят для всех случаев и нада рассматривать более частные, например при определенных углах будут разные формулы..
А я твой вариант не менял, я просто отформатировал его так, чтобы видно было, что к чему относится. Уж очень странно выглядят формулы, ощущение - что со скобками напутано. А вникать в логику происходящего в программе просто нет времени, да и поздно уже.
Вот код обработчика события таймера. Там почти все закомментировано, т.к содержит несколько вариантов обсчета скоростей. Однако все неправильно считают. Я начал подозревать, что дело не в формулах, а в самой идее реализации. Подскажите что-нить..
Подозреваю, что ты прав. Мне кажется, что формула при каждом пересчете дает дискретное значение, а это задача реального времени. Значение координаты шара постоянно меняется, и программа постоянно должна его мониторить.Когда я как ты, пытался считать по формулам, программа у меня вылетала-не знала, какое зачение подставлять-предыдущее или последующее. Тут надо понимать логику действий. Попробуй вот такой код. Он "типа корявый", но логика соударений в нем реализована.
program Sharik2; uses graph,crt; var Gd, Gm, X, Y, R, n: Integer; Napr: string; X1,Y1,R1,n1, Napr1: Integer; begin Gd := Detect; InitGraph(Gd, Gm, ' '); X:=120; Y:=240; R:=20; Napr:='NP'; n:=1; X1:=220; Y1:=230; R1:=15; Napr1:=6; n1:=1; 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); Circle(X1,Y1,R1); {Line(X,Y,X1,Y1);--эта линия не обязательна} delay(400); setcolor(0); Circle(X,Y,R); Circle(X1,Y1,R1); Line(X,Y,X1,Y1); if Napr='VP' then begin X:=X+n; Y:=Y-n; end; if Napr='NP' then begin X:=X+n; Y:=Y+n; end; if Napr='NL' then begin X:=X-n; Y:=Y+n; end; if Napr='VL' then begin X:=X-n; Y:=Y-n; 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; if Napr1=2 then begin X1:=X1+n1; Y1:=Y1-n1; end; if Napr1=4 then begin X1:=X1+n1; Y1:=Y1+n1; end; if Napr1=6 then begin X1:=X1-n1; Y1:=Y1+n1; end; if Napr1=8 then begin X1:=X1-n1; Y1:=Y1-n1; end; if Y1=40 then begin if Napr1=2 then Napr1:=4; if Napr1=8 then Napr1:=6; end; if X1=620 then begin if Napr1=2 then Napr1:=8; if Napr1=4 then Napr1:=6; end; if Y1=440 then begin if Napr1=4 then Napr1:=2; if Napr1=6 then Napr1:=8; end; if X1=20 then begin if Napr1=8 then Napr1:=2; if Napr1=6 then Napr1:=4; end; if (abs(X-X1)<(R1+R)/2) and (abs(Y-Y1)<(R1+R)/2) then begin if Napr='VP' then Napr:='NL'; if Napr='VL' then Napr:='NP'; if Napr='NP' then Napr:='VL'; if Napr='NL' then Napr:='VP'; if Napr1=2 then Napr1:=6; if Napr1=4 then Napr1:=8; if Napr1=6 then Napr1:=2; if Napr1=8 then Napr1:=4; end; until keypressed; CloseGraph end.
--------------------
Смысл откроется тебе. Красками играя Жизнь предстанет как поток без конца и края.
В этом мире поройразбиваютсямечты Но чтобы он стал другойВдруг в него приходишь ТЫ...
После странствий и скитаний настают другие времена. Старая волна уходит и приходит новая волна.