Задача такова, чтобы реализовать нецентральное соударение двух шаров (на плоскости) разных масс и скоростей и рисовать все это на канве (в Дельфи). Я так понимаю, что нужно делать в таймере: вычислять новые координаты, перебирать каждый шар (это если их много), не соприкасается ли он с другим. Когда это произошло, нужно перещитывать скорости и направления шаров. Вот это как раз таки и интересует. По каким формулам можно посчитать углы и скорости?? Перепробывал кучу формул, найденных в книгах и интернете. Не работает даже центральный удар. Может что-нибудь неправильно в самой идее реализации..
Заранее благодарен.
http://www.delphikingdom.com/asp/viewitem.asp?UrlItem=/mastering/poligon/billiard.htm тоже пробовал?
+ Поищи по форуму, выкладывались реализации (да и формулы тоже) того, что тебе нужно...
А ты б хотя бы этот, частный, случай реализовал - прежде чем за общее браться... Пока ни строчки твоего кода (даже неправильного работающего) никто не видел...
Вот код обработчика события таймера. Там почти все закомментировано, т.к содержит несколько вариантов обсчета скоростей. Однако все неправильно считают. Я начал подозревать, что дело не в формулах, а в самой идее реализации.
procedureCode.txt ( 9.13 килобайт )
Кол-во скачиваний: 733
Подскажите что-нить..
Насколько я вижу, у тебя не будет обновляться положение шаров, поскольку изменение координат X и Y происходит только при касании границы, а откуда взяться этому касанию?
Вот так попробуй:
procedure TForm1.Timer1Timer(Sender: TObject);Обрати внимание на то, КАК у тебя вычисляются Vx и Vy. Ты уверен, что ты именно этого хочешь, либо напутал со скобками?
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
VxOld:=Balls[i].Vx;
VyOld:=Balls[i].Vy;
Balls[i].Vx:=Trunc(
(
(Balls[i].Mass-Balls[j].Mass)*VxOld + 2*Balls[j].Mass*Balls[j].Vx
) /
(Balls[i].Mass+Balls[j].Mass)
);
Balls[i].Vy:=Trunc(
(
(Balls[i].Mass-Balls[j].Mass)*VyOld + 2*Balls[j].Mass*Balls[j].Vy
) /
(Balls[i].Mass+Balls[j].Mass)
);
Balls[j].Vx:=Trunc(
(
(Balls[j].Mass-Balls[i].Mass) * Balls[j].Vx + 2*Balls[i].Mass*VxOld
) /
(Balls[i].Mass+Balls[j].Mass)
);
Balls[j].Vy := Trunc(
(
(Balls[j].Mass-Balls[i].Mass) * Balls[j].Vy + 2*Balls[i].Mass*VyOld
) /
(Balls[i].Mass+Balls[j].Mass)
);
end;
end;
end;
end;
UpdatePic;
//
end;
В моем случае строчки "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.