Столкновения объектов в pybox2d
пытаюсь сделать модель некого устройства (как у OpenAI Gymnasium) для дальнейшего обучения модели PPO. Никак не могу понять, почему отсутствуют столкновения в модели, которую я пытаюсь сделать. Объекты просто проходя сквозь друг друга, хотя я сделал им всем фикстуры.
import pygame as pg
from pygame.locals import *
from pygame.color import *
import Box2D
from Box2D import *
import random
from math import cos, sin, radians, atan
FPS = 60
WIN_WIDTH = 900
WIN_HEIGHT = 750
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (125, 125, 125)
LIGHT_BLUE = (64, 128, 255)
GREEN = (0, 200, 64)
YELLOW = (225, 225, 0)
PINK = (230, 50, 230)
RED = (255, 0, 0)
clock = pg.time.Clock()
sc = pg.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
pg.init()
# Создаем мир Box2D
gravity = 50
world = b2World(gravity=(0, gravity), doSleep=False)
# Создаем рамку
top = world.CreateStaticBody(position=(1, 1), shapes=b2PolygonShape(box=(WIN_WIDTH, 1)))
bot = world.CreateStaticBody(
position=(WIN_WIDTH - 1, WIN_HEIGHT - 1), shapes=b2PolygonShape(box=(WIN_WIDTH, 1))
)
left = world.CreateStaticBody(
position=(0, 0), shapes=b2PolygonShape(box=(1, WIN_HEIGHT))
)
right = world.CreateStaticBody(
position=(WIN_WIDTH, WIN_HEIGHT), shapes=b2PolygonShape(box=(1, WIN_HEIGHT))
)
# Бараанный сбрасыватель (Параметры)
angle = 0
angle_spd = 0
r1 = 140
r2 = 100
x0 = WIN_WIDTH - (r1 + 10)
y0 = WIN_HEIGHT // 2
teeth_num = 12
phase = 360 / (teeth_num * 5)
drum_density = 10000
drum_friction = 1
# Винтовой холодильник (Параметры)
screw_left = 180
screw_right = 670
screw_top = 540 + 7.5
screw_bot = 540 - 7.5
x1 = 620
x2 = 640
y1 = 560
y2 = 520
a = x1
b = y1
step = 30
line_acc = 0
line_spd = 0
line_spd = 0.8
lines = []
for i in range(15):
lines.append([[x1 - step * i, y1], [x2 - step * i, y2]])
restart_line = False
line_ind = 0
# Создание барабанного сбрасываетля
drum = world.CreateDynamicBody(position=(x0, y0))
for i in range(1, teeth_num + 1):
# Первые пол паза
drum_fixture_points = []
drum_fixture_points.append((0, 0))
x = r2 * cos(radians(angle + phase * 0))
y = -r2 * sin(radians(angle + phase * 0))
drum_fixture_points.append((x, y))
x = r2 * cos(radians(angle + phase * 1))
y = -r2 * sin(radians(angle + phase * 1))
drum_fixture_points.append((x, y))
fixture = b2FixtureDef(
shape=b2PolygonShape(vertices=drum_fixture_points),
density=drum_density,
friction=drum_friction,
)
drum.CreateFixture(fixture)
# Зубец
drum_fixture_points = []
drum_fixture_points.append((0, 0))
x = r2 * cos(radians(angle + phase * 1))
y = -r2 * sin(radians(angle + phase * 1))
drum_fixture_points.append((x, y))
x = r1 * cos(radians(angle + phase * 2))
y = -r1 * sin(radians(angle + phase * 2))
drum_fixture_points.append((x, y))
x = r1 * cos(radians(angle + phase * 3))
y = -r1 * sin(radians(angle + phase * 3))
drum_fixture_points.append((x, y))
x = r2 * cos(radians(angle + phase * 4))
y = -r2 * sin(radians(angle + phase * 4))
drum_fixture_points.append((x, y))
fixture = b2FixtureDef(
shape=b2PolygonShape(vertices=drum_fixture_points),
density=drum_density,
friction=drum_friction,
)
drum.CreateFixture(fixture)
# Вторые пол паза
drum_fixture_points = []
drum_fixture_points.append((0, 0))
x = r2 * cos(radians(angle + phase * 4))
y = -r2 * sin(radians(angle + phase * 4))
drum_fixture_points.append((x, y))
x = r2 * cos(radians(angle + phase * 5))
y = -r2 * sin(radians(angle + phase * 5))
drum_fixture_points.append((x, y))
fixture = b2FixtureDef(
shape=b2PolygonShape(vertices=drum_fixture_points),
density=drum_density,
friction=drum_friction,
)
drum.CreateFixture(fixture)
angle += phase * 5
angle %= 360
# Создание винтового холодильника
screw = world.CreateStaticBody(
position=((screw_left + screw_right) / 2, (screw_top + screw_bot) / 2)
)
screw.CreateFixture(
b2FixtureDef(
shape=b2PolygonShape(
box=((screw_right - screw_left) / 2, (screw_bot - screw_top) / 2)
),
density=100000000000,
restitution=0,
)
)
screw_lines = []
for line in lines:
pos = (line[0][0] / 2 + line[1][0] / 2, line[0][1] / 2 + line[1][1] / 2)
screw_line = world.CreateDynamicBody(
position=pos,
shapes=b2EdgeShape(vertices=[line[0], line[1]]),
)
screw_lines.append(screw_line)
# Создаём первую трубу
pipe = world.CreateDynamicBody(position=(x0 - 500, y0 - r2 - 40))
pipe.CreateFixture(
b2FixtureDef(shape=b2CircleShape(radius=1.2), density=3, friction=0.3)
)
# Запускаем цикл симуляции
running = True
while running:
for event in pg.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
running = False
# Шаг симуляции
world.Step(1.0 / 60, 40, 40)
# Управление барабаном
angle_acc = random.random() * 0.1 - 0.05
angle_spd += angle_acc
if angle_spd < 0:
angle_spd = 0
if angle_spd > 0.5:
angle_spd = 0.5
# drum.ApplyForce(b2Vec2(x0, y0), b2Vec2(0, -gravity), True)
drum.position.Set(x0, y0)
drum.angularVelocity = -angle_spd
# Отрисовка
sc.fill((0, 0, 0))
for body in world.bodies:
for fixture in body.fixtures:
shape = fixture.shape
if isinstance(shape, b2PolygonShape):
vertices = [(body.transform * v) for v in shape.vertices]
pg.draw.polygon(sc, (255, 255, 255), [v for v in vertices])
elif isinstance(shape, b2CircleShape):
center = body.transform * shape.pos
radius = shape.radius
pg.draw.circle(sc, (255, 255, 255), center, int(radius * 10))
# Управление винтом
for (i, line), screw_line in zip(enumerate(lines), screw_lines):
line[0][0] -= line_spd
line[1][0] -= line_spd
if line[0][0] < 200:
x_dif = 200 - line[0][0]
y_dif = x_dif / (abs(x1 - x2) / abs(y1 - y2))
a -= x_dif
b -= y_dif
pg.draw.line(sc, WHITE, [a + step, y1], [x1 + step, b], 3)
line[0][0] += x_dif
line[0][1] -= y_dif
screw_line.position.Set(
(line[0][0] + line[1][0]) / 2, (line[0][1] + line[1][1]) / 2
)
if line[0][0] >= line[1][0] and line[0][1] <= line[1][1]:
restart_line = True
line_ind = i
pg.draw.line(sc, WHITE, line[0], line[1], 3)
if restart_line:
restart_line = False
lines.pop(line_ind)
lines.append([[a + step, y1], [x1 + step, b]])
a = x1
b = y1
# pg.display.flip()
# pg.time.wait(10)
pg.display.update()
clock.tick(FPS)
pg.quit()