Reputation: 309
I have just started to play around with pyBox2D and was doing a raycasting for a top down game to see around objects, similar to http://ncase.me/sight-and-light/.
But some rays are being cast onto a object and continuing through the object and hitting other behind it shown in this gif
https://i.sstatic.net/rJ0iK.jpg
As you can see some rays are casting through objects, but when I move the dynamic box around it begins to work (ish) but glitches around sometimes
Here is my raycasting callback
class lightRayCasting(b2RayCastCallback):
def __init__(self, point, ignoreBody):
b2RayCastCallback.__init__(self)
self.hit = False
self.point = point
self.ignoreBody = ignoreBody
def ReportFixture(self, fixture, point, normal, fraction):
if fixture.body != self.ignoreBody and fixture.filterData.groupIndex != -1 and not self.hit:
self.hit = True
self.point = point
return 0
return 1
And this is where I am calling the raycasting
def lightRayCasting(self, position, **kwargs):
points = []
for ray in range(kwargs.get("n", 100)):
angle = (ray / kwargs.get("n", 100) * 360 * (b2_pi / 180))
rayDirection = b2Vec2(math.sin(angle), math.cos(angle)) * kwargs.get("length", 10)
callback = lightRayCasting(rayDirection, ignoreBody = kwargs.get("ignoreBody", None))
self.world.RayCast(callback, self.convertPosition(position), rayDirection)
points.append(self.convertPosition(callback.point, 1))
if kwargs.get("debugDraw", False):
if callback.point != rayDirection: pygame.draw.aaline(self.surface, (255, 0, 0), position, self.convertPosition(callback.point, 1))
else: pygame.draw.aaline(self.surface, (0, 255, 0), position, self.convertPosition(callback.point, 1))
if not kwargs.get("debugDraw", False):
pygame.gfxdraw.filled_polygon(self.surface, points, (255, 255, 255))
pygame.gfxdraw.aapolygon(self.surface, points, (255, 255, 255))
self.convertPosition is just converting pixels into meters for Box2D to work with. I cannot see why it works sometimes but other times it doesn't work. Do bodies have to be awake for raycasting to work on them?
Upvotes: 1
Views: 378
Reputation: 309
I have fixed my issue, for anyone who wants to know I take the fractions from the callback and for each callback check if it is smaller then the current and if it is set the intersect point to the point on the callback
def ReportFixture(self, fixture, point, normal, fraction):
if fraction < self.fraction:
if not fixture in self.ignoreFixtures:
if not fixture.filterData.groupIndex in self.ignoreIndexes:
self.hit = True
self.point = point
self.fraction = fraction
return 1
Upvotes: 1