粒子模拟(重力和碰撞)错误

时间:2014-01-03 09:53:20

标签: simulation collision pascal gravity particles

1.粒子似乎有一个多余的y方向运动,但我没有为它们增加背景引力。

2.当粒子越来越近时,它们的移动速度似乎太快了(因为我不知道如何处理碰撞问题?)

我通过添加它所经历的相应力来计算位置,我怎么知道它们是否与其他相撞?例如:

  

第1阶段

     

particle1 [1,1]

     

particle2 [1,9]

     

第2阶段

     

particle1 [9,9]

     

particle2 [1,9]

如果我绘制属于每个粒子的路径图,我可以看到路径图是否与其他粒子截取,但路径截距不是100%意味着它们会发生碰撞,因为它们可以有不同的速度。

我试过调试,但却找不到出错的地方。

在版本0中,它们往往会失败(不是我的愿望)

在版本1中,它们往往会失败(我交换x y)(简化版)

这是bin和source的url(在pascal中):stack_exchange_particle_gravity_collision.zip

以下是版本0的源代码,以防您不想下载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.

抱歉格式不佳

1 个答案:

答案 0 :(得分:0)

  1. 如果要在距离太近时移除粒子,此线应该可以完成这项工作:

    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.