问题
I am trying to filter collisions occurring in my Box2D world by reproducing this example: https://github.com/pybox2d/pybox2d/blob/master/examples/collision_filtering.py
I have four classes in my world, Car, Wheel, Building, and Pedestrian, I want to filter which instance collided with which and one of the possible outputs is (pseudo-code)
if contact.FixtureA.isinstance(Pedestrian) and contact.FixtureB.isinstance(Car):
print("You have caused a traffic accident")
I have this set of categories
CAR_CATEGORY = 2
PEDESTRIAN_CATEGORY = 4
BUILDING_CATEGORY = 8
box2world = world(gravity =(0.0, 0.0), doSleep =True)
I also tried this: but it doesn't work (it does nothing)
class myContactListener(b2ContactListener):
def __init__(self):
b2ContactListener.__init__(self)
def BeginContact(self, contact):
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
pedestrian = None
car = None
for ud in (body_a, body_b):
if isinstance(ud, Pedestrian):
pedestrian = ud
elif isinstance(ud, Car):
car = ud
if car is not None and pedestrian is not None:
if began:
print("It does stuff")
else:
print("It does something")
def EndContact(self, contact):
pass
def PreSolve(self, contact, oldManifold):
pass
def PostSolve(self, contact, impulse):
pass
box2world = world(contactListener=myContactListener(),gravity =(0.0, 0.0), doSleep =True)
and I apply this in given classes (only class Pedestrian shown as example for simplicity):
class Pedestrian():
def __init__(self,box2world, ped_velocity =25, position =None,):
if position == None:
position = [5,5]
self.ped_velocity = ped_velocity
self.position = position
self.box2world = box2world
self.nearest_building = 0
self.body = self.box2world.CreateDynamicBody(position = position,
angle = 0.0,
fixtures = b2FixtureDef(
shape = b2CircleShape(radius = 1),
density = 2,
friction = 0.3,
filter = b2Filter(
categoryBits=PEDESTRIAN_CATEGORY,
maskBits=BUILDING_CATEGORY + CAR_CATEGORY,
groupIndex=0,
)))
self.current_position = [self.body.position]
self.body.userData = {'obj': self}
And then I draw the bodies and run the world using pygame
But I am confused about how to continue, how could I use the information from the collisionfilter to be able to for example print the sentence about the accident from above?
Thank you very much 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
回答1:
to answer your second comment that is more complex so I add it as another answer.
You don't handle collisions yourself, Box2D does it for you but you need to set things up.
- create your world
world = b2.World.new(0, 24, true)
- attach listeners to your world (for collisions handling)
world:addEventListener(Event.BEGIN_CONTACT, self.onBeginContact, self)
world:addEventListener(Event.END_CONTACT, self.onEndContact, self)
world:addEventListener(Event.PRE_SOLVE, self.onPreSolveContact, self)
world:addEventListener(Event.POST_SOLVE, self.onPostSolveContact, self)
- in your game loop you need to call Box2D update
self.world:step(1/60, 1, 1)
- then ANSWER IS HERE you check collisions for each objects in those box2d functions listeners
-- collisions handler
function LF_Bullet:onBeginContact(e)
local bodyA = e.fixtureA:getBody()
local bodyB = e.fixtureB:getBody()
if bodyA.type == 100 or bodyB.type == 100 then
self.removebullet = true
end
if bodyA.type == 200 and bodyB.type == 100 then
bodyA.isdead = true
end
if bodyA.type == 100 and bodyB.type == 200 then
bodyB.isdead = true
end
if bodyA.type == 201 and bodyB.type == 100 then
bodyA.isdead = true
end
if bodyA.type == 100 and bodyB.type == 201 then
bodyB.isdead = true
end
end
function LF_Bullet:onPreSolveContact(e)
end
function LF_Bullet:onPostSolveContact(e)
end
function LF_Bullet:onEndContact(e)
end
This is a quick example written in LUA using gideros mobile http://giderosmobile.com/.
A must website regarding box2d is of course: https://www.iforce2d.net/b2dtut/
It is a vast subject and you may want to follow some youtube tuts. Even if it is not written in py, box2d works the same so you just have to adapt to py. Some links that may help: https://www.youtube.com/playlist?list=PLZm85UZQLd2SXQzsF-a0-pPF6IWDDdrXt
That's how I learned using box2d. Hope that helps?
回答2:
hey I just answered your question on stackexchange :-)
For collisions it's easy:
local filterData = {
categoryBits = player,
maskBits = wall + nme + platform,
groupIndex = 0
}
fixture:setFilterData(filterData)
player, wall, nme, ... are integers variables (must be power of 2 numbers):
player = 1
wall = 2
nme = 4
... = 16, 32, 64, 128, 256, ...
categoryBits = main object you want to test collisions on
maskBits = you add (with +) all the numbers the main object can collide with.
It's better to store the numbers as variables otherwise it would look like:
local filterData = {
categoryBits = 1,
maskBits = 2 + 4 + 8 + 16 ...,
groupIndex = 0
}
fixture:setFilterData(filterData)
:-)
来源:https://stackoverflow.com/questions/58710804/how-to-detect-collision-using-pybox2d-and-use-that-information