Note
Go to the end to download the full example code
Raycast
This example shows how to use raycasting
/home/runner/.local/lib/python3.10/site-packages/b2d/testbed/backend/matplotlib_gif_gui/matplotlib_gif_gui.py:52: UserWarning: You passed in an explicit save_count=240 which is being ignored in favor of frames=240.
self.ani = animation.FuncAnimation(
from b2d.testbed import TestbedBase
import random
import numpy as np
import b2d
def rand_color():
return tuple([random.random() for i in range(3)])
class RayCastCallback(b2d.RayCastCallback):
def __init__(self):
super(RayCastCallback, self).__init__()
self._touched_circles = []
def report_fixture(self, fixture, point, normal, fraction):
user_data = fixture.body.user_data
if user_data is not None:
self._touched_circles.append(user_data)
return fraction
return -1
class Raycast(TestbedBase):
name = "raycast"
def __init__(self, settings=None):
super(Raycast, self).__init__(settings=settings)
dimensions = [30, 30]
# the outer box
box_shape = b2d.ChainShape()
box_shape.create_loop(
[
(0, 0),
(0, dimensions[1]),
(dimensions[0], dimensions[1]),
(dimensions[0], 0),
]
)
box = self.world.create_static_body(
position=(0, 0), fixtures=b2d.fixture_def(shape=box_shape, friction=1)
)
self.magic_circle_rad = 1.0
self.magic_circle = self.world.create_dynamic_body(
position=[1, 1],
fixtures=b2d.fixture_def(
shape=b2d.circle_shape(radius=self.magic_circle_rad),
density=1.0,
friction=1.0,
),
)
self.circles = []
for i in range(10):
self.circles.append(
self.world.create_dynamic_body(
position=[s / 2 + random.random() for s in dimensions],
fixtures=b2d.fixture_def(
shape=b2d.circle_shape(radius=1), density=1.0, friction=1.0
),
user_data=i,
)
)
self._touched_circles = []
def post_step(self, dt):
self._touched_circles = []
pos = self.magic_circle.position
n = 5
r0 = self.magic_circle_rad
r1 = 5
# most of this can be precomuted
t = np.linspace(0, 2 * np.pi, n, endpoint=False)
x0 = r0 * np.cos(t) + pos[0]
y0 = r0 * np.sin(t) + pos[1]
x1 = r1 * np.cos(t) + pos[0]
y1 = r1 * np.sin(t) + pos[1]
for i in range(n):
p0 = float(x0[i]), float(y0[i])
p1 = float(x1[i]), float(y1[i])
cb = RayCastCallback()
self.debug_draw.draw_segment(p0, p1, (1, 1, 1), line_width=0.1)
self.world.ray_cast(cb, p0, p1)
self._touched_circles.extend(cb._touched_circles)
def post_debug_draw(self):
position = tuple(self.magic_circle.position)
self.debug_draw.draw_solid_circle(position, 1.0, (1, 0), rand_color())
for i in self._touched_circles:
self.debug_draw.draw_solid_circle(
self.circles[i].position, 1.0, (1, 0), (1, 0, 0)
)
if __name__ == "__main__":
ani = b2d.testbed.run(Raycast)
ani
Total running time of the script: ( 0 minutes 37.426 seconds)