adammoyle
adammoyle

Reputation: 309

pyBox2D raycasting not working as it should

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

Answers (1)

adammoyle
adammoyle

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

Related Questions