procedure TFMain.TimerMainTimer(Sender: TObject); const ddt = 1; Mu = 1; // Коэффициент трения (исп. где бильярдные шары) var i, j: Integer; dx, dy: Real; VxOld, VyOld: Real; { fi, adir, bdir, av, bv, vn, dv1, dv2: Real; //} { vx10,vy10,vx20,vy20,m1,m2: Real; //} { l,x1,x2,y1,y2: Real; //} { ab, av, bv, alpha1, gamma1, beta1, alpha2, gamma2, beta2, pr1x, pr1y, pr1xx, pr1xy, pr1yx, pr1yy, pr2x, pr2y, pr2xx, pr2xy, pr2yx, pr2yy, Vx1New, Vy1New, Vx2New, Vy2New: Real; //} begin for i:=1 to Project.ProjObjectsCount do begin with Project.ProjObjects[i], Project do begin if x <= Radius then // Проверка столкновения с левой границей begin Vx:=-Vx; x:=x + Vx; end; if x >= ProjWidth-Radius then // с правой границей begin Vx:=-Vx; x:=x + Vx; end; if y <= Radius then // с верхней границей begin Vy:=-Vy; y:=y + Vy; end; if y>=ProjHeight-Radius then // с нижней границей begin Vy:=-Vy; y:=y + Vy; end; for j:=1 to ProjObjectsCount do if j<>i then begin dx:=x + vx - ProjObjects[j].x - ProjObjects[j].vx; dy:=y + vy - ProjObjects[j].y - ProjObjects[j].vy; if sqrt(dx*dx + dy*dy)<= Radius+ProjObjects[j].Radius then begin (* // // Упрощенный вариант // VxOld:=Vx; VyOld:=Vy; Vx:=((Mass-ProjObjects[j].Mass)*VxOld + 2*ProjObjects[j].Mass*ProjObjects[j].Vx) /(Mass+ProjObjects[j].Mass); Vy:=((Mass-ProjObjects[j].Mass)*VyOld + 2*ProjObjects[j].Mass*ProjObjects[j].Vy) /(Mass+ProjObjects[j].Mass); ProjObjects[j].Vx:=((ProjObjects[j].Mass-Mass) *ProjObjects[j].Vx + 2*Mass*VxOld)/(Mass+ProjObjects[j].Mass); ProjObjects[j].Vy:=((ProjObjects[j].Mass-Mass) *ProjObjects[j].Vy + 2*Mass*VyOld)/(Mass+ProjObjects[j].Mass); //*) (* // // Другой вариант // VxOld:=Vx; VyOld:=Vy; Vx:=(2*ProjObjects[j].Mass*ProjObjects[j].Vx - (ProjObjects[j].Mass-Mass)*Vx) /(ProjObjects[j].Mass+Mass); Vy:=(2*ProjObjects[j].Mass*ProjObjects[j].Vy - (ProjObjects[j].Mass-Mass)*Vy) /(ProjObjects[j].Mass+Mass); ProjObjects[j].Vx:=(2*Mass*VxOld - (Mass-ProjObjects[j].Mass)*ProjObjects[j].Vx) /(ProjObjects[j].Mass+Mass); ProjObjects[j].Vy:=(2*Mass*VyOld - (Mass-ProjObjects[j].Mass)*ProjObjects[j].Vy) /(ProjObjects[j].Mass+Mass); //*) (* // // Из статьи про бильярднае шары (http://billiard-bsv.narod.ru/) // ab:=Sqrt((ProjObjects[j].x-x)*(ProjObjects[j].x-x) + (ProjObjects[j].y-y)*(ProjObjects[j].y-y)); av:=Sqrt(Vx*Vx + Vy*Vy); bv:=Sqrt(ProjObjects[j].Vx*ProjObjects[j].Vx + ProjObjects[j].Vy*ProjObjects[j].Vy); //Для первого шара if ProjObjects[j].y > y then // alpha1:=arctan2(ProjObjects[j].x-x,ab) alpha1:=arccos((ProjObjects[j].x-x)/ab) else // alpha1:=-arctan2(ProjObjects[j].x-x,ab); alpha1:=-arccos((ProjObjects[j].x-x)/ab); if Vy > 0 then // gamma1:=arctan2(Vx,av) gamma1:=arccos(Vx/av) else // gamma1:=-arctan2(Vx,av); gamma1:=-arccos(Vx/av); beta1:=gamma1-alpha1; pr1x:=av*Cos(beta1); pr1y:=av*Sin(beta1); pr1xx:=pr1x*Cos(alpha1); pr1xy:=pr1x*Sin(alpha1); pr1yx:=pr1y*Cos(alpha1); pr1yy:=pr1y*Sin(alpha1); //Для второго шара if ProjObjects[j].y < y then // alpha2:=arctan2(x-ProjObjects[j].x,ab) alpha2:=arccos((x-ProjObjects[j].x)/ab) else // alpha2:=-arctan2(x-ProjObjects[j].x,ab); alpha2:=-arccos((x-ProjObjects[j].x)/ab); if ProjObjects[j].Vy > 0 then // gamma2:=arctan2(ProjObjects[j].Vx,bv) gamma2:=arccos(ProjObjects[j].Vx/bv) else // gamma2:=-arctan2(ProjObjects[j].Vx,bv); gamma2:=-arccos(ProjObjects[j].Vx/bv); beta2:=gamma2-alpha2; pr2x:=bv*Cos(beta2); pr2y:=bv*Sin(beta2); pr2xx:=pr2x*Cos(alpha2); pr2xy:=pr2x*Sin(alpha2); pr2yx:=pr2y*Cos(alpha2); pr2yy:=pr2y*Sin(alpha2); // Вычисление новых составляющих Vx1New:=Vx + ((-2*Pr1Xx)+Pr2Xx) * Mu; Vy1New:=Vy + ((-2*Pr1Xy)+Pr2Xy) * Mu; Vx2New:=ProjObjects[j].Vx + ((-2*Pr2Xx)+Pr1Xx) * Mu; Vy2New:=ProjObjects[j].Vy + ((-2*Pr2Xy)+Pr1Xy) * Mu; Vx:=Vx1New; Vy:=Vy1New; ProjObjects[j].Vx:=Vx2New; ProjObjects[j].Vy:=Vy2New; //*) (* // // Из флешевого ролика. // fi:=ArcTan2(ProjObjects[j].y-y, ProjObjects[j].x-x); adir:=ArcTan2(Vy,Vx); bdir:=ArcTan2(ProjObjects[j].Vy, ProjObjects[j].Vx); av:=Sqrt(Vx*Vx + Vy*Vy); bv:=Sqrt(ProjObjects[j].Vx*ProjObjects[j].Vx + ProjObjects[j].Vy*ProjObjects[j].Vy); vn:=av*sin(adir-fi+PI/2) - bv*sin(bdir-fi+PI/2); dv1:=-2*ProjObjects[j].Mass / (Mass+ProjObjects[j].Mass)*vn; dv2:=2*Mass / (Mass+ProjObjects[j].Mass)*vn; Vx:= Vx + dv1*cos(fi); Vy:= Vy + dv1*sin(fi); ProjObjects[j].Vx:=ProjObjects[j].Vx + dv2*cos(fi); ProjObjects[j].Vy:=ProjObjects[j].Vy + dv2*sin(fi); //*) (* // // Из учебника. Частный случай. Центральное столкновение // VyOld:=Vy; Vy:=VyOld*(Mass-ProjObjects[j].Mass)/ (ProjObjects[j].Mass+Mass) + ProjObjects[j].Vy*(2*ProjObjects[j].Mass)/ (ProjObjects[j].Mass+Mass); ProjObjects[j].Vy:=VyOld*(2*Mass)/ (ProjObjects[j].Mass+Mass) + ProjObjects[j].Vy*(ProjObjects[j].Mass-Mass)/ (ProjObjects[j].Mass+Mass); //*) (* // // Из того же учебника. Частный случай. Центральное столкновение. // Пытался подогнать результаты :( // VyOld:=Vy; if(VyOld*ProjObjects[j].Vy >= 0)then begin Vy:=(2*ProjObjects[j].Mass*ProjObjects[j].Vy - (ProjObjects[j].Mass-Mass)*Vy) /(ProjObjects[j].Mass+Mass); ProjObjects[j].Vy:=(2*Mass*VyOld - (Mass-ProjObjects[j].Mass)*ProjObjects[j].Vy) /(ProjObjects[j].Mass+Mass); end else if(VyOld*ProjObjects[j].Vy < 0)then begin Vy:=(2*ProjObjects[j].Mass*ProjObjects[j].Vy - Abs((ProjObjects[j].Mass-Mass)*Vy)) /(ProjObjects[j].Mass+Mass); ProjObjects[j].Vy:=(2*Mass*VyOld - Abs((Mass-ProjObjects[j].Mass)*ProjObjects[j].Vy)) /(ProjObjects[j].Mass+Mass); end; //*) (* // // Из форума "Всё о Паскале", Подфорум "Написание игр", // Тема "Супер Бильярд", Сообщение #2 // (http://forum.pascal.net.ru/index.php?showtopic=4685) // vx10 := Vx; { начальные значения скоростей } vy10 := Vy; vx20 := ProjObjects[j].Vx; vy20 := ProjObjects[j].Vy; m1:=Mass; m2:=ProjObjects[j].Mass; { скорость первого шара после удара } Vx := round((2*m2*vx20 + (m1-m2)*vx10)/(m1+m2)); Vy := round((2*m2*vy20 + (m1-m2)*vy10)/(m1+m2)); { скорость второго шара после удара } ProjObjects[j].Vx := round((2*m1*vx10 + (m2-m1)*vx20)/(m1+m2)); ProjObjects[j].Vy := round((2*m1*vy10 + (m2-m1)*vy20)/(m1+m2)); //*) (* // // Из форума "Всё о Паскале", Подфорум "Написание игр", // Тема "Супер Бильярд", Сообщение #14 // (http://forum.pascal.net.ru/index.php?showtopic=4685) // x1:=x; x2:=ProjObjects[j].x; y1:=y; y2:=ProjObjects[j].y; l:=Arctan((y2-y1)/(x2-x1)); vx10 := Vx; vy10 := Vy; vx20 := ProjObjects[j].Vx; vy20 := ProjObjects[j].Vy; Vx:=(vx20+vy20)*cos(l); Vy:=(vx20+vy20)*sin(l); ProjObjects[j].Vx:=(vx10+vy10)*cos(l+PI); ProjObjects[j].Vy:=(vx10+vy10)*sin(l+PI) //*) end; end; Vx:=Vx + Fx / Mass; Vy:=Vy + Fy / Mass; x:=x + Vx * ddt; y:=y + Vy * ddt; end; end; end;