Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Detect collision of kinematic bodies — Gideros Forum

Detect collision of kinematic bodies

ar2rsawseenar2rsawseen Maintainer
edited February 2012 in General questions
Is it possible?

If there are two kinematic bodies draggable by user, and they shouldn't be overlapping (or atleast detect if they're overlapping).

I know by default that kinematic and static bodies ar colliding (dispatching collision event) only with dynamic bodies, but in this case I don't need dynamic body, because gravity is applied, and I need that body to stay in position where user put it.

Any interesting ideas are welcomed. ;)

Likes: sslivka

Dislikes: red032, talis, r033rt

+1 -1 (+1 / -3 )Share on Facebook

Comments

  • atilimatilim Maintainer
    edited February 2012
    maybe welding a dynamic body to your kinematic just for dispatching collision events? (I know it's a weird way :-B)

    Likes: duke2017

    +1 -1 (+1 / -0 )Share on Facebook
  • Well actually that is awesome idea.

    Was experimenting with switching bodies from kinematic to dynamic on dragging, which was a bad idea.

    Weding should be relatively easier. Thanks
  • Something like this ? The joint does not work on the code below
    circle = Bitmap.new(Texture.new("1.png"))
     
    local actors = {}
    local world = b2.World.new(0, 9)
    local bodyDef1 = {type = b2.DYNAMIC_BODY, position = {x = 260, y = 210},  fixedRotation = true, linearDamping = 1}
    local body1 = world:createBody(bodyDef1)
    local shape1 = b2.PolygonShape.new()
    shape1:setAsBox(50, 50)
    body1:createFixture{shape = shape1, density = 1}
    body1.name="circle1"
     
    stage:addChild(circles[1])
    actors[body1] =  circles[1]
     
    local bodyDef2 = {type = b2.STATIC_BODY, position = {x = 260, y = 210}, fixedRotation = true, linearDamping = 1}
    local body2 = world:createBody(bodyDef2)
     
    local jointDef = b2.createWeldJointDef(body1,body2,0,0,0,0)
    weldJoint = world:createJoint(jointDef)
  • ar2rsawseenar2rsawseen Maintainer
    Hello @jarosmartin
    actually found a much better way, simply do not use sensors if you need collisions. Use collision filters instead:
    http://www.giderosmobile.com/DevCenter/index.php/Forum_FAQ#How_can_I_use_collision_filters.3F

    But if you are interested in Welding joints, then you should use common point of both bodies, in your case their center (260,210) coordinates, like this:
    local jointDef = b2.createWeldJointDef(body1, body2, 260, 210, 260, 210)
    weldJoint = world:createJoint(jointDef)


  • jarosmartinjarosmartin Member
    edited July 2012
    Hello @ar2rsawseen and thanks for the update !. I think my problem is the "multitouch.lua" from the touch Explorer example. I've attached the class. It returns index, position X, position Y. It seems the bodies' positions never get updated. If position[2] position[3] are assigned to bodies inside onEnterFrame then there is a weird behavior (the circle starts rotating around the finger).
     
    --WeldJoint Example
    require "box2d"
    b2.setScale(20)
     
    local circle = Multitouch.new("1.png",1)
     
    local actors = {}
    local world = b2.World.new(0, 3)
     
    local body1 = world:createBody{type = b2.STATIC_BODY, position = {x = 280, y = 410}}
    local circleFilter = {categoryBits = 2, maskBits = 1}
    body1.name="circle"
    local circleShape = b2.PolygonShape.new()
    circleShape:setAsBox(50, 50)
    local fixture1 = body1:createFixture{shape = circleShape, density = 1.0, friction = 0.1, restitution = 0.8, filter = circleFilter}
     
    stage:addChild(circle)
    actors[body1] = circle
     
    -------------------------------box-------------------------------
    local box = Bitmap.new(Texture.new("box.png"))
    box:setX(300)
    box:setY(600)
    box:setAnchorPoint(0.5,0.5)
    stage:addChild(box)
    local boxShape = b2.PolygonShape.new()
    boxShape:setAsBox(40,40)
    local body3 = world:createBody{type = b2.STATIC_BODY, position = {x=300, y=600}}
    local boxFilter = {categoryBits = 1, maskBits = 2}
    body3.name="box"
    fixture2 = body3:createFixture{shape = boxShape, density = 0, filter = boxFilter}
     
    local function onBeginContact(event)
    	-- you can get the fixtures and bodies in this contact like:
    	local fixtureA = event.fixtureA
    	local fixtureB = event.fixtureB
    	local bodyA = fixtureA:getBody()
    	local bodyB = fixtureB:getBody()
     
    	print(bodyA.name.."INSIDE"..bodyB.name)
    end
     
    local function onEndContact(event)
    	-- you can get the fixtures and bodies in this contact like:
    	local fixtureA = event.fixtureA
    	local fixtureB = event.fixtureB
    	local bodyA = fixtureA:getBody()
    	local bodyB = fixtureB:getBody()
     
    	print(bodyA.name.."OUTSIDE"..bodyB.name)
    end
     
    world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
    world:addEventListener(Event.END_CONTACT, onEndContact)
     
    -- step the world and then update the position and rotation of sprites
     
    local function onEnterFrame()
    --Do something to update postion of body1
    	world:step(1/60, 8, 3)
    	for body,sprite in pairs(actors) do
    		sprite:setPosition(body:getPosition())
    		sprite:setRotation(body:getAngle() * 180 / math.pi)
    	end
    end
     
    stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
  • ar2rsawseenar2rsawseen Maintainer
    You can't drag physical bodies as shown in multitouch explorer, that would feel unnatural and is against how box2d works. You need to use mousejoint for that purpose:

    http://appcodingeasy.com/Gideros-Mobile/Dragging-Box2d-object-in-Gideros-Mobile
  • Like this. Great !
    --MouseJoint Example
    require "box2d"
    b2.setScale(20)
    local actors = {}
    local world = b2.World.new(0, 0)
    local ground = world:createBody({})
    local bodyDef = {type = b2.DYNAMIC_BODY, position = {x = 160, y = 110}, fixedRotation = true, linearDamping = 1}
    local body = world:createBody(bodyDef)
    body:setLinearDamping(100)
    body:setAngularVelocity(0)
    local shape = b2.PolygonShape.new()
    shape:setAsBox(25, 25)
    local fixture = body:createFixture{shape = shape, density = 1, restitution=0, friction=1}
    body.name = "circle"
     
    local sprite = Bitmap.new(Texture.new("1.png", true))
    sprite:setAnchorPoint(0.5, 0.5)
    stage:addChild(sprite)
     
    actors[body] = sprite
     
    -------------------------------box-------------------------------
    local box = Bitmap.new(Texture.new("box.png"))
    box:setX(300)
    box:setY(600)
    box:setAnchorPoint(0.5,0.5)
    stage:addChild(box)
    local boxShape = b2.PolygonShape.new()
    boxShape:setAsBox(40,40)
    local body3 = world:createBody{type = b2.STATIC_BODY, position = {x=300, y=600}}
     
    body3.name="box"
    fixture2 = body3:createFixture{shape = boxShape, density = 0, isSensor=true}
     
    local function onBeginContact(event)
    	-- you can get the fixtures and bodies in this contact like:
    	local fixtureA = event.fixtureA
    	local fixtureB = event.fixtureB
    	local bodyA = fixtureA:getBody()
    	local bodyB = fixtureB:getBody()
     
    	print(bodyA.name.."INSIDE"..bodyB.name)
    end
     
    local function onEndContact(event)
    	-- you can get the fixtures and bodies in this contact like:
    	local fixtureA = event.fixtureA
    	local fixtureB = event.fixtureB
    	local bodyA = fixtureA:getBody()
    	local bodyB = fixtureB:getBody()
     
    	print(bodyA.name.."OUTSIDE"..bodyB.name)
    end
     
    world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
    world:addEventListener(Event.END_CONTACT, onEndContact)
     
    -- step the world and then update the position and rotation of sprites
    local mouseJoint = nil
     
    -- create a mouse joint on mouse down
    function sprite:onMouseDown(event)
    	if self:hitTestPoint(event.x, event.y) then
    		local jointDef = b2.createMouseJointDef(ground, body, event.x, event.y, 100000,100)
    		mouseJoint = world:createJoint(jointDef)
    	end
    end
     
    -- update the target of mouse joint on mouse move
    function sprite:onMouseMove(event)
    	if mouseJoint ~= nil then
    		mouseJoint:setTarget(event.x, event.y)
    	end
    end
     
    -- destroy the mouse joint on mouse update up
    function sprite:onMouseUp(event)
     
    	if mouseJoint ~= nil then
    		world:destroyJoint(mouseJoint)
    		mouseJoint = nil
    	end
    end
     
    -- register for mouse events
    sprite:addEventListener(Event.MOUSE_DOWN, sprite.onMouseDown, sprite)
    sprite:addEventListener(Event.MOUSE_MOVE, sprite.onMouseMove, sprite)
    sprite:addEventListener(Event.MOUSE_UP, sprite.onMouseUp, sprite)
     
    local function onEnterFrame()
    	world:step(1/60, 8, 3)
     
    	for body,sprite in pairs(actors) do
    		sprite:setPosition(body:getPosition())
    		sprite:setRotation(body:getAngle() * 180 / math.pi)
    	end
    end
     
    stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
Sign In or Register to comment.