What's the best way to make curved collision walls?

Hi everyone, I'm new here and mostly self-taught, so apologies in advance. I'm making a top-down racing game and I want to have curved corners you can slide along. What's the best way to do this? As I understand it, you can't rotate collision rectangles or I would use a series of them to make a curve. Any and all help would be appreciated. Thanks everyone!

I could be wrong but you can use collisions for this:

teddy:setCollideRect( 0, 0, teddy:getSize() )
if teddy:alphaCollision(another_object) then
...
end

I know it works for straight lines, but I think (though I'm not sure) that it works if the black pixels hit each other. Could be wrong about that though!

The flippy fish example game that comes with the playdate SDK has a working example of a fish and some seaweed that collides.

Maybe someone who knows more about collisions than me can shed some light!

The curved corner can be represented by a circle, or arc (which is just a circle but only registered if the collision is between the two angles of the arc), and rectangle to circle collisions are fairly easy.

If you approximate the shape of your car to also be a circle then you get really easy circle to circle collisions, angle of reflection, and so on. This (plus a bunch more smoke and mirrors) is what I do in Daily Driver.

You can do nearly any collision shape using Signed Distance Functions. Its a pretty neat concept and if you're not afraid of the math involved I'd give it a look. For curves I'd approximate the car shape with an oval and a curve by an inverted circle.

4 Likes

Thanks so much for the help everyone!

These are super cool.

Would be cool to have a Playdate compatible lua library of these.

I could try and implement a SDF collision library in Lua using playdate geomtry objects. You basically have to reimplement the methods I linked above and create a sprite sub-class that overrides all collision functions to use SDF's. I just dont know how performant a general implementation would be on the playdate.

2D SDFs have been ported: Playdate Squad Discord

1 Like

Yes, I have a golf poc for a game under development running with a library of SDF objects in Lua. I use the sprites AABB collision to bound when an SDF check is needed.
The collision physics is super simple and super performant, you just caculate the normal by taking the gradient of a sampling of neighbour distances then use that for your movement resolution.
(You can see a animation on the discord, I can't post here as a new user)
pd.geo is good for rendering but optional for complex shapes since you can always derive the shape from sampling all points in the sdf itself albeit rather slow and suited to pre-rendering. (eg. in my demo animation the parabolic hill shading is rendered from surface distance)
I've been experimenting with optimising raymarching so I can use it for lighting scenes but success remains to be seen.

I can publish a library with the sdf's.. would be cool if in SDK even.

Observations from porting to the SDK. These would be nice simple vector helpers:

  • scalar * vector2D not just the reverse
  • min(v1, v2) to take the min of the x and y (and max)
  • a function for (v1.x * v2.x, v1.y * v2.y)

e.g. here is an arc

-- returns distance from point p (vector2D) with angle sc of radius ra and line with rb
function sdArc(p, sc, ra, rb)
	-- sc = vector2D.new(math.sin(rad),math.cos(rad))
	p.x = math.abs(p.x)
	local dist = (sc.y * p.x > sc.x * p.y) and (p - sc * ra):magnitude() or math.abs(p:magnitude() - ra)
	return dist - rb
end
1 Like

Sounds very cool, seems like you already beat me to it haha :smiley: Maybe post it in the SDK suggestion board.

This video seems less than 50fps due to the capture (gif capture is usually more performant, and very much smaller)

Copied from the discord