
-----------------------------------
Homer_simpson
Thu Jan 01, 2009 9:04 pm

2d collisions physics simulation
-----------------------------------
i seem to have a problem with collision when balls are moving in the same general direction



View.Set ("offscreenonly,graphics:700;350")

function distance (x1, y1, x2, y2 : real) : real
    result sqrt (((x2 - x1) ** 2) + ((y2 - y1) ** 2)) %y

end distance
function findangle (x1, y1, x2, y2 : real) : real
    var ang, slope : real
    if not (x2 = x1) then
        slope := (y2 - y1) / (x2 - x1)
    else
        slope := 999999999
    end if
    ang := arctand (slope)
    if slope > 0 then
        if y2 < y1 then
            ang := 180 + ang
        end if
    end if
    if slope < 0 then
        if x2 < x1 then
            ang := 180 + ang
        end if
        if x2 > x1 then
            ang := 360 + ang
        end if
    end if
    if slope = 0 then
        if x2 > x1 then
            ang := 0
        end if
        if x2 < x1 then
            ang := 180
        end if
    end if
    result ang
end findangle
type Particle_Type :
    record
        x, y, vx, vy, w : real
        ch : boolean
    end record

const MaxParticles := 9

var Particles : array 1 .. MaxParticles of Particle_Type


procedure RenewParticle (var p : Particle_Type, x, y : real, a, r, w : real)
    p.x := x
    p.y := y
    p.vx := a
    p.vy := r
    p.w := w
    p.ch := false
end RenewParticle


for i : 1 .. MaxParticles
    RenewParticle (Particles (i), Rand.Int (1, 700), Rand.Int (0, 350), .4, .4, Rand.Int (10, 100))
end for
colorback (black)
cls

RenewParticle (Particles (1), 200, 100, .6, .3, Rand.Int (10, 100))
RenewParticle (Particles (2), 400, 200, .4, .2, Rand.Int (10, 100))
var chars : array char of boolean

color (white)
procedure collide (var particles1, particles2 : Particle_Type)
    var temp1, temp2, temp3, nvx1, nvy1, nvx2, nvy2, magnitude, dirx, diry, mag1, mag2 : real
    dirx := - (abs (particles2.vx) / particles2.vx) * (abs (particles1.vx) / particles1.vx)
    diry := - (abs (particles2.vy) / particles2.vy) * (abs (particles1.vy) / particles1.vy)
    mag1 := distance (0, 0, particles1.vx, particles1.vy)
    mag2 := distance (0, 0, particles2.vx, particles2.vy)

    locate (1, 1)
    temp1 := findangle (particles1.x, particles1.y, particles2.x, particles2.y)

    temp2 := findangle (0, 0, particles2.vx, particles2.vy) - temp1
    temp3 := findangle (0, 0, particles1.vx, particles1.vy) - temp1
    put temp1
    put temp2 + temp1
    put temp3 + temp1
    temp2 := findangle (0, 0, cosd (temp2), -sind (temp2)) + temp1
    temp3 := findangle (0, 0, cosd (temp3), -sind (temp3)) + temp1
    put "-----------"
    put temp2
    put temp3

    %put "collision angle = ", temp1
    %put "Vellocity angle = ", temp2
    %put "relative angle  = ", temp2 - temp1
    %put "------------"

    nvx1 := cosd (temp2) %* distance (0, 0, particles1.vx, particles1.vy)
    nvy1 := sind (temp2) %* distance (0, 0, particles1.vx, particles1.vy)

    nvx2 := cosd (temp3) %* distance (0, 0, particles2.vx, particles2.vy)
    nvy2 := sind (temp3) %* distance (0, 0, particles2.vx, particles2.vy)


    /*drawline (round (particles1.x), round (particles1.y), round (particles2.x), round (particles2.y), red)

     drawline (round (particles2.x), round (particles2.y), round (particles2.x) + round (particles2.vx * 4), round (particles2.y) + round (particles2.vy * 4),
     yellow)
     drawline (round (particles2.x), round (particles2.y), round (particles2.x) + round (cosd (temp3) * magnitude * 4), round (particles2.y) + round (sind (temp3) *
     magnitude * 4),
     11)

     drawline (0, round (particles2.y), 700, round (particles2.y), green)%*/
    %col := true
    drawline (round (particles1.x), round (particles1.y), round (particles1.x + (particles1.vx * 90)), round (particles1.y + (particles1.vy * 90)), white)
    drawline (round (particles2.x), round (particles2.y), round (particles2.x + (particles2.vx * 90)), round (particles2.y + (particles2.vy * 90)), white)

    particles2.vx := -nvx1 * dirx * mag1
    particles2.vy := -nvy1 * diry * mag1

    particles1.vx := -nvx2 * mag2
    particles1.vy := -nvy2 * mag2

    particles1.x += particles1.vx * 4
    particles1.y += particles1.vy * 4
    particles2.x += particles2.vx * 4
    particles2.y += particles2.vy * 4

    drawline (round (particles1.x), round (particles1.y), round (particles1.x + (particles1.vx * 90)), round (particles1.y + (particles1.vy * 90)), yellow)
    drawline (round (particles2.x), round (particles2.y), round (particles2.x + (particles2.vx * 90)), round (particles2.y + (particles2.vy * 90)), yellow)
    View.Update
    %delay (300)

    %particles1.ch := true
    %particles2.ch := true
end collide

loop
    Input.KeyDown (chars)
    if chars ('+') then
    end if

    for i : 1 .. MaxParticles


        Particles (i).x += Particles (i).vx
        Particles (i).y += Particles (i).vy

        drawfilloval (round (Particles (i).x), round (Particles (i).y), 10, 10, 30 + i)

        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%ball collision%%%%%%%%%%%%%%%%%%%%%%%%
        for ii : 1 .. MaxParticles
            if distance (Particles (i).x, Particles (i).y, Particles (ii).x, Particles (ii).y) = 690 and Particles (i).vx > 0 then
            Particles (i).vx := -Particles (i).vx
        end if
        if Particles (i).x = 340 and Particles (i).vy > 0 then
            Particles (i).vy := -Particles (i).vy
        end if
        if Particles (i).y 