Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Box2D and Gideros and, the ever mystifying, Units — Gideros Forum

Box2D and Gideros and, the ever mystifying, Units

totebototebo Member
edited October 2015 in General questions
Hi guys,

I've released two games using Box2D and so have a good idea how it works. However, one thing I've never fully understood are the units.

This is from Box2D's manual:
http://www.box2d.org/manual.html
Box2D is tuned for MKS units. Keep the size of moving objects roughly between 0.1 and 10 meters. You'll need to use some scaling system when you render your environment and actors. The Box2D testbed does this by using an OpenGL viewport transform. DO NOT USE PIXELS.
This reads to me as if the units used in Box2D are meters. Why, then, does this code fail to create a triangle with 1 meter sides?
require "box2d"
 
local sprite = Sprite.new()
 
-- Sets up a world with -10 gravity and allows sleeping bodies
world = b2.World.new( 0, -10, true ) 
 
-- Creates a 1x1 meter triangle
local body = world:createBody{type = b2.STATIC_BODY} 
local polygonShape = b2.PolygonShape.new() 
polygonShape:set(0,0, 1,0, 1,1)	
local fixture = body:createFixture{shape = polygonShape}
 
-- Adds and shows debug sprite
local sprite_debug_draw = b2.DebugDraw.new()
world:setDebugDraw( sprite_debug_draw )	
sprite:addChild(sprite_debug_draw)
stage:addChild( sprite )
Instead of a triangle, this is the result:
image

Now, if I change the pixel scale Gideros use to 10 (from the default 30) it does produce a triangle:
require "box2d"
 
b2.setScale(10)
 
local sprite = Sprite.new()
sprite:setScale(100)
 
-- Sets up a world with -10 gravity and allows sleeping bodies
world = b2.World.new( 0, -10, true ) 
 
-- Creates a 1x1 meter triangle
local body = world:createBody{type = b2.STATIC_BODY} 
local polygonShape = b2.PolygonShape.new() 
polygonShape:set(0,0, 1,0, 1,1)	
local fixture = body:createFixture{shape = polygonShape}
 
-- Adds and shows debug sprite
local sprite_debug_draw = b2.DebugDraw.new()
world:setDebugDraw( sprite_debug_draw )	
sprite:addChild(sprite_debug_draw)
stage:addChild( sprite )
Like so:
image

My guess is that the units Box2D use are not meters after all, and when I set the triangle too small, it can't be rendered. If that's true, how big is a Box2D unit in meters? Are the sides of the triangle actually 0.01 meters? 0.1 meters?

Please help shed some light on this, before I stop trying to understand how it works and just make everything very big.

:)

Niclas
Screen Shot 2015-10-02 at 10.52.17.png
170 x 270 - 9K
Screen Shot 2015-10-02 at 10.54.21.png
169 x 273 - 9K
My Gideros games: www.totebo.com

Comments

  • john26john26 Maintainer
    Although Box2D works in metres, everything in Gideros works in pixels. So when you define Box2D shapes in Gideros you should set their size in pixels. Gideros then internally scales down by the number you set with b2.setScale (default 30).

    So basically Gideros has "got your back" on this! The advice "DO NOT USE PIXELS" is already being followed internally by Gideros. Just use pixels throughout.

    However, if you have a very high res game then you may find 30 is not enough. Eg 3000x3000 pixel body would correspond to 100 m x 100 m in the b2d world which might get a bit hairy. So in that case maybe b2.setScale(100).
  • totebototebo Member
    edited October 2015
    Wow, that explains it. And also leads to another question: How do I keep things between 0.1 and 10 Box2D meters, as is recommended by the manual? I suppose this actual value is somewhat obfuscated by Gideros and its setScale()? Just use a very high setScale value?
    My Gideros games: www.totebo.com
  • If I setScale(100) and create a box that's 200 square, what would the actual Box2D meters be? Blimey, this is making me dizzy.
    My Gideros games: www.totebo.com
  • john26john26 Maintainer
    It would be 2 m wide in b2d world. (and would appear to be 200 pixels on screen)

    For example here is how I create a square body in Nebula:
    local radius=10
     
    egox,egoy=ego:getPosition()  -- ego is a Sprite, so x,y in pixels
     
    body=world:createBody({type=b2.DYNAMIC_BODY, position={x=egox,y=egoy}, 
    				angle=10, allowSleep=false})
     
    shape=b2.PolygonShape.new()
    shape:setAsBox(radius,radius)
     
    body:createFixture({shape=shape, density=1, restitution=0.0, friction=0.6})
    so the body will be 20 pixels wide and 20/30 = 0.666 m wide
  • Okay, great. For it to work in my case I'll use setScale(100) and think of Box2D units as centimeters. The graphics I'm adding will need to be scaled on various devices, but the Box2D units have to stay the same to adhere to the 0.1-10 meter guide. I hope this is a good way of going about it. :)
    My Gideros games: www.totebo.com
  • All is right, Gideros handles position for you, just one remark, it is not in pixels, but in logical units you set in your project properties. which might equal to pixels and might not. :)

    and only the dimensions and positions are scaled internally. Other units such as velocity, gravity or speed are kept as same.

    also more info here

    http://giderosmobile.com/forum/discussion/1311/box2d-scaling-factor/p1
  • Thanks, now it's crystal clear. Or, at least, not a mystery anymore. :)
    My Gideros games: www.totebo.com
Sign In or Register to comment.