Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Box2d question — Gideros Forum

Box2d question

xGuiltxGuilt Member
edited July 2013 in General questions
I've been using box2d lately and managed to pull off an angry birds like trial with the walls and the projectile but the problem i can't seem to solve is creating custom shapes. I've managed to use boxes for the polygon shape of the walls and other objects and circle for the shape of the ball but i can't seem to make custom shapes like triangles or even complex shapes like forming a flag or a spike or something else.

I've read through the net and can't seem to understand and implement some samples i've found. Oh and i'm using the physics helper from http://www.giderosmobile.com/forum/discussion/373/display-object-physics-helper-library

Comments

  • ar2rsawseenar2rsawseen Maintainer
    edited July 2013
    @xGuilt I have no idea about physics helper, but in Gideros to create complex shapes, you would need to use b2.ChainShape:
    http://appcodingeasy.com/Gideros-Mobile/Creating-terrain-in-Gideros-using-ChainShape

    But it mostly can be used as terrain (box2d limitation) and can not be dynamic.

    If you want a dynamic complex shape, then you need b2.EdgeShape. But it also has its own (box2d) limitations. I think it can only have up to 8 vertices and they should be defined clockwise order.

    If you need dynamic shape which should have more than 8 vertices, you will need to create a body of multiple b2.EdgeShape fixtures :)

    But I think that all the physics editors, like physics helper, should automatically convert the drawn shape to the best code case.
  • xGuiltxGuilt Member
    I've looked into the codes of the helper and it seemed like there is no support for any other shapes besides circle and boxes so i have to make customs without the helper :D

    Do you have a tutorial on edgeshapes? I mean even just a small piece of code which shows how to define the shape.
  • ar2rsawseenar2rsawseen Maintainer
    edited July 2013
    oops, I have no idea why I said EdgeShape, I meant PolygonShape, thats what you get answering posts in the morning in hurry :)

    Here's a simple code:
    local polygonShape = b2.PolygonShape.new()
    polygonShape:set(1,4, 2,6, 3,7) --x,y pairs up to I think 8 vertices
    And then pass it to fixture as shape
  • xGuiltxGuilt Member
    edited July 2013
    hahaha, to be fair, edgeshape does exist :D

    Is the x and y of the shape based on the object or is it based on the x and y of the whole stage? Like if i have a sprite on 300,550, do i have to base the shape from that location or what?

    Edit: Ok, i've tried to add some things to the helper and came up with this
    	elseif args.triangle then
    		thisShape = b2.PolygonShape.new()
    		thisShape:set(bodyDef.x1, bodyDef.y1, bodyDef.x2, bodyDef.y2, bodyDef.x3, bodyDef.y3)
    it works nice and i managed to create a triangle body and matches well with the sprite it belongs to. Thanks @ar2rsawseen.

    next up is collisions and the only samples i've seen so far are all collisions within the body and not the edges only -,-. study study haha :D
  • plamenplamen Member
    Polygon shapes are naughty. Plenty of limitations. Be careful with those :)
  • xGuiltxGuilt Member
    edited July 2013
    Ok found a new problem.
    Collisions are working fine now and i'm getting the intended collision output except when i'm trying to remove a body on collision. I keep getting an error saying "world is locked" how do i unlock the world?

    Edit: ok i've found a way around. I set the world:step to (0,0,0) just before removing the bodies and it worked nicely. Is this a safe move? i mean sometimes the player suddenly hangs and must be closed randomly when a collision is made
  • ar2rsawseenar2rsawseen Maintainer
    @xGuilt it does not sound like a safe move.
    To ensure proper simulation of physics values passed to world:step should always be the same.
    The world lock notice is given due to the fact you are removing a body in the same enterFrame event where you received collision.
    Most quick and dirty hack is to remove the body using a Timer delay, like:
    Timer.delayedCall(1, function()
        --remove body here
    end)
    But usually there should be a mechanism, where you stack all the bodies to be removed and you remove them on enter frame event before calling world:step :)
  • xGuiltxGuilt Member
    edited July 2013
    @ar2rsawseen wow this works really perfectly. Thanks :D
    right now i'm having problem with collisions in implementing an out-of-bounds for the object. I'll ask if ever i hit a dead end. Thanks again, you're a big help :D

    edit: scratch that, found the dead end already. I've been trying to destroy the body of the ball object that makes contact with the boundaries i've made and when i try to destroy the ball body, it says "Body is already destroyed" I've tried resorting to just moving the ball object and it's body back to it's original place but doesn't work either. The force applied to the ball just as it made contact with the boundary is still applied to it. Is there a work around this?
  • xGuiltxGuilt Member
    i have another question. Is it possible to make a collision event exclusive to specific objects only? like a ball can only collide with a box and run a command while a triangle can collide with the box but will not run a command.

    right now i have a collision detector
    				local function onBeginContact(e)
    				local fixtureA = e.fixtureA
    				local fixtureB = e.fixtureB
    				local BodyA = fixtureA:getBody()
    				local BodyB = fixtureB:getBody()
     
    					if BodyA.name == "target" then
    						stage:removeChild(target)
    						Timer.delayedCall(1, function()
    						world:destroyBody(BodyA)
    						end)
    						score = score + 5000
    						scoreField:setText("Score: ".. score)	
    					end
     
    					if BodyA.name == "boundary" then
     
    						Timer.delayedCall(5, function()
    						self.ball:removeFromParent()
    						--world:destroyBody(BodyB)
    						scoreField:setText("dead")
    						end)
    					end
    			end
     
    			world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
    But the problem i have is that i have 4 objects: ball,block(s),target and boundary(just a body, no image) What i intend to do is that when the ball makes contact with the wall, it will disappear but what's happening is that anything that makes contact with the boundary fires the commands in it's if. Can't really think of what's going wrong since the collision detection for "target" is working fine, it doesn't register the collisions from the blocks and boundary and will only fire the event when the ball makes contact.
  • ar2rsawseenar2rsawseen Maintainer
    @xGuilt well I've tried to do something like that in GiderosCodingEasy, but underneath it's the same:
    if (BodyA.name == "target" and BodyB.name == "ball") or
    (BodyB.name == "target" and BodyA.name == "ball") then
        --do this collision
    end
  • xGuiltxGuilt Member
    Thank you @ar2rsawseen that works perfectly :D
Sign In or Register to comment.