Ошибка симуляции частиц (гравитация и столкновение)

1. Кажется, что частицы имеют избыточное движение по оси Y, но я не добавил для них фоновую гравитацию.

2. Кажется, что частицы движутся слишком быстро, когда они все ближе и ближе (потому что я не знаю, как справиться с проблемой столкновения?)

Я рассчитываю местоположение, добавляя соответствующую силу, которую он испытал, как я могу узнать, столкнулись ли они с другими? например:

этап 1

частица1 [1,1]

частица2 [1,9]

этап 2

частица1 [9,9]

частица2 [1,9]

Если я построю график пути, принадлежащего каждой частице, я смогу увидеть, пересекается ли график путей с другими, но перехват пути не на 100% означает, что они столкнутся, поскольку они могут иметь разную скорость.

Я пытался отладить, но просто не могу узнать, где идет не так.

в версии 0 они, как правило, терпят неудачу (не мое желание)

в версии 1 они имеют тенденцию терпеть неудачу вправо (я обмениваю xy) (упрощенная версия)

Вот URL-адрес корзины и источника (на паскале): https://www.dropbox.com/s/9bfyh3urc88w7yj/stack_exchange_particle_gravity_collision.zip?dl=0

Вот исходный код версии 0 на тот случай, если вы не хотите загружать zip-архив:

    программа ParticlesV0;

    использования
      граф;

    Const
      р = +3,14159265358979;
      п =500;
      defaultSpeed ​​=1;
      defaultRadius=2;
      defaultDensity=1E4;
      energyLoss=0,50;
      dotStyle=1;
      backGroundLevel=0;

    тип
      ParticleType= запись
        х, у, д-р, дд, дй, д, DFR, DFD: реальный;
        цвет: слово;
        радиус, масса: реальный;
      конец;

    вар
      Г.Д., г: SMALLINT;
      PathToDriver: строка;
      л: LONGINT;
      частица: массив [1..n] ParticleType;

    ////////////////////////////////////////////////////////////////

    процедура backGround(я:smallint);
    вар
      у: SMALLINT;
      S, T: строка;
      ж, Ori: слово;
    начать
      Ori: = GetColor;
      SetColor(10);
      пока я>0 начинаю
        для y:=0 до (GetMaxY div 10) начинаются
          с:='';
          для w:= от 0 до 255 начинаются
            ул (случайный (10), т);
            S: = S + T;
          конец;
        OutTextXY(5, у *10, с);
        конец;
        Декабрь (я);
      конец;
      SetColor(Ori);
    конец;

    строка процедуры (x1,y1,x2,y2:smallint);
    вар
      х, у: SMALLINT;
    начать
      х: = GetX;
      у: = GetY;
      MoveTo (x1, y1);
      LineTo (х2, у2);
      MoveTo (х, у);
    конец;

    функция rx (x: real): real;
    начать
      rx:=x+(GetMaxX div 2);
    конец;
    функция ry (у: реальная): реальная;
    начать
      ry:=y+(GetMaxY div 2);
    конец;
    функция s (r: реальная):smallint;
    начать
      с: = круглый (г);
    конец;

    расстояние функции (p1,p2:ParticleType): действительное;
    вар
      х, у: реальные;
    начать
      х:=p1.x-p2.x;
      Y:=p1.y-p2.y;
      Расстояние: = SQRT (х * х + у * у);
    конец;

    степень функции (p1,p2:ParticleType): действительная;
    вар
      х, у, д: реальные;
    начать
      х:=p2.x-p1.x;
      Y:=p2.y-p1.y;
      если x0, то d: = arctan (y / x)
      иначе if (yGetMaxX) тогда начните
          дх:=- дх;
          х:=GetMaxX-(х-GetMaxX);
        конец;
         if (xGetMaxY) тогда начинайте
          д:=- д;
          у:=GetMaxY-(у-GetMaxY);
        конец;
        если (у0) то начинай
          TFR:=G* * p.mass частиц [л].mass/ кв (г);
          TFD: = степени (р, частица [л]);
          TDX: = TFR * сов (TFD);
          TDY: = TFR *sin(TFD);
          дх: дх = + TDX;
          д: = д + TDY;
    // tdx: =
        конец;
        p.dx:=p.dx+ дх;
        p.dy:=p.dy+ ду;
      конец;

    конец;
    // ++++++++++++++++++++++++++++++ //

    ////////////////////////////////////////////////// //////////////

    начать
      Г.Д.: = обнаружить; {максимально возможное разрешение}
      г:=0; {не требуется, автоопределение}
      PathToDriver:=' '; {путь к BGI-шрифтам, драйверы не нужны}
      InitGraph(Г.Д., г,PathToDriver);
      if (GraphResult=grok) тогда начинайте

        Writeln ("Б-г", Б-г);
        writeln('GetMaxX ',GetMaxX);
        writeln('GetMaxY ',GetMaxY);
        writeln('GetMaxColor ',GetMaxColor);

        ПРЕДПОСЫЛКИ (backGroundLevel);
        строка (0, 0, GetMaxX, GetMaxY);
        SetFillStyle(HatchFill,13);
        FillEllipse(ы (гх (0)), с (гу (0)),10,10);

        для l: = 1 до n сделать initp (частица [l]);
        повторение
          для l: = 1 до n начинаются
            Calp (частица [л]);
            MOVEP (частица [л]);
          конец;
        до ложного;

        ReadLn;
        CloseGraph; {восстанавливает старый графический режим}
      end else writeln('Графика не поддерживается.');
      ReadLn;
    конец.

извините за плохое форматирование

1 ответ

  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.

Другие вопросы по тегам