Ошибка симуляции частиц (гравитация и столкновение)
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 ответ
Если вы хотите удалить частицу, когда она окажется слишком близко, эта строка должна выполнить работу:
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.