Coldet - Functions for collision detection

TheMrCerebro

New Member
Joined
Apr 7, 2018
Location
Spain
Hello everyone!!!

These are some very useful functions to detect collisions in different ways, each one will use the one that best suits your game or application. I do not think they need examples, they are very intuitive to use.

Note: Many of the functions I have not tried, but I hope they work.

Code:
#rem
Created by http://benmoren.com
Some functions and code modified version from http://www.jeffreythompson.org/collision-detection
GNU LGPL 2.1 License
Version 0.1 | January 10th, 2016
#end

'Version for Cerberus-X by TheMrCerebro

'[~++~+~+~++~+~++~++~+~+~ 2D ~+~+~++~+~++~+~+~+~+~+~+~+~+~+~+]

Function colRectRect(x#, y#, w#, h#, x2#, y2#, w2#, h2#)

    'add in a thing to detect rectMode CENTER
    If (x + w >= x2 And x <= x2 + w2 And y + h >= y2 And  y <= y2 + h2) Return True
    Return False
  
End

Function colRectCircle(rx#, ry#, rw#, rh#, cx#, cy#, diameter#)

  'temporary variables to set edges for testing
  Local testX# = cx
  Local testY# = cy

  'which edge is closest?
  If (cx < rx)
      testX = rx 'left edge
  Else If (cx > rx+rw)
      testX = rx+rw 'right edge
  endif

  If (cy < ry)
      testY = ry 'top edge
  Else If (cy > ry+rh)
      testY = ry+rh 'bottom edge
  endif

  'get distance from closest edges
  Local distance# = Sqrt( Pow(cx-testX,2)+Pow(cy-testY,2) )

  'if the distance is less than the radius, collision!
  if (distance <= diameter/2) return true

  Return False

End

Function colCircleCircle(x#, y#, d#, x2#, y2#, d2#)

    If Sqrt( Pow(x-x2,2)+Pow(y-y2,2) ) <= (d/2)+(d2/2) Then Return True
    Return False

End

Function colPointCircle(x#, y#, cx#, cy#, d#)

    If Sqrt( Pow(x-cx,2)+Pow(y-cy,2) ) <= d/2 Then Return True
    Return False
  
End

Function colPointPoint(x1#, y1#, x2#, y2#)

    'are the two points in the same location?
    if (x1 = x2 and y1 = y2) then return true
    Return False

End

Function colPointRect(pointX#, pointY#, x#, y#, xW#, yW#)

    If (pointX >= x And pointX <= x + xW And pointY >= y And pointY <= y + yW) Then Return True
    Return False
  
End


function colLineRect(x1#, y1#, x2#, y2#, rx#, ry#, rw#, rh#)

    'check if the line has hit any of the rectangle's sides
    'uses the Line/Line function below
    Local left?   = colLineLine(x1,y1,x2,y2, rx,ry,rx, ry+rh)
    Local right?  = colLineLine(x1,y1,x2,y2, rx+rw,ry, rx+rw,ry+rh)
    Local top?    = colLineLine(x1,y1,x2,y2, rx,ry, rx+rw,ry)
    Local bottom? = colLineLine(x1,y1,x2,y2, rx,ry+rh, rx+rw,ry+rh)

    'if ANY of the above are true, the line has hit the rectangle
    If (left or right or top or bottom) Then Return True

    Return False
  
end

Function colLineLine(x1#, y1#, x2#, y2#, x3#, y3#, x4#, y4#)

    'calculate the direction of the lines
    Local uA# = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1))
    Local uB# = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1))

    'if uA and uB are between 0-1, lines are colliding
    if (uA >= 0 and uA <= 1 and uB >= 0 and uB <= 1) then Return True

    Return False

end

Function colLineCircle(x1#, y1#, x2#, y2#, cx#, cy#, r#)

    'is either end INSIDE the circle?
    'if so, return true immediately
    Local inside1? = colPointCircle(x1,y1, cx,cy,r)
    local inside2? = colPointCircle(x2,y2, cx,cy,r)
    if (inside1 or inside2) return true

    'get length of the line
    Local distX# = x1 - x2
    Local distY# = y1 - y2
    Local len# = Sqrt( (distX*distX) + (distY*distY) )

    'get dot product of the line and circle
    Local dot# = ( ((cx-x1)*(x2-x1)) + ((cy-y1)*(y2-y1)) ) / Pow(len,2)

    'find the closest point on the line
    Local closestX# = x1 + (dot * (x2-x1))
    Local closestY# = y1 + (dot * (y2-y1))

    'is this point actually on the line segment?
    'if so keep going, but if not, return false
    Local onSegment? = colLinePoint(x1,y1,x2,y2, closestX,closestY)
    If Not onSegment Then Return False

    'get distance to closest point
    distX = closestX - cx
    distY = closestY - cy
    Local distance# = Sqrt( (distX*distX) + (distY*distY) )

    If (distance <= r) Then Return True

    return false

end

Function colLinePoint(x1#, y1#, x2#, y2#, px#, py#)

    'get distance from the point to the two ends of the line
    Local d1# = dist(px,py, x1,y1)
    local d2# = dist(px,py, x2,y2)

    'get the length of the line
    Local lineLen# = dist(x1,y1, x2,y2)

    'since floats are so minutely accurate, add
    'a little buffer zone that will give collision
    Local buffer# = 0.1 'higher # = less accurate

    'if the two distances are equal to the line's length, the
    'point is on the line!
    'note we use the buffer here to give a range, rather than one #
    If (d1+d2 >= lineLen-buffer and d1+d2 <= lineLen+buffer) Then Return True

    Return False

End
 

Attachments

Holzchopf

Moderator
Joined
Jul 31, 2017
Location
Bern, Switzerland
Thanks, very handy!

But I think the colLineRect function is missing the 'is either end INSIDE the circle?-part (like the colLineCircle has) and therefore won't trigger when a line is completely inside the rect.

Also I'd prefer having full Pascal case function names. E.g. CollideRectRect, CollideRectCircle and so on.
 
Top Bottom