我正在尝试通过重现以下示例来过滤Box2D世界中发生的碰撞:https://github.com/pybox2d/pybox2d/blob/master/examples/collision_filtering.py
我的世界中有四个类别,分别是汽车,车轮,建筑和行人,我想过滤哪个实例与哪个实例相撞,并且可能的输出之一是(伪代码)
if contact.FixtureA.isinstance(Pedestrian) and contact.FixtureB.isinstance(Car):
print("You have caused a traffic accident")
我有这组类别
CAR_CATEGORY = 2
PEDESTRIAN_CATEGORY = 4
BUILDING_CATEGORY = 8
box2world = world(gravity =(0.0, 0.0), doSleep =True)
我也尝试过这种方法:但是它不起作用(什么都不做)
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)
并且我将其应用于给定的类(为简单起见,仅以行人类为例):
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}
然后我用pygame绘制身体并运行世界
但是我对如何继续感到困惑,如何使用碰撞过滤器中的信息来例如从上方打印有关事故的句子?
非常感谢 编辑:我找到了一个链接,它可以完全解决我想做的事情,但是它是用C ++编写的,我不理解 http://www.iforce2d.net/b2dtut/collision-callbacks
答案 0 :(得分:2)
嘿,我刚刚回答了您关于stackexchange的问题:-)
对于碰撞很简单:
local filterData = {
categoryBits = player,
maskBits = wall + nme + platform,
groupIndex = 0
}
fixture:setFilterData(filterData)
玩家,墙壁, nme ,...是整数变量(必须为2的幂):
player = 1
wall = 2
nme = 4
... = 16, 32, 64, 128, 256, ...
categoryBits =您要测试碰撞的主要对象
maskBits =您添加(带有+)所有主要对象可以碰撞的数字。
最好将数字存储为变量,否则看起来像这样:
local filterData = {
categoryBits = 1,
maskBits = 2 + 4 + 8 + 16 ...,
groupIndex = 0
}
fixture:setFilterData(filterData)
:-)
答案 1 :(得分:1)
回答您的第二条更复杂的评论,因此我将其添加为另一个答案。
您自己无法处理碰撞,Box2D会为您完成,但是您需要进行设置。
-创建您的世界
world = b2.World.new(0, 24, true)
-将听众附加到您的世界(用于碰撞处理)
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)
-在游戏循环中,您需要调用Box2D更新
self.world:step(1/60, 1, 1)
-然后在这里,您将在这些box2d函数侦听器中检查每个对象的冲突
-- 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
这是一个使用 gideros mobile http://giderosmobile.com/用LUA编写的快速示例。
关于box2d的必选网站当然是: https://www.iforce2d.net/b2dtut/
这是一个广泛的主题,您可能需要关注一些youtube tut。即使它不是用py编写的,box2d的工作原理也一样,因此您只需要适应py。 一些链接可能会有所帮助: https://www.youtube.com/playlist?list=PLZm85UZQLd2SXQzsF-a0-pPF6IWDDdrXt
这就是我使用box2d学习的方法。希望有帮助吗?