Log In  

Cart #circle_collision_example-0 | 2024-03-30 | Code ▽ | Embed ▽ | No License
3

This is a simple example on how circle collision works.

All you need from this cartridge is the function:

function circ_col(c1, c2)
  local dx = c1.pos.x - c2.pos.x
  local dy = c1.pos.y - c2.pos.y
  local distance = sqrt(dx*dx + dy*dy)
  return distance <= (c1.r + c2.r)
end

If you want to check if two circles are colliding, you simply pass them as parameters c1 and c2 see an example bellow:

c1 = {
    pos={x=64,y=64},
    r = 4 --size the radius would have to be for a 8x8 sprite
}

c2 = {
    pos={x=70,y=70},
    r = 8 --size the radius would have to be for a 8x8 sprite
}

collides = false

function _update()
   collides = circ_col(c1, c2)
end

function _draw()
   cls()

   if collides then 
      print("colliding",4,4,11)
   end

   --draw the circles here - mind you in most projects you woudn't, usually you would have them invisible and have them
   --at the same position (or slightly offsetted) as your player
   --i would recommend drawing them anyway at the start to see that the are always where they are supposed to be
   circ(c1.pos.x,c2.pos.y,c1.r,11)
   circ(c2.pos.x,c2.pos.y,c2.r,8)
end

function circ_col(c1, c2)
  local dx = c1.pos.x - c2.pos.x
  local dy = c1.pos.y - c2.pos.y
  local distance = sqrt(dx*dx + dy*dy)
  return distance <= (c1.r + c2.r)
end
P#145104 2024-03-30 10:25

Simple clean code that works well for small circles.
A word of warning with semi-big cirles : the 16.16 format of pico8 numbers will easily overflow , even computing the diagonal of a 128x128 square will fail.

P#145143 2024-03-30 17:19 ( Edited 2024-03-30 17:32)

@RealShadowCaster

Thanks a lot for pointing that out o.O! Wasn't aware of that.

P#145151 2024-03-30 18:03

Because you already know the distance you want to check against (r1+r2) you can use this distance check by Mot which is efficient and safe from overflow: https://www.lexaloffle.com/bbs/?pid=130349#p
by passing in your dx,dy,(r1+r2)

P#145161 2024-03-30 19:52
1

@kozm0naut, interesting approach, both token and speed efficient.
My approach is different, instead of comparing d1 and d2,
I'm comparing (d1/256)^2 and (d2/256)^2
You also avoid the square root, and use every bit of the 16.16 format for precision while avoiding overflows.

function circ_col(c1, c2)
  local dx = (c1.pos.x - c2.pos.x)>>8
  local dy = (c1.pos.y - c2.pos.y)>>8
  local rsum= (c1.r + c2.r)>>8
  return dx*dx+dy*dy <= rsum*rsum
end
P#145189 2024-03-30 22:42 ( Edited 2024-03-30 22:45)

[Please log in to post a comment]