1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203:
| unit Unit1;
interface
uses SysUtils, Forms, StdCtrls, ExtCtrls, Classes;
const dt = 20; SubIterations = 10; KugelCount = 10;
type TKugel = class;
TForm1 = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private public Kugeln: array[0..KugelCount-1] of TKugel; end;
Borders = (boLeft, boTop, boBottom, boRight); BordersSet = set of Borders; TKugel = class(TShape) private FX, FY: Extended; FR: Extended; FM: Extended; FVx, FVy: Extended; procedure setR(const Value: Extended); public property X: Extended read FX write FX; property Y: Extended read FY write FY; property R: Extended read FR write setR; property M: Extended read FM write FM; property Vx: Extended read FVx write FVx; property Vy: Extended read FVy write FVy; procedure Move; procedure Apply; function CollidesWith(const Kugel2: TKugel): Boolean; function WallCollisions: BordersSet; constructor Create(AOwner: TComponent); override; end;
var Form1: TForm1;
implementation
{$R *.dfm}
function TKugel.CollidesWith(const Kugel2: TKugel): Boolean; begin Result := sqr(FX-Kugel2.FX)+sqr(FY-Kugel2.FY) < sqr(FR+Kugel2.FR); end;
constructor TKugel.Create(AOwner: TComponent); begin inherited; Shape := stCircle; end;
procedure TKugel.Move; begin X := X + (dt/1000)/SubIterations*FVx; Y := Y + (dt/1000)/SubIterations*FVy; end;
function TKugel.WallCollisions: BordersSet; const Border = 10; begin Result := []; if X-Border < R then Result := Result + [boLeft]; if Y-Border < R then Result := Result + [boTop]; if X+Border >= Parent.ClientWidth-R then Result := Result + [boRight]; if Y+Border >= Parent.ClientHeight-R then Result := Result + [boBottom]; end;
procedure TKugel.setR(const Value: Extended); begin FR := Value; Width := Round(FR*2); Height := Round(FR*2); end;
procedure TKugel.Apply; begin Left := round(X-FR); Top := round(Y-FR); end;
procedure TForm1.FormCreate(Sender: TObject); const Border = 10; var I: Integer; begin with Timer1 do begin Interval := dt; OnTimer := Timer1Timer; end;
for I := 0 to Length(Kugeln)-1 do begin Kugeln[I] := TKugel.Create(Form1); with Kugeln[I] do begin Parent := self; R := 20+Random(8); X := Random(self.ClientWidth-2*Round(R+Border))+Round(R+Border); Y := Random(self.ClientHeight-2*Round(R+Border))+Round(R+Border); Vx := Random(400); Vy := Random(400); M := 4/3*R*R*R*pi; Brush.Color := Random(256*256*256); end; end; end;
procedure TForm1.Timer1Timer(Sender: TObject); var DX, DY, M11, M21, M12, M22, L, Vp1, Vp2, Vs1, Vs2, MTot, Vp1_, Vp2_: Extended; I, J, K: Integer; B: BordersSet; begin for K := 0 to SubIterations-1 do begin for I := 0 to Length(Kugeln)-1 do Kugeln[I].Move;
for I := 0 to Length(Kugeln)-1 do for J := I+1 to Length(Kugeln)-1 do if Kugeln[I].CollidesWith(Kugeln[J]) then begin DX := Kugeln[j].X-Kugeln[i].X; DY := Kugeln[j].Y-Kugeln[i].Y; L := sqrt(sqr(DX)+sqr(DY)); M11 := DX/L; M12 := -DY/L; M21 := DY/L; M22 := DX/L;
Vp1 := Kugeln[i].Vx*M11+Kugeln[i].Vy*-M12; Vs1 := Kugeln[i].Vx*-M21+Kugeln[i].Vy*M22; Vp2 := Kugeln[j].Vx*M11+Kugeln[j].Vy*-M12; Vs2 := Kugeln[j].Vx*-M21+Kugeln[j].Vy*M22;
if Vp1-Vp2<0 then Continue; MTot := Kugeln[i].M+Kugeln[j].M; Vp1_ := (Kugeln[i].M-Kugeln[j].M)/MTot*Vp1+2*Kugeln[j].M/MTot*Vp2; Vp2_ := (Kugeln[j].M-Kugeln[i].M)/MTot*Vp2+2*Kugeln[i].M/MTot*Vp1;
Kugeln[i].Vx := Vp1_*M11+Vs1*M12; Kugeln[i].Vy := Vp1_*M21+Vs1*M22; Kugeln[j].Vx := Vp2_*M11+Vs2*M12; Kugeln[j].Vy := Vp2_*M21+Vs2*M22; end;
for I := 0 to Length(Kugeln)-1 do with Kugeln[I] do begin B := WallCollisions; if ((boLeft in B) and (Vx < 0)) or ((boRight in B) and (Vx > 0)) then Vx := -Vx; if ((boTop in B) and (Vy < 0)) or ((boBottom in B) and (Vy > 0)) then Vy := -Vy; end; end; for I := 0 to Length(Kugeln)-1 do Kugeln[I].Apply; end;
end. |