simple 2d verlet
Blitz3D Forums/Blitz3D Programming/simple 2d verlet
| ||
hopefully this isnt too much to ask, and ive seen all that great 3d verlet stuff from you lot... so i was hoping that you might be able to implement collisions in this for me? i really dont have a clue where to start. its taken from the article on gamasutra, and it seems to work ok... thanks Graphics 800,600,0,2 SetBuffer BackBuffer() Const TIMESTEP# = 0.05 Const ITERATIONS = 5 Type particle Field x#,y# Field oldx#,oldy# Field xvel#,yvel# Field xacc#,yacc# Field mass# End Type Type link Field p0.particle Field p1.particle Field length# End Type a.particle = particle(400-100,300-50) b.particle = particle(400-50,300+50) c.particle = particle(400+50,300+50) d.particle = particle(400+50,300-50) link a,b,100 link b,c,100 link c,d,100 link d,a,100 link a,c,Sqr(100^2 + 100^2) link b,d,Sqr(100^2 + 100^2) While Not KeyHit(1) Cls Verlet SatisfyConstraints RenderParticles RenderLinks ApplyGlobalAcc 0,10 If MouseDown(1) a\x = MouseX() a\y = MouseY() End If Flip Wend End Function Particle.particle(x#,y#,mass#=0.1) p.particle = New particle p\x = x p\y = y p\oldx = p\x p\oldy = p\y p\mass = mass Return p End Function Function Link.link(p0.particle,p1.particle,Length#=10) l.link = New link l\p0 = p0 l\p1 = p1 l\length = length Return l End Function Function ApplyGlobalAcc(x#,y#) For p.particle = Each particle p\xacc = x p\yacc = y Next End Function Function Verlet() For p.particle = Each particle tmpX# = p\x# tmpY# = p\y# p\x# = tmpX# + tmpX# - p\oldx# + p\xacc# * TIMESTEP# * TIMESTEP# p\y# = tmpY# + tmpY# - p\oldy# + p\yacc# * TIMESTEP# * TIMESTEP# p\oldx# = tmpX# p\oldy# = tmpY# Next End Function Function SatisfyConstraints() For j = 1 To ITERATIONS For p.particle = Each particle If p\x < 50 Then p\x = 50 If p\y < 50 Then p\y = 50 If p\x > 750 Then p\x = 750 If p\y > 550 Then p\y = 550 Next For l.link = Each link delX# = l\p1\x - l\p0\x delY# = l\p1\y - l\p0\y deltalength# = Sqr(delX * delX + delY * delY) diff# = (deltalength# - l\length#) / (deltalength# * (-l\p0\mass# + -l\p1\mass#)) l\p0\x# = l\p0\x# + delX# * -l\p0\mass# * diff# l\p0\y# = l\p0\y# + delY# * -l\p0\mass# * diff# l\p1\x# = l\p1\x# - delX# * -l\p1\mass# * diff# l\p1\y# = l\p1\y# - delY# * -l\p1\mass# * diff# Next Next End Function Function RenderParticles() For p.particle = Each particle Oval p\x-4,p\y-4,8,8 Next End Function Function RenderLinks() For l.link = Each link Line l\p0\x,l\p0\y,l\p1\x,l\p1\y Next End Function |
| ||
What kind of collisions are you looking for? line collisions are easy enough. circle collisions are REALLY easy. Also, as most of the time your gonna link to particles with a constraint with the restlength of the particles current distance, you might want to simplify the link function. As for 2d collisions, you'd probably want to talk to bouncer although he will tell you to use the 3d collisions. Which are in fact, faster even when your doing 2d, but You might want it strictly 2d anyway. |
| ||
Btw. I have not used 3D collisions... Wouldn't touch so slow stuff... I use VERY optimized OBBtrees and customized Sweep and prune algo thru x-axis. Soon to be even faster as I'm currently writing the collision code in asm / c++. If you are making 3D stuff... then it's the easiest and fastest to use blitzes stuff ... unless you want something faster, but then it's going to be pretty advanced at least in poly to poly level. But if you only want sphere to sphere precision eg. no object to scenery collisions, you can easily write your own optimized sphere to sphere routines which are fater than blitzes. If your doing 2D ... use circles as collision primitives. They're fast to calculate and pretty universal shapes. They are even used in very accurate collision modelling. Just have to use lot's of 'em :) |
| ||
Just re-read your topic... so you want 2d. Ok... basic circle to circle collisions: Every particle has to have radius then: // so then you basicly test (in pseudo): dx = particle1_x - particle2_x dy = particle1_y - particle2_y particle distance = sqr(dx*dx + dy*dy) normdist = particleradius1 + particleradius2 if particle distance < normdist then collision occurs // It's that simple // Then just move the particles so they are not // interpenetrating. // this also calculates the weights... so lighter particle will move more coldepth = (particle_distance - normdist) / particle_distance totalweight = p1weight + p2weight forcex = (dx*coldepth) / totalweight forcey = (dy*coldepth) / totalweight particle1x - (forcex * p2weight) particle1y - (forcey * p2weight) particle2x + (forcex * p1weight) particle2y + (forcey * p1weight) |
| ||
yay thanks bouncer, that works when the particles collide, but how about when a particle passes through a link? that shouldnt be allowed either, and if im thinking straight, then all i need is circle-line and circle-circle collisions (with reactions) and it should be solid? |
| ||
ahh. I was under the impresion that you used 3d cols cause there faster. I guess not. probably someone else. the circle- line thing is the bain of the current systems. It shouldn't be to hard in 2d, but It's pretty dang hard to get fast stuff in 3d. oh well. I don't have any code, but I'm guessing that the best way to do it is find the nearest point on a line(algorithm of some sort). Then find the distance from the sphere to the point. if the radius is greater than the distance then you need to correct for it the same way as you did the circles. The problem with this is that the line doesn't move. this can be solved, but it takes some maths I don't know yet. The Verlet article on Gamasutra("Advanced charachter physics") covers the problem of point-line. |