I have this PyBox2D script, And I want all the bodies to destroy and then reset when a Car hits a building. The collision detection works well, so does the destroying of the world, a problem occurs when I try to reset the world. The world would either crash, or the car moves uncontrollably or it does not move at all.
My apologies for such a long code, but this is the minimal runnable example. Thank you very much for any help
import numpy as np
import random
import keyboard
import Box2D
from Box2D.b2 import world, polygonShape, circleShape, edgeShape, staticBody, dynamicBody, kinematicBody, revoluteJoint, wheelJoint, contact
from Box2D import b2Vec2, b2FixtureDef, b2PolygonShape, b2CircleShape, b2Dot, b2EdgeShape, b2Contact, b2ContactFilter, b2Filter, b2ContactListener
import pygame
from pygame import HWSURFACE, DOUBLEBUF, RESIZABLE, VIDEORESIZE
from pygame.locals import (QUIT, KEYDOWN, K_ESCAPE)
pygame.init()
# PyBox2D setup
PPM = 5
SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
POS_X = SCREEN_WIDTH / PPM / 3
POS_Y = SCREEN_HEIGHT / PPM / 3
CAR_CATEGORY = 0x0002
BUILDING_CATEGORY = 0x0008
CAR_GROUP = 2
BUILDING_GROUP = -8
contact_flag = False
class myContactListener(b2ContactListener):
def handle_contact(self, contact, began):
# A contact happened -- see if a wheel hit a
# ground area
fixture_a = contact.fixtureA
fixture_b = contact.fixtureB
body_a, body_b = fixture_a.body, fixture_b.body
ud_a, ud_b = body_a.userData, body_b.userData
car_contact = None
building_contact = None
wheel_contact = None
for ud in (ud_a, ud_b):
if ud is not None:
obj = ud['obj']
if isinstance(obj, Car):
car_contact = obj
elif isinstance(obj, Building):
building_contact = obj
elif isinstance(obj, Wheel):
wheel_contact = obj
if car_contact is not None and building_contact is not None:
print("BUMMM")
_destroy()
def __init__(self):
b2ContactListener.__init__(self)
def BeginContact(self, contact):
self.handle_contact(contact, True)
def EndContact(self, contact):
pass
def PreSolve(self, contact, oldManifold):
pass
def PostSolve(self, contact, impulse):
pass
def _destroy():
for building in skyscrapers:
building.destroy_flag = True
for wheel in cars[0].tires:
wheel.destroy_flag = True
cars[0].destroy_flag = True
def _reset():
if len(box2world.bodies) == 0:
for building in skyscrapers:
building.destroy_flag = False
for wheel in cars[0].tires:
wheel.destroy_flag = False
cars[0].destroy_flag = False
create_buildings()
create_car()
cars[0].control()
box2world = world(contactListener=myContactListener(), gravity=(0.0, 0.0), doSleep=True)
class Wheel():
def __init__(self, box2world, phi, max_lateral_impulse=1, shape=(0.25, 0.75), turn_torque=15000, position=None):
if position is None:
position = [POS_X, POS_Y]
self.destroy_flag = False
self.position = position
self.shape = shape
self.box2world = box2world
self.phi = phi
self.max_lateral_impulse = max_lateral_impulse
self.turn_torque = turn_torque
self.wheel = self.box2world.CreateDynamicBody(position=(self.position[0], self.position[1]),
angle=self.phi,
fixtures=b2FixtureDef(
shape=b2PolygonShape(box=shape),
density=650.0,
friction=10000,
))
self.wheel.userData = {'obj': self}
# Cancelling lateral velocity
@property
def forward_velocity(self):
current_normal = self.wheel.GetWorldVector((0, 1))
return current_normal.dot(self.wheel.linearVelocity) * current_normal
def get_lateral_velocity(self):
currentRightNormal = self.wheel.GetWorldVector((1, 0))
return currentRightNormal.dot(self.wheel.linearVelocity) * currentRightNormal
def apply_impulse(self):
Impulse = self.wheel.mass * -Wheel.get_lateral_velocity(self)
self.wheel.ApplyLinearImpulse(Impulse, self.wheel.worldCenter, wake=True)
if Impulse.length > self.max_lateral_impulse:
Impulse *= self.max_lateral_impulse / Impulse.length
self.wheel.ApplyLinearImpulse(Impulse, self.wheel.worldCenter, True)
# Allowing skidding
angular_impulse = 0.5 * self.wheel.inertia * -self.wheel.angularVelocity
self.wheel.ApplyAngularImpulse(angular_impulse, True)
current_forward_normal = self.forward_velocity
current_forward_speed = current_forward_normal.Normalize()
drag_force_magnitude = -2 * current_forward_speed
self.wheel.ApplyForce(drag_force_magnitude * current_forward_normal, self.wheel.worldCenter, True)
class Car():
def __init__(self, box2world, position=None):
if position is None:
position = [POS_X + 10, POS_Y + 5]
self.destroy_flag = False
self.position = position
self.ticking = 0
self.box2world = box2world
self.body = self.box2world.CreateDynamicBody(position=self.position,
angle=0.0)
self.body_Fixtures = self.body.CreatePolygonFixture(shape=b2PolygonShape(box=(2.189 / 2, 4.897 / 2)),
density=2810,
friction=0,
filter=b2Filter(
categoryBits=CAR_CATEGORY,
maskBits=BUILDING_CATEGORY,
groupIndex=CAR_GROUP))
self.tires = []
self.suspensions = []
self.on_the_beginning = False
self.body.userData = {'obj': self}
# Connecting bodywork with wheels
for i in range(4):
if i == 1 or i == 2: # Moving wheels a bit away from the chassis
X_SHIFT = 0.45
else:
X_SHIFT = -0.45
# Creating Wheels
self.tires.append(Wheel(box2world=box2world, phi=0, position=(self.position[0] + X_SHIFT, self.position[1])))
if i in range(2):
# Rear wheels do not move so they can be welded to chassis
self.suspensions.append(box2world.CreateWeldJoint(bodyA=self.body,
bodyB=self.tires[i].wheel,
localAnchorA=(self.body_Fixtures.shape.vertices[i][0] + X_SHIFT, self.body_Fixtures.shape.vertices[i][1] + 0.5),
localAnchorB=(0, 0),
))
else:
# Front wheels are revolute joints
self.suspensions.append(box2world.CreateRevoluteJoint(bodyA=self.tires[i].wheel,
bodyB=self.body,
localAnchorA=(0, 0),
localAnchorB=(self.body_Fixtures.shape.vertices[i][0] + X_SHIFT, self.body_Fixtures.shape.vertices[i][1] - 0.5),
enableMotor=True,
maxMotorTorque=100000,
enableLimit=True,
lowerAngle=0,
upperAngle=0,
motorSpeed=0
))
def control(self): # This makes control independent from visualisation
# Front left suspension: index 2
# Front right suspension: index 3
# Alternative steering (Con: Physical perversion, Pro: It works...)
if keyboard.is_pressed("a"):
self.suspensions[2].lowerLimit -= np.deg2rad(2)
self.suspensions[2].upperLimit -= np.deg2rad(2)
self.suspensions[3].lowerLimit -= np.deg2rad(2)
self.suspensions[3].upperLimit -= np.deg2rad(2)
if self.suspensions[2].lowerLimit <= -np.pi / 4:
self.suspensions[2].upperLimit = -np.pi / 4
self.suspensions[2].lowerLimit = -np.pi / 4
self.suspensions[3].upperLimit = -np.pi / 4
self.suspensions[3].lowerLimit = -np.pi / 4
if keyboard.is_pressed("d"):
self.suspensions[2].upperLimit += np.deg2rad(2)
self.suspensions[2].lowerLimit += np.deg2rad(2)
self.suspensions[3].upperLimit += np.deg2rad(2)
self.suspensions[3].lowerLimit += np.deg2rad(2)
if self.suspensions[2].upperLimit >= np.pi / 4:
self.suspensions[2].lowerLimit = np.pi / 4
self.suspensions[2].upperLimit = np.pi / 4
self.suspensions[3].lowerLimit = np.pi / 4
self.suspensions[3].upperLimit = np.pi / 4
else:
self.ticking = -1
FORWARD_IMPULSE = 1000
if keyboard.is_pressed("w"):
self.tires[2].wheel.ApplyLinearImpulse(b2Vec2(self.tires[2].wheel.GetWorldVector((0, FORWARD_IMPULSE))), self.tires[2].wheel.position, True)
self.tires[3].wheel.ApplyLinearImpulse(b2Vec2(self.tires[3].wheel.GetWorldVector((0, FORWARD_IMPULSE))), self.tires[3].wheel.position, True)
if keyboard.is_pressed("s"):
self.tires[2].wheel.ApplyLinearImpulse(b2Vec2(self.tires[2].wheel.GetWorldVector((0, -FORWARD_IMPULSE))), self.tires[2].wheel.position, True)
self.tires[3].wheel.ApplyLinearImpulse(b2Vec2(self.tires[3].wheel.GetWorldVector((0, -FORWARD_IMPULSE))), self.tires[3].wheel.position, True)
for wheels in self.tires:
if wheels == 0 or wheels == 1:
pass
else:
Wheel.apply_impulse(wheels)
class Building():
BUILDING_FILTER = b2Filter(categoryBits=BUILDING_CATEGORY,
maskBits=CAR_CATEGORY,
groupIndex=BUILDING_GROUP,
)
def __init__(self, box2world, shape, position, sensor=None):
self.box2world = box2world
self.destroy_flag = False
self.shape = shape
self.position = position
if sensor is None:
sensor = False
self.sensor = sensor
self.footprint = self.box2world.CreateStaticBody(position=position,
angle=0.0,
fixtures=b2FixtureDef(
shape=b2PolygonShape(box=(self.shape)),
density=1000,
friction=1000,
filter=Building.BUILDING_FILTER))
self.footprint.userData = {'obj': self}
############################################################## Setting up car and buildings
def create_buildings():
BUILDINGS_POSITIONS = [(POS_X - 25, POS_Y), (POS_X + 40, POS_Y), (POS_X - 25, POS_Y + 40), (POS_X + 40, POS_Y + 40),
(POS_X - 25, POS_Y - 40), (POS_X + 40, POS_Y - 40), (POS_X - 25, POS_Y - 80), (POS_X + 40, POS_Y + -80),
(POS_X + 165, POS_Y), (POS_X + 105, POS_Y), (POS_X + 165, POS_Y + 40), (POS_X + 105, POS_Y + 40),
(POS_X + 165, POS_Y - 40), (POS_X + 105, POS_Y - 40), (POS_X + 165, POS_Y - 80), (POS_X + 105, POS_Y + -80),
(POS_X + 230, POS_Y + 40), (POS_X + 230, POS_Y), (POS_X + 230, POS_Y - 40), (POS_X + 230, POS_Y + - 80)]
# Generate buildings of different shape (the number of buildings is partly determined by an element of coincidence)
RANDOM_MODULO = random.randint(3,7)
for i in range(len(BUILDINGS_POSITIONS)):
if i % RANDOM_MODULO == 0:
skyscrapers.append(Building(box2world, shape=(8, 12), position=(BUILDINGS_POSITIONS[i][0] + 15.5, BUILDINGS_POSITIONS[i][1])))
skyscrapers.append(Building(box2world, shape=(10, 12), position=(BUILDINGS_POSITIONS[i][0] - 15.5, BUILDINGS_POSITIONS[i][1])))
else:
skyscrapers.append(Building(box2world, shape=(23, 12), position=(BUILDINGS_POSITIONS[i])))
skyscrapers = []
create_buildings()
# Randomly choose a skyscraper, next to which a car will be generated
# (first four skyscraper are visible when the PyGame window is launched)
cars_random_skyscraper = random.choice(skyscrapers[0:3])
def create_car():
cars.append(Car(box2world, position=(cars_random_skyscraper.position[0] + 1.55 * cars_random_skyscraper.shape[0], cars_random_skyscraper.position[1])))
cars = []
create_car()
############################################################## Pygame visualisation
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), HWSURFACE | DOUBLEBUF | RESIZABLE)
pygame.display.set_caption('Top Down Car Using OOP')
colors = {dynamicBody: (133, 187, 101, 0), staticBody: (15, 0, 89, 0)}
running = True
FPS = 24
TIME_STEP = 1.0 / FPS
############################### Drawing functions
SCREEN_OFFSETX, SCREEN_OFFSETY = SCREEN_WIDTH / 16, SCREEN_HEIGHT
def fix_vertices(vertices):
return [(int(SCREEN_OFFSETX + v[0]), int(SCREEN_OFFSETY - v[1])) for v in vertices]
def _draw_polygon(polygon, screen, body, fixture):
transform = body.transform
vertices = fix_vertices([transform * v * PPM for v in polygon.vertices])
pygame.draw.polygon(
screen, [c / 2.0 for c in colors[body.type]], vertices, 0)
pygame.draw.polygon(screen, colors[body.type], vertices, 1)
polygonShape.draw = _draw_polygon
def step():
if (cars[0].destroy_flag == False):
TIME_STEP = 1.0 / FPS
box2world.Step(TIME_STEP, 10, 10)
else:
for body in box2world.bodies:
box2world.DestroyBody(body)
############################### Main game loop
while running:
# Control your car
cars[0].control()
# Check the event queue
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
# The user closed the window or pressed escape
running = False
# Draw the world
screen.fill((255, 255, 255, 255))
for body in box2world.bodies:
for fixture in body.fixtures:
fixture.shape.draw(screen, body, fixture)
# Simulate dynamic equation in each step
step()
_reset()
# Flip the screen and try to keep at the target FPS
pygame.display.flip() # Update the full display Surface to the screen
pygame.time.Clock().tick(FPS)
pygame.quit()
print('Done!')
EDIT This is the complete error message I get, when to world crashes, hope it helps
Fatal Python error: (pygame parachute) Segmentation Fault
Thread 0x00001e80 (most recent call first):
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 296 in wait
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\queue.py", line 170 in get
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\site-packages\keyboard\_generic.py", line 57 in process
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 865 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydev_bundle\pydev_monkey.py", line 667 in __call__
Thread 0x000023ec (most recent call first):
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\site-packages\keyboard\_winkeyboard.py", line 563 in listen
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\site-packages\keyboard\__init__.py", line 294 in listen
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 865 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydev_bundle\pydev_monkey.py", line 667 in __call__
Thread 0x000033cc (most recent call first):
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\pydevd.py", line 199 in _on_run
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 149 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
Thread 0x00003758 (most recent call first):
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 300 in wait
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 552 in wait
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\pydevd.py", line 171 in _on_run
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 149 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
Thread 0x00003958 (most recent call first):
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\wrapper.py", line 168 in recv
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 248 in _read_line
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 262 in _on_run
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 149 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
Thread 0x00002e6c (most recent call first):
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 300 in wait
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\queue.py", line 179 in get
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 362 in _on_run
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 149 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
Thread 0x00001dd8 (most recent call first):
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\ipcjson.py", line 113 in _buffered_read_line_as_ascii
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\ipcjson.py", line 154 in _wait_for_message
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\ipcjson.py", line 272 in process_one_message
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\ipcjson.py", line 258 in process_messages
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\wrapper.py", line 521 in process_messages
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 865 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
Thread 0x000036d8 (most recent call first):
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 300 in wait
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 552 in wait
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\futures.py", line 122 in run_forever
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 865 in run
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917 in _bootstrap_inner
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\threading.py", line 885 in _bootstrap
Current thread 0x00003694 (most recent call first):
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\site-packages\Box2D\Box2D.py", line 8320 in <lambda>
File "c:\Users\Mechatrnk\OneDrive\V\u0160\DP - Design of Autonomous Vehicle Simulator\Programming\CarModel.py", line 152 in control
File "c:\Users\Mechatrnk\OneDrive\V\u0160\DP - Design of Autonomous Vehicle Simulator\Programming\Final_OOP_TopDown_Car_19_2_Model_auta_v_novem_skriptu.py", line 320 in <module>
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\runpy.py", line 85 in _run_code
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\runpy.py", line 96 in _run_module_code
File "C:\Users\Mechatrnk\AppData\Local\Programs\Python\Python37\lib\runpy.py", line 263 in run_path
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\__main__.py", line 316 in run_file
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\lib\python\old_ptvsd\ptvsd\__main__.py", line 432 in main
File "c:\Users\Mechatrnk\.vscode\extensions\ms-python.python-2020.2.63072\pythonFiles\ptvsd_launcher.py", line 48 in <module>
User contributions licensed under CC BY-SA 3.0