Using Box2D With Line Object?

Newbie preamble: I’m a programmer by trade, but new to Corona SDK and Box2D. Please forgive me if I break any forum rules out the gate.

I’ve been messing around with Box2D and noticed something odd when using a line as a static physics object. It seems that that one half of the line will be static and act like it should upon collision, but the other half does not appear to have any sort of body at all as objects fall straight through it. See below for a full example I’ve written up to demonstrate. I’ve even tried manually defining the shape using the line shape property when registering it as a physics object.

Any thoughts would be greatly appreciated!

Please tell me this is some silly oversight on my part. :slight_smile:

[lua]local physics = require “physics”
physics.start( true )
local background = display.newRect(0, 0, display.viewableContentWidth, display.viewableContentHeight)
background:setFillColor (255, 255, 255)
local line = display.newLine(0, 160, display.viewableContentWidth, 160)
local ball1 = display.newCircle( display.viewableContentWidth/4, 20, 20)
ball1:setFillColor(250, 0,0)
local ball2 = display.newCircle( (display.viewableContentWidth/4)*3, 20, 20)
ball2:setFillColor(0, 250,0)
line:setColor(0,0, 0)
line.width = 5
physics.addBody(line, “static”)
physics.addBody(ball1)
physics.addBody(ball2)[/lua] [import]uid: 172008 topic_id: 30394 reply_id: 330394[/import]

Hi there,

I believe Box2D expects all physics objects to be enclosed (and convex) polygons – it is not set up to handle lines. The behavior you’re seeing is, I think, a symptom of Box2D not knowing how exactly do to with the line. It’s effectively treating one side of the line as the “outside”, which produces collisions, and the other side as the “inside”, which doesn’t.

Instead of creating an actual line, you should instead create a very thin rectangle, which will look just like a line to a user, but also play nicely with Box2D.

Hope this helps.

  • Andrew [import]uid: 109711 topic_id: 30394 reply_id: 121781[/import]

Ah, I see. Thank you for the quick and detailed response!

I had played around with using a rectangle instead but couldn’t figure out how to rotate from a corner as opposed to the center (with a line, I was simply re-drawing every time). From what I’ve read, physics objects always rotate from the center.

Guess I’ll work on a creative solution for that problem as opposed to making the line idea work. :slight_smile: [import]uid: 172008 topic_id: 30394 reply_id: 121782[/import]

About the rectangle rotating around one of its corners - it depends on how you employ it, but basically if you join it to something through the corner, it will rotate around that corner. [import]uid: 160496 topic_id: 30394 reply_id: 121785[/import]

No problem.

It actually is possible to rotate a physics object about a point other than the corner if you define the physics object using the [lua]shape[/lua] property, and the shape you define is not centered around 0,0. Here’s an example.

[blockcode]
require(“physics”)
physics.start()
physics.setDrawMode(“hybrid”)
physics.setGravity(0,0)

obj = display.newRect(100, 100, 0, 0)

physicsShape = {0,0, 50,0, 50,20, 0,20 }
physics.addBody( obj, “dynamic”, { density=30.0, friction=0.5, bounce=0.3, shape=physicsShape } )

rotate = function()
obj:rotate(1)
end
Runtime:addEventListener( “enterFrame”, rotate )
[/blockcode]

However, to use this method, you’ll notice that the rectangle I created has zero height and width. To track a display object against the physics object, you would need to do some additional work to “track” a separate display object against the physics object, like the following:

[blockcode]
require(“physics”)
physics.start()
physics.setDrawMode(“hybrid”)
physics.setGravity(0,0)

phys = display.newRect(100, 100, 0, 0)
rect = display.newRect(100, 100, 50, 20)
rect.xReference, rect.yReference = -25, -10

physicsShape = {0,0, 50,0, 50,20, 0,20 }
physics.addBody( phys, “dynamic”, { density=30.0, friction=0.5, bounce=0.3, shape=physicsShape } )

rotate = function()
phys:rotate(1)
end
Runtime:addEventListener( “enterFrame”, rotate )

follow = function()
rect.x, rect.y, rect.rotation = phys.x, phys.y, phys.rotation
end
Runtime:addEventListener( “enterFrame”, follow )
[/blockcode]

Hope this helps.

  • Andrew [import]uid: 109711 topic_id: 30394 reply_id: 121786[/import]

That’s great! This gives me more than enough to work with. Thanks again - you’re a life saver, or at least a time saver. :slight_smile:
[import]uid: 172008 topic_id: 30394 reply_id: 121788[/import]

Hi there,

I believe Box2D expects all physics objects to be enclosed (and convex) polygons – it is not set up to handle lines. The behavior you’re seeing is, I think, a symptom of Box2D not knowing how exactly do to with the line. It’s effectively treating one side of the line as the “outside”, which produces collisions, and the other side as the “inside”, which doesn’t.

Instead of creating an actual line, you should instead create a very thin rectangle, which will look just like a line to a user, but also play nicely with Box2D.

Hope this helps.

  • Andrew [import]uid: 109711 topic_id: 30394 reply_id: 121781[/import]

Ah, I see. Thank you for the quick and detailed response!

I had played around with using a rectangle instead but couldn’t figure out how to rotate from a corner as opposed to the center (with a line, I was simply re-drawing every time). From what I’ve read, physics objects always rotate from the center.

Guess I’ll work on a creative solution for that problem as opposed to making the line idea work. :slight_smile: [import]uid: 172008 topic_id: 30394 reply_id: 121782[/import]

About the rectangle rotating around one of its corners - it depends on how you employ it, but basically if you join it to something through the corner, it will rotate around that corner. [import]uid: 160496 topic_id: 30394 reply_id: 121785[/import]

No problem.

It actually is possible to rotate a physics object about a point other than the corner if you define the physics object using the [lua]shape[/lua] property, and the shape you define is not centered around 0,0. Here’s an example.

[blockcode]
require(“physics”)
physics.start()
physics.setDrawMode(“hybrid”)
physics.setGravity(0,0)

obj = display.newRect(100, 100, 0, 0)

physicsShape = {0,0, 50,0, 50,20, 0,20 }
physics.addBody( obj, “dynamic”, { density=30.0, friction=0.5, bounce=0.3, shape=physicsShape } )

rotate = function()
obj:rotate(1)
end
Runtime:addEventListener( “enterFrame”, rotate )
[/blockcode]

However, to use this method, you’ll notice that the rectangle I created has zero height and width. To track a display object against the physics object, you would need to do some additional work to “track” a separate display object against the physics object, like the following:

[blockcode]
require(“physics”)
physics.start()
physics.setDrawMode(“hybrid”)
physics.setGravity(0,0)

phys = display.newRect(100, 100, 0, 0)
rect = display.newRect(100, 100, 50, 20)
rect.xReference, rect.yReference = -25, -10

physicsShape = {0,0, 50,0, 50,20, 0,20 }
physics.addBody( phys, “dynamic”, { density=30.0, friction=0.5, bounce=0.3, shape=physicsShape } )

rotate = function()
phys:rotate(1)
end
Runtime:addEventListener( “enterFrame”, rotate )

follow = function()
rect.x, rect.y, rect.rotation = phys.x, phys.y, phys.rotation
end
Runtime:addEventListener( “enterFrame”, follow )
[/blockcode]

Hope this helps.

  • Andrew [import]uid: 109711 topic_id: 30394 reply_id: 121786[/import]

That’s great! This gives me more than enough to work with. Thanks again - you’re a life saver, or at least a time saver. :slight_smile:
[import]uid: 172008 topic_id: 30394 reply_id: 121788[/import]