Rocket

Fly a rocket from one plant to another. Use ‘a’,’w’,’d’ to fire the rockets engines, but avoid the black hole!

/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
import b2d
import math


class Rocket(TestbedBase):

    name = "Rocket"

    def __init__(self, settings=None):
        super(Rocket, self).__init__(gravity=(0, 0), settings=settings)

        # gravitational constant
        self.gravitational_constant = 6.0

        self.planets = {}

        # home planet
        home_planet = self.world.create_kinematic_body(
            position=(10, 0),
            fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=20)),
            user_data="home_planet",
        )

        # target planet
        target_planet = self.world.create_kinematic_body(
            position=(100, 100),
            fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=10)),
            user_data="target_planet",
        )

        # black hole
        black_hole = self.world.create_kinematic_body(
            position=(0, 400),
            fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=1)),
            user_data="black_hole",
        )

        self.planets = {
            home_planet: dict(radius=20, density=1, color=(0, 0.2, 1)),
            target_planet: dict(radius=10, density=1, color=(0.7, 0.7, 0.7)),
            black_hole: dict(radius=1, density=10000, color=(0.1, 0.1, 0.1)),
        }

        # a tiny rocket
        self.rocket = self.world.create_dynamic_body(
            position=(10, 10),
            fixtures=[
                b2d.fixture_def(shape=b2d.polygon_shape(box=[1, 1]), density=1),
                b2d.fixture_def(
                    shape=b2d.polygon_shape(vertices=[(-1, 1), (0, 4), (1, 1)]),
                    density=1,
                ),
            ],
            angular_damping=0.5,
            linear_damping=0.2,
            user_data="rocket",
        )
        # check if the rocket is gone
        self.touched_black_hole = False

        # particle system
        pdef = b2d.particle_system_def(
            viscous_strength=0.9,
            spring_strength=0.0,
            damping_strength=100.5,
            pressure_strength=1.0,
            color_mixing_strength=0.05,
            density=0.1,
        )

        psystem = self.world.create_particle_system(pdef)
        psystem.radius = 0.1
        psystem.damping = 0.5

        self.emitters = []
        self.key_map = {"w": 0, "a": 1, "d": 2}

        angle_width = (math.pi * 2) / 16
        emitter_def = b2d.RandomizedRadialEmitterDef()
        emitter_def.emite_rate = 2000
        emitter_def.lifetime = 1.0
        emitter_def.enabled = False
        emitter_def.inner_radius = 1
        emitter_def.outer_radius = 1
        emitter_def.velocity_magnitude = 10.0
        emitter_def.start_angle = math.pi / 2 - angle_width / 2.0
        emitter_def.stop_angle = math.pi / 2 + angle_width / 2.0
        emitter_def.body = self.rocket

        delta = 0.2
        self.emitter_local_anchors = [
            (0, -delta),  # main
            (-delta, -0.5),  # left,
            (delta, -0.5),  # right
        ]
        self.emitter_local_rot = [math.pi, math.pi / 2, -math.pi / 2]  # main

        # main trust
        emitter_def.emite_rate = 2000
        world_anchor = self.rocket.get_world_point(self.emitter_local_anchors[0])
        emitter_def.transform = b2d.Transform(
            world_anchor, b2d.Rot(self.emitter_local_rot[0])
        )
        emitter = b2d.RandomizedRadialEmitter(psystem, emitter_def)
        self.emitters.append(emitter)

        # left
        emitter_def.emite_rate = 200
        world_anchor = self.rocket.get_world_point(self.emitter_local_anchors[1])
        emitter_def.transform = b2d.Transform(
            world_anchor, b2d.Rot(self.emitter_local_rot[1])
        )
        emitter = b2d.RandomizedRadialEmitter(psystem, emitter_def)
        self.emitters.append(emitter)

        # right
        emitter_def.emite_rate = 200
        world_anchor = self.rocket.get_world_point(self.emitter_local_anchors[1])
        emitter_def.transform = b2d.Transform(
            world_anchor, b2d.Rot(self.emitter_local_rot[1])
        )
        emitter = b2d.RandomizedRadialEmitter(psystem, emitter_def)
        self.emitters.append(emitter)

    def pre_step(self, dt):

        # check if the rocket has died
        if self.touched_black_hole:
            if self.rocket is not None:
                self.world.destroy_body(self.rocket)
                self.rocket = None
        else:
            rocket_center = self.rocket.world_center
            rocket_mass = self.rocket.mass
            # compute gravitational forces
            net_force = numpy.zeros([2])
            for planet, planet_def in self.planets.items():
                radius = planet_def["radius"]
                planet_center = planet.position
                planet_mass = planet_def["density"] * radius ** 2 * math.pi
                delta = rocket_center - planet_center
                distance = delta.normalize()
                f = (
                    -self.gravitational_constant
                    * rocket_mass
                    * planet_mass
                    / (distance * distance)
                )
                net_force += delta * f
            f = float(net_force[0]), float(net_force[1])
            self.rocket.apply_force_to_center(f)

            # run the rockets engines
            for emitter, local_anchor, local_rotation in zip(
                self.emitters, self.emitter_local_anchors, self.emitter_local_rot
            ):
                world_anchor = self.rocket.get_world_point(local_anchor)
                emitter.position = world_anchor
                emitter.angle = self.rocket.angle + local_rotation
                emitter.step(dt)

    def begin_contact(self, contact):
        body_a = contact.body_a
        body_b = contact.body_b
        if body_b.user_data == "rocket":
            body_a, body_b = body_b, body_a

        user_data_a = body_a.user_data
        user_data_b = body_b.user_data
        if body_a.user_data == "rocket":
            if user_data_b == "black_hole":
                self.touched_black_hole = True

    def on_keyboard_down(self, key):
        if key in self.key_map:
            self.emitters[self.key_map[key]].enabled = True
            return True
        return False

    def on_keyboard_up(self, key):
        if key in self.key_map:
            self.emitters[self.key_map[key]].enabled = False
            return False
        return False

    def pre_debug_draw(self):
        pass

    def post_debug_draw(self):
        for planet, planet_def in self.planets.items():
            pos = planet.position

            self.debug_draw.draw_solid_circle(
                pos, planet_def["radius"] + 0.1, axis=None, color=planet_def["color"]
            )
            if planet.user_data == "black_hole":
                self.debug_draw.draw_circle(
                    pos, planet_def["radius"] * 5, color=(1, 1, 1), line_width=0.1
                )


if __name__ == "__main__":

    ani = b2d.testbed.run(Rocket)

Total running time of the script: ( 0 minutes 37.573 seconds)

Gallery generated by Sphinx-Gallery