Log In  


Cart #orbuswip-0 | 2023-07-01 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

Are circular hitboxes possible?

is it possible to make circular hitboxes?
I need the bullets to be deleted when they touch the white circle.
So I need to be able to detect when they are inside the circle.

My first idea was to have a buch of thin rectangular hitboxes next to eachother that are higher near the center of the circle to approximate the shape, but I am struggling with the math to make it work.

PS Is there a way to make the cart show it's actual title on the BBS rather then it's ID. having title an ID match is not always possible.

1


1

I think there's better ways, but the simplest solution is to use Pythagorean distance:

if sqrt( (x-x0)^2 + (y-y0)^2 ) < r then etc

...except that you really don't need the square root if you're just checking magnitude:

if (x-x0)^2+(y-y0)^2 < r^2 then etc

...except 128^2 + 128^2 = fixed point overflow, so you probably want to check radius first:

if abs(x-x0) < r and abs(y-y0) < r and (x-x0)^2+(y-y0)^2 < r^2 then etc

...but at this point you want to precalculate the differences:

local dx,dy=x-x0,y-y0
if abs(dx) < r and abs(dy) < r and dx*dx+dy*dy < r*r then etc

...but that's not, like, an optimized solution - it's just a very quick off-the-top-of-my-head one. I know there's better out there, I just don't remember the details.


3

The most basic way to check if circles overlap is to check if the distance between their centers is less than the sum of each radius. If the distance is less, then they must overlap. If the sum of each radius is less, then they can't overlap.

The formula packbat gave above is almost there, except that "r^2" really should be "(r+r0)^2".

That said, if your circles are going to have a radius bigger than around 64, then the formula in this thread is a better way to check distance, since it doesn't risk using too big of numbers for pico-8:
https://www.lexaloffle.com/bbs/?tid=49827

@packbat I don't think checking the radius would solve overflows on its own. If the game's scale is such that distances could be above 64, you should bitshift them (or divide if that's mentally easier) by a set amount to take more advantage of the number of bits pico-8 gives numbers.


1

I managed to get something working. I did it by checking the distance between the centers against the sum of the radii like you said @kimiyoribaka. Thanks for the hint. The function I wrote is definetely not optimized and I do not compensate for potential overflow, but that might not be necessary in this case.
I am still a beginner and not from a programming background so readable solutions are still better for me then heavely optimized ones. My version:

	function circle_collide(a,b)
		local distx=abs(b.x-a.x)
		local disty=abs(b.y-a.y)
		local dist=abs(distx+disty)
		local rsum=a.r+b.r
		if dist>rsum then return false end
		return true

	end

@packbat your feedback has also been helpfull.
Thanks to both of you

Cart #orbuswip2-0 | 2023-07-02 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1


1

@Doriencey as you can notice in your cart when bullets hit the circle in diagonals they seem to have more penetration.
The distance calc in your function has to be improved, you can tell its imprecision at a bigger scale in this example gif (yellow circle becomes red when the collide function returns true):

I'd use trig for that, here's a more precise version:

function circoll(a,b)
 local dx,dy = abs(b.x-a.x),abs(b.y-a.y)
 if(dx<dy) dx,dy = dy,dx
 local dst = dx/sin(atan2(dy,dx))
 return dst<a.r+b.r
end

The distance information is also present in the thread suggested by kimiyoribaka.
This function in action in the gif below:


@Heracleum I also noticed the inaccuracy when adding enemies. They need to disappear when they touch the edge of the biggest circle and they did so way early when going diagonally compared to horizontally or vertically. Your function does indeed fix the issue. Thanks a lot


1

Nice 👍
And of course if one visually prefers a bit more bullet penetration, you set the radius like 2px smaller and when you render the circle you add the 2px.


I already did a similar thing for the enemies. they go a few pixels outside the circel already shown. I don't show the actual radius I used for the collision. I would have to see how it looks when I actually add things like particles.


1

I'm used to using vectors and real world units for this sort of thing. It's a little bit of overhead to set up the classes required for it, but it simplifies the math a lot. If you set a meter to some pixel amount (ie 8px to 1m) you can extend the range to overflow beyond the typical screen space for pico8. You just have to make sure when you're rendering things that you convert from world space to screen space.



[Please log in to post a comment]