Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Circle-line collision
#11
[Image: b7tjT.jpg]

It's been 2 years since Marcus introduced this polygon - circle line collision, and it still has me wondering. I keep staring at it, trying to figure out what it's actually supposed to be. It's probably just a quick test model again  
Big Grin Big Grin Big Grin

Code:
#win32
set window "Collision", 640, 480
set redraw off

'Vertices
v  = []
v.square    = [-50, -50, 50, -50, 50, 50, -50, 50]
v.star      = [0, -100, 25, -25, 100, 0, 25, 25, 0, 100, -25, 25, -100, 0, -25, -25]
v.rectangle = [0, 0, 129, 0, 129, 31, 0, 31]
v.tmp1      = [0, 0, 200, 0, 200, 31, 0, 31]
v.tmp2      = [0, 0, 31, 0, 31, 415, 0, 415]
v.cross = [-19,-59, -19,-19, -59,-19, -59,20, -19,20, -19,60, 20,60, 20,20, 60,20, 60,-19, 20,-19, 20,-59]

visible lines = []
filledPolys = []

'             MakePoly(verts,       x, y,       r, g, b,        lines, renderList)
square      = MakePoly(v.square,    320, 240, 255, 100, 100,    lines, filledPolys)
star        = MakePoly(v.star,      425, 100, 100, 255, 100,    lines, filledPolys)
cross       = MakePoly(v.cross,     175, 125, 100, 100, 255,     lines, filledPolys)
rectangle   = MakePoly(v.rectangle, 110, 300, 100, 255, 255,    lines, filledPolys)
rectangle2  = MakePoly(v.rectangle, 425, 300, 100, 255, 255,    lines, filledPolys)
tmp1        = MakePoly(v.tmp1,       50, 416, 255, 100, 255,    lines, filledPolys)
tmp2        = MakePoly(v.tmp2,       32,  32, 255, 100, 255,    lines, filledPolys)

'Balls
visible objs = []
ballCount = 0
objs[ballCount] = Object(rnd(0,width()), 0, 16)


'-----------
' Main Loop
'-----------
while not keydown(KEY_ESCAPE, true)
    ' Clear screen 
    set color 0, 0, 0; cls

    ' Draw grid
    set color 64, 64, 64
    for gx = 0 to 640 step 64  draw line gx, 0, gx, 480 
    for gy = 0 to 480 step 64  draw line 0, gy, 640, gy 

    ' Rotate obstacles: + = clockwise, - = counter-clockwise
    square.SetAngle(square.Angle() + rad(0.5))
    star.SetAngle(star.Angle() + rad(0.25))
    cross.SetAngle(cross.Angle() - rad(0.5))
    rectangle.SetAngle(rectangle.Angle() - rad(0.25))
    rectangle2.SetAngle(rectangle2.Angle() + rad(0.25))
   
    ' draw obstacles
    foreach polygn in filledPolys  polygn.DrawFilled()

    ' coordinate labels, infobox
    set color 255, 255, 255
    shapes = [square,star,cross,rectangle,rectangle2,tmp1,tmp2]
    for i = 0 to sizeof(shapes)-1   
        DrawCoordLabel(shapes[i])
    next
    set caret width()/2+100, height()-50; center "Press ENTER for more balls"

    ' balls
    foreach ball in objs
        UpdateObject(ball)
        DrawObject(ball)
    next
   
    i = 0
    while i < ballCount - 1
        j = i + 1
        while j < ballCount
            ResolveBallCollision(objs[i], objs[j])
            j = j + 1
        wend
        i = i + 1
    wend
   
    'Drop ball
    if keydown(KEY_RETURN,true) then
        objs[ballCount] = Object(rnd(0,width()), 0, 16)
        ballCount = ballCount + 1
    endif

    redraw
    fwait 60
wend


'------------
' Functions
'------------
function Object(x, y, r)
    return [x: x, y: y, r: r, rsqr: r*r, dx: 0, dy: 0, pdx: 0, pdy: 0]
endfunc

' Draw ball
function DrawObject(obj)
    set color 255, 255, 0
    draw ellipse obj.x, obj.y, obj.r, obj.r, true
endfunc

' Update ball
function UpdateObject(obj)
    obj.dy = obj.dy + 0.1
    if obj.dy > 6 then obj.dy = 6
   
    ' Update position
    obj.x = obj.x + obj.dx
    obj.y = obj.y + obj.dy
   
    ' Collision detection
    PushOut(obj, lines)
endfunc

' ResolveBallCollision
function ResolveBallCollision(b1, b2)
    dx = b2.x - b1.x; dy = b2.y - b1.y
    distSq = dx*dx + dy*dy
    minDist = b1.r + b2.r
    minDistSq = minDist * minDist
   
    ' Early exit if no collision or zero distance
    if distSq >= minDistSq or distSq = 0 then return
   
    dist = sqr(distSq)
           
    ' push apart
    overlap = minDist - dist
    b1.x = b1.x -  overlap; b1.y = b1.y -  overlap
    b2.x = b2.x +  overlap; b2.y = b2.y +  overlap 
endfunc

' PushOut: collision resolution
function PushOut(obj, lines)
    for i = 1 to 4
        col = false
        foreach ln in lines
            dp = max(0, min(ln[6], (obj.x - ln[0])*ln[4] + (obj.y - ln[1])*ln[5]))
            px = ln[0] + dp*ln[4]; py = ln[1] + dp*ln[5]
            dx = obj.x - px; dy = obj.y - py
            d = dx*dx + dy*dy
           
            if d < obj.rsqr
                k = 1/sqr(d)
               
                obj.x = px + dx*k*obj.r
                obj.y = py + dy*k*obj.r
               
                obj.dx = obj.dx + 0.5 * dx*k
                obj.dy = obj.dy + 0.5 * dy*k
                col = true
            endif
        next
        if not col break
    next
endfunc

' Polygon
function Polygon(points, x, y, r, g, b)
    p = [trans: unset, org: [], verts: [], x: x, y: y, a: 0, cx: 0, cy: 0, r: r, g: g, b: b]
    pcount = sizeof(points)/2
   
    ' Store original vertices
    for i = 0 to pcount - 1
        p.verts[sizeof(p.verts)] = points[i*2]
        p.verts[sizeof(p.verts)] = points[i*2 + 1]
    next
   
    ' collision lines
    n = pcount - 1
   
    for i = 0 to n
        j = (i + 1)%pcount
        p.org[sizeof(p.org)] = Line(
                points[i*2], points[i*2 + 1],
                points[j*2], points[j*2 + 1])
    next
   
    for i = 0 to pcount - 1
        p.cx = p.cx + points[i*2]; p.cy = p.cy + points[i*2 + 1]
    next
    p.cx = p.cx/pcount; p.cy = p.cy/pcount
    p.trans = copy(p.org)
   
    p.AddTo = function(lines)
        foreach ln in .trans  lines[sizeof(lines)] = ln
    endfunc

    p.X = function(); return .x ;endfunc
    p.Y = function(); return .y ;endfunc
    p.Angle = function(); return .a ;endfunc
   
    p.SetTransform = function(x, y, angle)
        .x = x; .y = y; .a = angle; .Transform()
    endfunc
    p.SetPosition = function(x, y)
        .x = x; .y = y; .Transform()
    endfunc
    p.SetAngle = function(angle)
        .a = angle; .Transform()
    endfunc
   
    p.Transform = function()
        RotateLines(.org, .trans, .cx, .cy, .a)
        foreach ln in .trans
            ln[0] = ln[0] + .x; ln[1] = ln[1] + .y
            ln[2] = ln[2] + .x; ln[3] = ln[3] + .y
            ln[4] = (ln[2] - ln[0])/ln[6]; ln[5] = (ln[3] - ln[1])/ln[6]
        next
    endfunc
   
    p.DrawFilled = function()
        set color .r, .g, .b
        vcount = sizeof(.verts)/2
        polyArgs = []
        for i = 0 to vcount - 1
            vx = .verts[i*2] - .cx; vy = .verts[i*2 + 1] - .cy
            ' Apply rotation
            rx = vx*cos(.a) - vy*sin(.a)
            ry = vx*sin(.a) + vy*cos(.a)
            polyArgs[sizeof(polyArgs)] = rx + .cx + .x
            polyArgs[sizeof(polyArgs)] = ry + .cy + .y
        next
        draw poly polyArgs, true
    endfunc
   
    p.Transform()
    return p
   
    function RotateLines(srcLines, dstLines, aroundX, aroundY, angle)
        c = cos(angle); s = sin(angle)
        for i = 0 to sizeof(srcLines) - 1
            srcLn = srcLines[i]; dstLn = dstLines[i]
            x = srcLn[0] - aroundX; y = srcLn[1] - aroundY
            dstLn[0] = aroundX + x*c - y*s; dstLn[1] = aroundY + y*c + x*s
            x = srcLn[2] - aroundX; y = srcLn[3] - aroundY
            dstLn[2] = aroundX + x*c - y*s; dstLn[3] = aroundY + y*c + x*s
        next
    endfunc   
endfunc

function Line(x0, y0, x1, y1)
    ln = [x0, y0, x1, y1]
    dx = ln[2] - ln[0]; dy = ln[3] - ln[1]
    ln[6] = sqr(dx*dx + dy*dy)
    ln[4] = dx/ln[6]
    ln[5] = dy/ln[6]
    return ln
endfunc

function MakePoly(verts, x, y, r, g, b, lines, renderList)
    p = Polygon(verts, x, y, r, g, b)
    p.AddTo(lines)
    renderList[sizeof(renderList)] = p
    return p
endfunc

function DrawCoordLabel(p)
    set caret p.X(), p.Y()
    wln "X"
    wln (int(p.X())) + "," + (int(p.Y()))
endfunc
Reply


Messages In This Thread
Circle-line collision - by Marcus - 04-16-2024, 03:59 PM
RE: Circle-line collision - by kevin - 04-16-2024, 05:30 PM
RE: Circle-line collision - by Marcus - 04-16-2024, 06:40 PM
RE: Circle-line collision - by johnno56 - 04-16-2024, 07:09 PM
RE: Circle-line collision - by 1micha.elok - 04-17-2024, 04:17 AM
RE: Circle-line collision - by johnno56 - 04-17-2024, 07:01 AM
RE: Circle-line collision - by Marcus - 04-17-2024, 09:24 AM
RE: Circle-line collision - by johnno56 - 04-17-2024, 09:37 AM
RE: Circle-line collision - by Marcus - 04-18-2024, 04:03 PM
RE: Circle-line collision - by 1micha.elok - 04-19-2024, 02:12 AM
RE: Circle-line collision - by 1micha.elok - 05-16-2026, 11:01 AM
RE: Circle-line collision - by kevin - 05-16-2026, 01:59 PM
RE: Circle-line collision - by 1micha.elok - 05-17-2026, 02:16 AM
RE: Circle-line collision - by Marcus - 05-16-2026, 03:59 PM
RE: Circle-line collision - by johnno56 - 05-17-2026, 03:41 AM
RE: Circle-line collision - by kevin - 05-17-2026, 10:20 AM
RE: Circle-line collision - by 1micha.elok - 05-18-2026, 03:51 AM
RE: Circle-line collision - by kevin - 05-18-2026, 09:22 AM
RE: Circle-line collision - by kevin - 05-18-2026, 07:49 AM
RE: Circle-line collision - by kevin - 05-18-2026, 11:20 AM
RE: Circle-line collision - by 1micha.elok - 05-18-2026, 11:25 AM
RE: Circle-line collision - by kevin - 05-18-2026, 11:50 AM
RE: Circle-line collision - by 1micha.elok - 05-19-2026, 09:12 AM
RE: Circle-line collision - by kevin - 05-19-2026, 12:43 PM
RE: Circle-line collision - by kevin - 05-20-2026, 08:17 AM
RE: Circle-line collision - by 1micha.elok - 05-20-2026, 08:22 AM
RE: Circle-line collision - by kevin - 05-20-2026, 09:31 AM
RE: Circle-line collision - by kevin - 05-20-2026, 12:23 PM
RE: Circle-line collision - by kevin - 05-20-2026, 04:35 PM
RE: Circle-line collision - by 1micha.elok - 05-22-2026, 08:18 AM
RE: Circle-line collision - by 1micha.elok - 05-20-2026, 10:36 PM
RE: Circle-line collision - by Marcus - 05-21-2026, 04:31 PM
RE: Circle-line collision - by johnno56 - 05-22-2026, 10:25 AM
RE: Circle-line collision - by kevin - 05-23-2026, 07:58 AM
RE: Circle-line collision - by Marcus - 05-23-2026, 08:15 AM
RE: Circle-line collision - by johnno56 - 05-23-2026, 09:58 AM
RE: Circle-line collision - by 1micha.elok - 05-24-2026, 04:57 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)