0
\$\begingroup\$

Hi I am working on a PyBox2D game and it became quite complex and I need to learn about collisions, so I made this very simple script in order to learn collision setting more effectively, however I am completely stuck, I really do not know how to detect whether the collision occurred and how to use that information

I have been stuck on this topic for about a week now. I googled it, looking for tutorials but nothing helped (mostly because these tutorials were not written in python).

So... I would be more than grateful if you showed me on my script for example how to change color of the rectangle when it hits the ground (I am not showing you what I have already tried because there were various ways using e.g. memory locations and I want to make this example as simple as possible.

import pygame
import numpy as np
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


pygame.init()

PPM = 15
SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
pos_X = SCREEN_WIDTH/PPM/3
pos_Y = SCREEN_HEIGHT/PPM

Box_2_World = world(gravity = (0.0, -9.81), doSleep = True)

Rectangle = Box_2_World.CreateDynamicBody(position = (pos_X+5, pos_Y + 5),
                                    angle = np.pi/4,
                                    fixtures = b2FixtureDef(
                                        shape = b2PolygonShape(box= (5,5)),
                                        density = 1000,
                                        friction = 1000,
                                                            ))
Ground = Box_2_World.CreateStaticBody(position = [0,0],
                                    angle = 0,
                                    fixtures = b2FixtureDef(
                                        shape = b2PolygonShape(box= (50,1)),
                                        density = 1000,
                                        friction = 1000,
                                                            ))


screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
colors = {dynamicBody: (133, 187, 101, 0),  staticBody: (15, 0, 89, 0)}
FPS = 24
TIME_STEP = 1.0 / FPS
running = True

def my_draw_polygon(polygon, body, fixture):
    vertices = [(body.transform * v) * PPM for v in polygon.vertices]
    vertices = [(v[0], SCREEN_HEIGHT - v[1]) for v in vertices]
    pygame.draw.polygon(screen, colors[body.type], vertices)
polygonShape.draw = my_draw_polygon

while running:
    # Draw the world
    screen.fill((255, 255, 255, 255))

    for body in Box_2_World.bodies:
        for fixture in body.fixtures:
            fixture.shape.draw(body, fixture)

    # Simulate dynamic equation in each step
    TIME_STEP = 1.0 / FPS
    Box_2_World.Step(TIME_STEP, 10, 10)

        # 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()

Thank you VERY much for any response. I cannot move forward in my game without this...

P.S. I have posted almost identical question on Stack Overflow because the answer is really important to me, I apologize for spamming

EDIT: I have found a link which solves exactly what I want to do, but it is written in C++ and I do not understand it :( http://www.iforce2d.net/b2dtut/collision-callbacks

\$\endgroup\$
0
\$\begingroup\$

warning: I don't know any python programming but I may help you a little bit? As per your code example it seems that the only thing you are missing is the b2ContactListener which will tell you when two fixtures collide:

from iforce2d:

Now, we want Box2D to tell us when the contact state changes. Make a subclass of b2ContactListener and implement the BeginContact/EndContact functions as follows:

I don't know how you make listener in python but in c++:

//at global scope
MyContactListener myContactListenerInstance;
//in FooTest constructor
m_world->SetContactListener(&myContactListenerInstance);

In lua it's (gideros engine example):

world = b2.World.new(0, -9.81, true)
world:addEventListener(Event.BEGIN_CONTACT, self.onBeginContact, self)
world:addEventListener(Event.END_CONTACT, self.onEndContact, self)

And then you do stuff in the contact listeners on bodyA and bodyB.

Now the question is how do you call listeners in python. Hope this will guide you in the right direction.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.