• Dear Cerberus X User!

    As we prepare to transition the forum ownership from Mike to Phil (TripleHead GmbH), we need your explicit consent to transfer your user data in accordance with our amended Terms and Rules in order to be compliant with data protection laws.

    Important: If you accept the amended Terms and Rules, you agree to the transfer of your user data to the future forum owner!

    Please read the new Terms and Rules below, check the box to agree, and click "Accept" to continue enjoying your Cerberus X Forum experience. The deadline for consent is April 5, 2024.

    Do not accept the amended Terms and Rules if you do not wish your personal data to be transferred to the future forum owner!

    Accepting ensures:

    - Continued access to your account with a short break for the actual transfer.

    - Retention of your data under the same terms.

    Without consent:

    - You don't have further access to your forum user account.

    - Your account and personal data will be deleted after April 5, 2024.

    - Public posts remain, but usernames indicating real identity will be anonymized. If you disagree with a fictitious name you have the option to contact us so we can find a name that is acceptable to you.

    We hope to keep you in our community and see you on the forum soon!

    All the best

    Your Cerberus X Team

Snippet Coldet - Functions for collision detection

TheMrCerebro

Member
Tutorial Author
Joined
Apr 7, 2018
Messages
18
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

  • coldet.cxs
    4.2 KB · Views: 328
  • 1548882340791.png
    1548882340791.png
    3.2 KB · Views: 447
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.
 
Back
Top Bottom