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.
抱歉格式不佳
答案 0 :(得分:0)
如果要在距离太近时移除粒子,此线应该可以完成这项工作:
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.