Blame lazarus/gravity/unit1.pas

Ivan Mahonin 1beac4
unit Unit1;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
{$mode objfpc}{$H+}
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
interface
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
uses
Ivan Mahonin 1beac4
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
type
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  { TForm1 }
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  TForm1 = class(TForm)
Ivan Mahonin 1beac4
    Timer1: TTimer;
Ivan Mahonin 1beac4
    procedure FormCreate(Sender: TObject);
Ivan Mahonin 1beac4
    procedure FormPaint(Sender: TObject);
Ivan Mahonin 1beac4
    procedure Timer1Timer(Sender: TObject);
Ivan Mahonin 1beac4
  private
Ivan Mahonin 1beac4
    { private declarations }
Ivan Mahonin 1beac4
  public
Ivan Mahonin 1beac4
    { public declarations }
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  TBall = record
Ivan Mahonin 1beac4
    x, y, vx, vy, ax, ay, r, m: double;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
const
Ivan Mahonin 1beac4
  ballsCount = 5;
Ivan Mahonin 1beac4
  g = 100;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
var
Ivan Mahonin 1beac4
  Form1: TForm1;
Ivan Mahonin 1beac4
  balls: array[0..ballsCount] of TBall;
Ivan Mahonin 1beac4
  ringX: double = 500;
Ivan Mahonin 1beac4
  ringY: double = 500;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
implementation
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
uses Math;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
{$R *.lfm}
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
function RingNormalize(a, ringSize: double): double;
Ivan Mahonin 1beac4
begin
Ivan Mahonin 1beac4
  if ringSize = 0 then Result := a else
Ivan Mahonin 1beac4
    Result := a - ringSize*Floor(a/ringSize);
Ivan Mahonin 1beac4
end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
function RingDelta(a, b, ringSize: double): double;
Ivan Mahonin 1beac4
begin
Ivan Mahonin 1beac4
  if ringSize = 0 then Result := a - b else begin
Ivan Mahonin 1beac4
    Result := RingNormalize(a - b, ringSize);
Ivan Mahonin 1beac4
    if Result > ringSize/2 then Result := Result - ringSize;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
{ TForm1 }
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
procedure TForm1.FormCreate(Sender: TObject);
Ivan Mahonin 1beac4
var
Ivan Mahonin 1beac4
  i: integer;
Ivan Mahonin 1beac4
  r: double;
Ivan Mahonin 1beac4
begin
Ivan Mahonin 1beac4
  ringX := ClientWidth;
Ivan Mahonin 1beac4
  ringY := ClientHeight;
Ivan Mahonin 1beac4
  Randomize;
Ivan Mahonin 1beac4
  for i := 0 to ballsCount-1 do begin
Ivan Mahonin 1beac4
    r := 10 + 30*Random;
Ivan Mahonin 1beac4
    balls[i].x := ringX * Random;
Ivan Mahonin 1beac4
    balls[i].y := ringY * Random;
Ivan Mahonin 1beac4
    balls[i].vx := 0;
Ivan Mahonin 1beac4
    balls[i].vy := 0;
Ivan Mahonin 1beac4
    balls[i].r := r;
Ivan Mahonin 1beac4
    balls[i].m := r*r*r;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
procedure TForm1.FormPaint(Sender: TObject);
Ivan Mahonin 1beac4
var
Ivan Mahonin 1beac4
  i, j, k: integer;
Ivan Mahonin 1beac4
  x, y, r: double;
Ivan Mahonin 1beac4
begin
Ivan Mahonin 1beac4
  for i := 0 to ballsCount-1 do begin
Ivan Mahonin 1beac4
    r := balls[i].r;
Ivan Mahonin 1beac4
    for j := -1 to 1 do for k := -1 to 1 do begin
Ivan Mahonin 1beac4
      x := balls[i].x + ringX * j;
Ivan Mahonin 1beac4
      y := balls[i].y + ringY * k;
Ivan Mahonin 1beac4
      Canvas.Ellipse(round(x-r), round(y-r), round(x+r), round(y+r));
Ivan Mahonin 1beac4
    end;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
procedure TForm1.Timer1Timer(Sender: TObject);
Ivan Mahonin 1beac4
var
Ivan Mahonin 1beac4
  t, i, j: integer;
Ivan Mahonin 1beac4
  dx, dy, d, nx, ny, ax, ay, dt, dvx, dvy, dv
Ivan Mahonin 1beac4
  , v0, v1: double;
Ivan Mahonin 1beac4
begin
Ivan Mahonin 1beac4
  dt := Timer1.Interval/1000/1000;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  for t := 1 to 1000 do begin
Ivan Mahonin 1beac4
  for i := 0 to ballsCount-1 do begin
Ivan Mahonin 1beac4
    balls[i].ax := 0;
Ivan Mahonin 1beac4
    balls[i].ay := 0;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  for i := 0 to ballsCount-1 do begin
Ivan Mahonin 1beac4
    for j := i+1 to ballsCount-1 do begin
Ivan Mahonin 1beac4
      dx := RingDelta(balls[j].x, balls[i].x, ringX);
Ivan Mahonin 1beac4
      dy := RingDelta(balls[j].y, balls[i].y, ringY);
Ivan Mahonin 1beac4
      d := sqrt(dx*dx + dy*dy);
Ivan Mahonin 1beac4
      nx := dx / d;
Ivan Mahonin 1beac4
      ny := dy / d;
Ivan Mahonin 1beac4
      if d > balls[i].r + balls[j].r then begin
Ivan Mahonin 1beac4
        ax := g*balls[i].m*balls[j].m*nx/(d*d);
Ivan Mahonin 1beac4
        ay := g*balls[i].m*balls[j].m*ny/(d*d);
Ivan Mahonin 1beac4
        balls[i].ax := balls[i].ax + ax;
Ivan Mahonin 1beac4
        balls[i].ay := balls[i].ay + ay;
Ivan Mahonin 1beac4
        balls[j].ax := balls[j].ax - ax;
Ivan Mahonin 1beac4
        balls[j].ay := balls[j].ay - ay;
Ivan Mahonin 1beac4
      end else begin
Ivan Mahonin 1beac4
        dvx := balls[j].vx - balls[i].vx;
Ivan Mahonin 1beac4
        dvy := balls[j].vy - balls[i].vy;
Ivan Mahonin 1beac4
        dv := dvx*nx + dvy*ny;
Ivan Mahonin 1beac4
        if dv<0 then begin
Ivan Mahonin 1beac4
          v0 :=  2*dv*balls[j].m/(balls[i].m + balls[j].m);
Ivan Mahonin 1beac4
          v1 := -2*dv*balls[i].m/(balls[i].m + balls[j].m);
Ivan Mahonin 1beac4
          balls[i].vx := balls[i].vx + v0*nx;
Ivan Mahonin 1beac4
          balls[i].vy := balls[i].vy + v0*ny;
Ivan Mahonin 1beac4
          balls[j].vx := balls[j].vx + v1*nx;
Ivan Mahonin 1beac4
          balls[j].vy := balls[j].vy + v1*ny;
Ivan Mahonin 1beac4
        end;
Ivan Mahonin 1beac4
      end;
Ivan Mahonin 1beac4
    end;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  for i := 0 to ballsCount-1 do begin
Ivan Mahonin 1beac4
    balls[i].vx := balls[i].vx + balls[i].ax*dt/balls[i].m;
Ivan Mahonin 1beac4
    balls[i].vy := balls[i].vy + balls[i].ay*dt/balls[i].m;
Ivan Mahonin 1beac4
    balls[i].x := RingNormalize(balls[i].x + balls[i].vx*dt, ringX);
Ivan Mahonin 1beac4
    balls[i].y := RingNormalize(balls[i].y + balls[i].vy*dt, ringY);
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
  end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
  Refresh;
Ivan Mahonin 1beac4
end;
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
Ivan Mahonin 1beac4
end.
Ivan Mahonin 1beac4