1
votes

1.The particles seems to have an excess y-direction movement, but i didn't add a background gravity for them.

2.The particles seems to move too fast when they're getting closer and closer, (because I don't know how to handle the issue of collision?)

I calculate the location by adding the corresponding force it experienced , how can i know if they collided with other? for example:

stage 1

particle1 [1,1]

particle2 [1,9]

stage 2

particle1 [9,9]

particle2 [1,9]

If I plot a graph of the path belonging to each particle, I can see if the graph of paths intercept with other, but the path intercept doesn't 100% means they'll collide, as they can have different speed.

I've tried to debug but just cannot find out where is going wrong.

in version 0 they tend to fail down (not my wish)

in version 1 they tend to fail to the right (i swap the x y) (simplified version)

here is the url of the bin and source (in pascal): stack_exchange_particle_gravity_collision.zip

here is the source code of version 0 in case you do not want to download the zip:

    program ParticlesV0;
    
    uses
      graph;
    
    const
      pi=3.14159265358979;
      n=500;
      defaultSpeed=1;
      defaultRadius=2;
      defaultDensity=1e4;
      energyLoss=0.50;
      dotStyle=1;
      backGroundLevel=0;
    
    type
      ParticleType=record
        x,y,dr,dd,dx,dy,dfr,dfd:real;
        color:word;
        radius,mass:real;
      end;
    
    var
      gd,gm:smallint;
      PathToDriver:string;
      l:longint;
      particle:array[1..n]of ParticleType;
    
    ////////////////////////////////////////////////////////////////
    
    procedure backGround(i:smallint);
    var
      y:smallint;
      s,t:string;
      w,ori:word;
    begin
      ori:=GetColor;
      SetColor(10);
      while i>0 do begin
        for y:=0 to (GetMaxY div 10) do begin
          s:='';
          for w:=0 to 255 do begin
            str(random(10),t);
            s:=s+t;
          end;
        OutTextXY(5,y*10,s);
        end;
        dec(i);
      end;
      SetColor(ori);
    end;
    
    procedure line(x1,y1,x2,y2:smallint);
    var
      x,y:smallint;
    begin
      x:=getx;
      y:=gety;
      moveto(x1,y1);
      lineto(x2,y2);
      moveto(x,y);
    end;
    
    function rx(x:real):real;
    begin
      rx:=x+(GetMaxX div 2);
    end;
    function ry(y:real):real;
    begin
      ry:=y+(GetMaxY div 2);
    end;
    function s(r:real):smallint;
    begin
      s:=round(r);
    end;
    
    function distance(p1,p2:ParticleType):real;
    var
      x,y:real;
    begin
      x:=p1.x-p2.x;
      y:=p1.y-p2.y;
      distance:=sqrt(x*x+y*y);
    end;
    
    function degree(p1,p2:ParticleType):real;
    var
      x,y,d:real;
    begin
      x:=p2.x-p1.x;
      y:=p2.y-p1.y;
      if x0 then d:=arctan(y/x)
      else if (yGetMaxX) then begin
          dx:=-dx;
          x:=GetMaxX-(x-GetMaxX);
        end;
         if (xGetMaxY) then begin
          dy:=-dy;
          y:=GetMaxY-(y-GetMaxY);
        end;
        if (y0) then begin
          tfr:=G*p.mass*particle[l].mass/sqr(r);
          tfd:=degree(p,particle[l]);
          tdx:=tfr*cos(tfd);
          tdy:=tfr*sin(tfd);
          dx:=dx+tdx;
          dy:=dy+tdy;
    //      tdx:=
        end;
        p.dx:=p.dx+dx;
        p.dy:=p.dy+dy;
      end;
    
    end;
    //++++++++++++++++++++++++++++++//
    
    ////////////////////////////////////////////////////////////////
    
    begin
      gd:=detect; { highest possible resolution }
      gm:=0; { not needed, auto detection }
      PathToDriver:=' '; { path to BGI fonts, drivers aren't needed }
      InitGraph(gd,gm,PathToDriver);
      if (GraphResult=grok) then begin
    
        writeln('gd ',gd);
        writeln('GetMaxX ',GetMaxX);
        writeln('GetMaxY ',GetMaxY);
        writeln('GetMaxColor ',GetMaxColor);
    
        backGround(backGroundLevel);
        line(0, 0, GetMaxX, GetMaxY);
        SetFillStyle(HatchFill,13);
        FillEllipse(s(rx(0)),s(ry(0)),10,10);
    
        for l:=1 to n do initp(particle[l]);
        repeat
          for l:=1 to n do begin
            calp(particle[l]);
            movep(particle[l]);
          end;
        until false;
    
        readln;
        CloseGraph; { restores the old graphics mode }
      end else writeln('Graphic not supported.');
      readln;
    end.
    

sorry for the poor formatting

1
I discussed this with my lecturer and he suggested to use vector(maths) rather then degree(maths). It seems I token all 0-deg as 180-deg.Beeno Tung

1 Answers

0
votes
  1. If you want to remove a particle when it get too close, this line should do the job:

    procedure calp(var p:ParticleType); ... e:=*put a number here witch scales with mass or something esle, you can even use defaultradius constant*; if (r>e) then begin ... else mass:=0 <- this now means it won't pull others particles, and won't be pulled either, ideally now you need to check everywhere for 0-os, alternatively you can place the particle randomly on the screen again, but it can cause some funny stuff, becouse of leftover vectors.