Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
dynamic change of body type (b2.DYNAMIC_BODY to b2.KINEMATIC_BODY and reverse) — Gideros Forum

dynamic change of body type (b2.DYNAMIC_BODY to b2.KINEMATIC_BODY and reverse)

linker_ualinker_ua Member
edited November 2011 in General questions
Hi, is it possible to change type of phisical body in function onEnterFrame()

For example I want to stick 2 objects like at this preview:
http://www.freeimagehosting.net/d149f

I detect collision but don't know how to stick it...
Have you any ideas how to solve this solution?

Comments

  • atilimatilim Maintainer
    hi,

    You need to create weld joint to stick them together.
  • Thanks! I found it in reference manual! :) Hope that I will understand it...
  • atilimatilim Maintainer
    :) weld joint is one of the easiest joints to use :)
  • linker_ualinker_ua Member
    edited December 2011
    Kinematic Object - barriers[1].body
    Dynamic Object - actors[1].body

    Creation weld joint on collision enter:
    jd = b2.createWeldJointDef(barriers[1].body, actors[1].body, barriers[1].body:getPosition(), actors[1].body:getPosition())
    weldJoint = world:createJoint(jd)
    It give's me fatal error!

    Expression IsLocked == false

    When I use this code "onButtonPress" - than it works, else - fatal error..
    Works not so well! help to find my error
    -------------------------------------------------------- this don't works
    local function onBeginContact(event)
    	local fixtureA = event.fixtureA
    	local fixtureB = event.fixtureB
    	local bodyA = fixtureA:getBody()
    	local bodyB = fixtureB:getBody()
    	objectA = bodyA.name
    	objectB = bodyB.name
    	if (objectB == "Barrier") or (objectA == "Barrier") then
    	jd = b2.createWeldJointDef(barriers[1].body, actors[1].body, barriers[1].body:getPosition(), actors[1].body:getPosition())
    		weldJoint = world:createJoint(jd)
    	end
     
    end
    world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
    --------------------------------------------------------this works
    function onClick(event)
    	if event:getTarget() == rightright then
    		jd = b2.createWeldJointDef(barriers[1].body, actors[1].body, barriers[1].body:getPosition(), actors[1].body:getPosition())
    		weldJoint = world:createJoint(jd)
    	end
    end
    rightright:addEventListener("click", onClick)
    ----------------------------------------
    Thanks a lot! :)
  • atilimatilim Maintainer
    edited December 2011
    Hi,

    Box2d locks the world while it dispatches events BEGIN_CONTACT, END_CONTACT, PRE_SOLVE and POST_SOLVE. And if the world is locked, these functions give assertion:

    b2.World:createBody
    b2.World:destroyBody
    b2.World:createJoint
    b2.World:destroyJoint
    b2.Body:createFixture
    b2.Body:destroyFixture
    b2.Body:setActive
    b2.Body:setPosition

    For your case, the solution is to create your joint outside of these events. (For example, you can set a flag and check this flag on ENTER_FRAME and if it's true create your joint)
  • linker_ualinker_ua Member
    edited December 2011
    do you mean something like this?
    r1 = 50 --radius of first body
    r2 = 94 --radius of second body
     
    local function onEnterFrame()
    	world:step(1/60, 8, 3)
    	local x1,y1 = actors[1].body:getPosition()
    	local x2,y2 = barriers[1].body:getPosition()
    	local length = math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
    	print(length)
    	if (length < (r1+ r2 + 20) and length > (r1+ r2)) and weldJoint == nil then
    		jd = b2.createWeldJointDef(barriers[1].body, actors[1].body, barriers[1].body:getPosition(), actors[1].body:getPosition())
    		weldJoint = world:createJoint(jd)
    	end
    end
    But if FPS drop, one frame when length value will be higher than (r1+ r2 + 20), next frame - after some seconds, then we could lost value when length < (r1+ r2 + 20).
  • atilimatilim Maintainer
    edited December 2011
    Not exactly.

    I mean set a flag on onBeginContact function and test this flag on onEnterFrame, if true create your weld joint.
    local function onBeginContact(event)
      local fixtureA = event.fixtureA
      local fixtureB = event.fixtureB
      local bodyA = fixtureA:getBody()
      local bodyB = fixtureB:getBody()
      local objectA = bodyA.name
      local objectB = bodyB.name
      if (objectB == "Barrier") or (objectA == "Barrier") then
        createWeldJoint = true
      end
    end
    world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
     
    local function onEnterFrame()
      if createWeldJoint == true then
        local jd = b2.createWeldJointDef(barriers[1].body, actors[1].body, barriers[1].body:getPosition(), actors[1].body:getPosition())
        weldJoint = world:createJoint(jd)
        createWeldJoint = false
      end
    end
    stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
Sign In or Register to comment.