Learning Box2d and Lua — Gideros Forum

#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Learning Box2d and Lua

Member
edited February 2012
I'm starting from scratch and trying to figure out how to do some simple things like get the falling crates demo to drop crates of different dimensions. My 1st question (and many more will follow) is how do I change the size of a Bitmap or Sprite to match the size of a b2body? I can create different size crates but the costume for these b2bodies doesn't match what it's behind. Help!

Likes: larf, Yan

Tagged:
+1 -1 (+2 / -0 )Share on Facebook

• Guru

The Physics/SleepingBodies example might be doing exactly what you describe?

The "onTimer" function randomly chooses the x/y scales (sx,sy) then scales the x/y dimensions of both the box2d body [see the line with: shape:setAsBox(34.5 * sx, 34.5 * sy)] and the associated sprite [see the line with: sprite:setScale(sx, sy)].

Likes: Cliff76

+1 -1 (+1 / -0 )Share on Facebook
• Member
Ah, the one example I didn't open. Thank you much! I'm confused now. These examples seem to work directly in pixels. I thought box2d was based on MKS (meters/kilos/seconds)?
• Guru
Ah, the one example I didn't open. Thank you much! I'm confused now. These examples seem to work directly in pixels. I thought box2d was based on MKS (meters/kilos/seconds)?
I seem to stay confused ... I'll take a shot at an answer though ...

Box2d does work in MKS. That example is just making very large bodies. To make smaller objects in the example:

* scale down the size and positions of the objects in the box2d world (e.g., by 1/10)

* when you use body:getPosition() to get the position of a body, scale the position back up (e.g., by 10) to position the sprite associated with the body
• Maintainer
edited February 2012
@Cliff76 You're right, box2d units are in meters, and images and objects sizes are in pixels.

There is a funciton b2.setScale(scale) using which you can scale all pixel units, by default it's value is 30, so all your objects are already scaled. As I understood, then it's done internally and nothing additional is required from you, then simply provide scale.

@ndoss Correct me if I'm wrong, but I think you don't need to scale input nor output by yourself, it is done internally.
• Guru
@ndoss Correct me if I'm wrong, but I think you don't need to scale input nor output by yourself, it is done internally.
You're probably right ... but it doesn't seem to work for me? I'm likely doing something wrong.
• Maintainer
edited February 2012
Well, we can always wait for atilim on that.

By the way, how do you determine it's not working for you?

You should use it once, just right after calling require "box2d" (Well actually before using anything else from box2d, but you get the point)
• Guru
Well, we can always wait for atilim on that.

By the way, how do you determine it's not working for you?
When I go into one of the examples and call b2.setScale, it doesn't seem to change the scale of the graphics.
• Maintainer
no no, it's doesn't change the size of graphics itself. It changes the ratio between 1m and 1 pixel in box2d simulation. It will change nothing from visual point of view. Only how simulations behave and maybe even get some performance, if internal calculations would be performed in interval between 10 and 0.1.

For example if your largest object is 300px and your smallest object is 3px, then by setting scale to 30, box2d would handle them as they were 10 units and 0.1. It won't change the actual size. But simulations may behave differently. Try setting scale 0 and look and dynamic object moving and collisions. They should be pretty jigged.
• Guru
@ar2rsawseen -- thanks for the clarification
• Maintainer
@ar2rsawseen exactly correct.
(as a side note, only the dimensions and positions are scaled internally. Other units such as velocity, gravity or speed are kept as same.)

• Member
Maybe I'm just dense or something but I'm still stuck! In the Sleeping Bodies example the scale is set to 20, yet it still use pixel sizes in all the calculations. position is set using a random value between 0 and 320 the screen pixel width and setShapeAsBox is called with half pixel size of the crate graphic. The collision detection example seems to work this way as well.
• Maintainer
yes, the set 20 scale works internally in Box2d

For example you set position
body:setPosition(120, 200)

inside set position function 120 and 200 are divided by 20 (120/20 = 6, 200/20 = 10) and values 6 and 10 are used.

And if you use get position function
local x,y = body:getPosition() then inside getPosition function values 6 and 10 are taken and multiplied by scale (6*20 = 120, 10*20 = 200) and returned back to you.

As you see, you don't even notice the scaling, it's all done internally, you operate with same pixels sized you have for your objects. Think of it as automatic optimization.
• Maintainer
edited February 2012
exactly as @ar2rsawseen said

Although not very logical, you can change the scale between setPosition and getPosition to get the internal values:
 ```b2.setScale(20) body:setPosition(120, 200) b2.setScale(1) local x,y = body:getPosition() --> returns 6, 10```
• Member
Thank you, that's exactly what I was after. Being new to Lua and Box2d I looked for tutorials and stumbled over FlashyTodd's Actionscript box2d tutorials. I was following along with that as well as a few other box2d tutorials and everyone seemed to hint the explicit conversion from pixels to units was a necessary step and common cause of problems. I like that it is handled behind the scenes! However, I see "setPosition(x,y)" does conversion internally but getPosition returns values unconverted? Are there any other unbalanced setter/getters that one should be aware of?
• Maintainer
I've done some series of articles on Gideros Box2d with examples, you might try start with one and see, maybe you'll find couple of useful things.

http://appcodingeasy.com/Gideros-Mobile/Gideros-Box2D-basics

Likes: Cliff76

+1 -1 (+1 / -0 )Share on Facebook
• Member
@ar2rsawseen Those articles are on point! Thanks! =D>
• Maintainer
@Cliff76 sorry for making things complicated. setter and getter functions are balanced. Here:
 ```b2.setScale(20) body:setPosition(120, 200) b2.setScale(1) --> in fact you shouldn't change the scale in the middle local x,y = body:getPosition()```
setting the scale in the middle of the application brakes the balance on purpose. You usually set the scale just after calling require("box2d"). If you delete the 3rd line above, setPosition and getPosition sets/returns the same values.

• Member
@atilim I completely missed the 2nd setScale. I see what you mean now, thanks.
• Member
Stuck again, self.body:getPosition() returns a number type? How do I get the y position of a b2body? I tried self.body:getPosition().y but I get an error "tried to index a Number value"
• Maintainer
Hi,

Lua can return multiple values and self.body:getPosition() return two values: x and y. You can write:
 `local x, y = self.body:getPosition()`
to get both values.

Likes: ___

+1 -1 (+1 / -0 )Share on Facebook
• Member
edited March 2012
Dang! Still not used to multiple return values in Lua! ) Thanks again!
• Maintainer
You're welcome Also, there is great information about this issue at chapter 5 of the book Programming in Lua: http://www.lua.org/pil/index.html#5