diff --git a/lazarus/gravity/project1.ico b/lazarus/gravity/project1.ico new file mode 100644 index 0000000..0341321 Binary files /dev/null and b/lazarus/gravity/project1.ico differ diff --git a/lazarus/gravity/project1.lpi b/lazarus/gravity/project1.lpi new file mode 100644 index 0000000..3afe492 --- /dev/null +++ b/lazarus/gravity/project1.lpi @@ -0,0 +1,79 @@ + + + + + + + + + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <Icon Value="0"/> + </General> + <i18n> + <EnableI18N LFM="False"/> + </i18n> + <VersionInfo> + <StringTable ProductVersion=""/> + </VersionInfo> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + </local> + </RunParams> + <RequiredPackages Count="1"> + <Item1> + <PackageName Value="LCL"/> + </Item1> + </RequiredPackages> + <Units Count="2"> + <Unit0> + <Filename Value="project1.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="unit1.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Form1"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Unit1"/> + </Unit1> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="project1"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/lazarus/gravity/project1.lpr b/lazarus/gravity/project1.lpr new file mode 100644 index 0000000..58c35dc --- /dev/null +++ b/lazarus/gravity/project1.lpr @@ -0,0 +1,21 @@ +program project1; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, Unit1 + { you can add units after this }; + +{$R *.res} + +begin + RequireDerivedFormResource:=True; + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/lazarus/gravity/project1.res b/lazarus/gravity/project1.res new file mode 100644 index 0000000..e994dfa Binary files /dev/null and b/lazarus/gravity/project1.res differ diff --git a/lazarus/gravity/unit1.lfm b/lazarus/gravity/unit1.lfm new file mode 100644 index 0000000..94b5a77 --- /dev/null +++ b/lazarus/gravity/unit1.lfm @@ -0,0 +1,16 @@ +object Form1: TForm1 + Left = 141 + Height = 523 + Top = 235 + Width = 823 + Caption = 'Form1' + OnCreate = FormCreate + OnPaint = FormPaint + LCLVersion = '1.6.2.0' + object Timer1: TTimer + Interval = 10 + OnTimer = Timer1Timer + left = 30 + top = 26 + end +end diff --git a/lazarus/gravity/unit1.pas b/lazarus/gravity/unit1.pas new file mode 100644 index 0000000..3f509c6 --- /dev/null +++ b/lazarus/gravity/unit1.pas @@ -0,0 +1,152 @@ +unit Unit1; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls; + +type + + { TForm1 } + + TForm1 = class(TForm) + Timer1: TTimer; + procedure FormCreate(Sender: TObject); + procedure FormPaint(Sender: TObject); + procedure Timer1Timer(Sender: TObject); + private + { private declarations } + public + { public declarations } + end; + + TBall = record + x, y, vx, vy, ax, ay, r, m: double; + end; + +const + ballsCount = 5; + g = 100; + +var + Form1: TForm1; + balls: array[0..ballsCount] of TBall; + ringX: double = 500; + ringY: double = 500; + +implementation + +uses Math; + +{$R *.lfm} + +function RingNormalize(a, ringSize: double): double; +begin + if ringSize = 0 then Result := a else + Result := a - ringSize*Floor(a/ringSize); +end; + +function RingDelta(a, b, ringSize: double): double; +begin + if ringSize = 0 then Result := a - b else begin + Result := RingNormalize(a - b, ringSize); + if Result > ringSize/2 then Result := Result - ringSize; + end; +end; + +{ TForm1 } + +procedure TForm1.FormCreate(Sender: TObject); +var + i: integer; + r: double; +begin + ringX := ClientWidth; + ringY := ClientHeight; + Randomize; + for i := 0 to ballsCount-1 do begin + r := 10 + 30*Random; + balls[i].x := ringX * Random; + balls[i].y := ringY * Random; + balls[i].vx := 0; + balls[i].vy := 0; + balls[i].r := r; + balls[i].m := r*r*r; + end; +end; + +procedure TForm1.FormPaint(Sender: TObject); +var + i, j, k: integer; + x, y, r: double; +begin + for i := 0 to ballsCount-1 do begin + r := balls[i].r; + for j := -1 to 1 do for k := -1 to 1 do begin + x := balls[i].x + ringX * j; + y := balls[i].y + ringY * k; + Canvas.Ellipse(round(x-r), round(y-r), round(x+r), round(y+r)); + end; + end; +end; + +procedure TForm1.Timer1Timer(Sender: TObject); +var + t, i, j: integer; + dx, dy, d, nx, ny, ax, ay, dt, dvx, dvy, dv + , v0, v1: double; +begin + dt := Timer1.Interval/1000/1000; + + for t := 1 to 1000 do begin + for i := 0 to ballsCount-1 do begin + balls[i].ax := 0; + balls[i].ay := 0; + end; + + for i := 0 to ballsCount-1 do begin + for j := i+1 to ballsCount-1 do begin + dx := RingDelta(balls[j].x, balls[i].x, ringX); + dy := RingDelta(balls[j].y, balls[i].y, ringY); + d := sqrt(dx*dx + dy*dy); + nx := dx / d; + ny := dy / d; + if d > balls[i].r + balls[j].r then begin + ax := g*balls[i].m*balls[j].m*nx/(d*d); + ay := g*balls[i].m*balls[j].m*ny/(d*d); + balls[i].ax := balls[i].ax + ax; + balls[i].ay := balls[i].ay + ay; + balls[j].ax := balls[j].ax - ax; + balls[j].ay := balls[j].ay - ay; + end else begin + dvx := balls[j].vx - balls[i].vx; + dvy := balls[j].vy - balls[i].vy; + dv := dvx*nx + dvy*ny; + if dv<0 then begin + v0 := 2*dv*balls[j].m/(balls[i].m + balls[j].m); + v1 := -2*dv*balls[i].m/(balls[i].m + balls[j].m); + balls[i].vx := balls[i].vx + v0*nx; + balls[i].vy := balls[i].vy + v0*ny; + balls[j].vx := balls[j].vx + v1*nx; + balls[j].vy := balls[j].vy + v1*ny; + end; + end; + end; + end; + + for i := 0 to ballsCount-1 do begin + balls[i].vx := balls[i].vx + balls[i].ax*dt/balls[i].m; + balls[i].vy := balls[i].vy + balls[i].ay*dt/balls[i].m; + balls[i].x := RingNormalize(balls[i].x + balls[i].vx*dt, ringX); + balls[i].y := RingNormalize(balls[i].y + balls[i].vy*dt, ringY); + end; + end; + + Refresh; +end; + + +end. +