Page 1 of 1

Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 12:45 pm
by mattpace
Hey, I'm still struggling with some of the basics it seems.

Two questions regarding this code.
1) Why doesn't the box rotate as it hits the platform?
2) What am I doing wrong that prevents applyForce from being applied each frame while the A button is being held down?

Code: Select all
  1. MOAISim.openWindow("Rocket Test", 960, 480)

  2. STAGE_WIDTH = 960

  3. STAGE_HEIGHT = 480

  4. viewport = MOAIViewport.new()

  5. viewport:setScale (960,480)

  6. viewport:setSize(960,480)

  7.  

  8. layer = MOAILayer2D.new()

  9. layer:setViewport(viewport)

  10. MOAISim.pushRenderPass(layer)

  11.  

  12.  

  13. engineA = {}

  14. engineA.on = false

  15. engineA.thrust = 2000

  16.  

  17. physWorld = MOAIBox2DWorld.new()

  18. physWorld:setGravity(0, -1.8)

  19. physWorld:setUnitsToMeters(1/10)

  20. physWorld:start()

  21. layer:setBox2DWorld(physWorld)

  22.  

  23. MOAIGfxDevice.setClearColor(1,1,1,1)

  24.  

  25. staticBody = physWorld:addBody(MOAIBox2DBody.STATIC)

  26. staticBody:setTransform(0,-100,20)

  27.  

  28. dynamicBody = physWorld:addBody(MOAIBox2DBody.DYNAMIC)

  29. dynamicBody:setTransform(-50,0)

  30.  

  31. kinematicBody = physWorld:addBody(MOAIBox2DBody.KINEMATIC)

  32. kinematicBody:setTransform(50,0)

  33.  

  34. rectFixture = staticBody:addRect(-200, -15, 200, 15)

  35. circleFixture = dynamicBody:addCircle(0,0,20)

  36. hexPoly = {

  37.     -10, 20,

  38.     -20, 0,

  39.     -10, -20,

  40.     10, -20,

  41.     20, 0,

  42.     10, 20,

  43. }

  44. hexFixture = kinematicBody:addPolygon (hexPoly)

  45.  

  46. shipBody = physWorld:addBody(MOAIBox2DBody.DYNAMIC)

  47. shipBody:setMassData(30)

  48.  

  49. shipBody:setTransform(-200,-50)

  50.  

  51. shipFixture = shipBody:addRect(-60,-20,60,20)

  52.  

  53. forcesThread = MOAICoroutine.new()

  54. forcesThread:run (

  55.     function()

  56.         while true do

  57.             if (engineA.on == true) then

  58.                 shipBody:applyForce(0,-2000,0,0)

  59.             end

  60.             coroutine.yield()

  61.         end

  62.     end

  63. )

  64.  

  65. --input event callbacks

  66. if(MOAIInputMgr.device.keyboard) then

  67.     MOAIInputMgr.device.keyboard:setCallback(

  68.         function (key, down)

  69.             if(down==true) then

  70.                 if (key=='a') then

  71.                     engineA.on = true

  72.                 end

  73.  

  74.             else

  75.                 if(key=='a') then

  76.                     engineA.on = false

  77.                 end

  78.             end

  79.         end

  80.     )

  81. end

  82.  


Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 2:29 pm
by stun
Regarding your shipBody:applyForce call, the x, y values are zero. In my experience of Box2D you probably want those set to the world coordinates of the shipBody's center itself (or at least relative to the shipBody's centre). As in:

local sx, sy = shipBody:getWorldCenter()
shipBody:applyForce(0, -2000, sx, sy)

Also I typically apply force as a factor of the mass of the body that the force is being applied to. That means the force will scale with the density/mass of the body (should you change it). However I guess you're ok here since you're explicitly setting both the shipBody mass and the force being applied.

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 2:44 pm
by stun
Ah. Actually the problem is because you're explicitly setting the body mass. Your fixtures have no density, which is why they won't rotate. Instead of

shipBody:setMass(30)

Try this, after you create the fixture.

shipFixture = shipBody:addRect(-60,-20,60,20)
shipFixture:setDensity(1)
shipBody:resetMassData()

I'd also suggest reading the Box2d.org documentation, and examining any MOAI Box2D samples you can find. Also consider building and examining the 'Testbed' application that comes with Box2D under the MOAI/3rdParty/box2d*/ folder. That contains a bunch of excellent C++ based Box2D samples. Examining them can give you a lot of hints about the ways to use Box2D.

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 3:08 pm
by stun
Replying to myself again. Your thrust code doesn't work because you're comparing the keys pressed naively. Unfortunately you get key codes rather than ascii strings for the keys being pressed. Instead of 'a' compare the keypress to 97.

Your thrust is also too low. Try: -2000 * 60 * shipBody:getMass(). That's a thrust value, times 60fps * body mass. That'll make the ship body react.

What IDE are you using? Can I recommend http://studio.zerobrane.com/ Zero Brane Studio? It has support for step by step debugging MOAI + Lua code and is superb for seeing what's going on in the bowels of your app.

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 3:29 pm
by halfnelson
here it is as a fiddle

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 3:31 pm
by halfnelson
yep, changing the force was enough to get the big rectangle to move, http://moaifiddle.com/JMUKSPQ4B/3

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 3:35 pm
by halfnelson
and with both of stuns fixes (although less thrust than he recommended)

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 6:31 pm
by mattpace
thanks for the input everyone I'll play around when I get home.

I've been meaning to check out zerobrane maybe I'll do that tonight. Usually it's just vim and bash

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 8:04 pm
by stun
I can heartily recommend it. The integrated debugging on ZBS is invaluable to me. You can also debug callbacks by inserting require('mobdebug').on() in the callback. ZBS has it's quirks, but is also regularly updated and seems to be getting consistently better.

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 11:09 pm
by paulclinger
@stun, thank you for the kind feedback; I'm very glad it's working well for you! Paul.

Re: Box2D body rotation and applyForce each frame

PostPosted: Thu Jun 26, 2014 11:24 pm
by stun
Not a problem.I also made a humble donation a while back. Keep up the good work!

Re: Box2D body rotation and applyForce each frame

PostPosted: Fri Jun 27, 2014 3:53 am
by nosheet
If you're just starting with Box2D I would also recommend taking a look at Chipmunk physics. While I worked with Box2D for several years, I just recently started playing around with Chipmunk in Moai and found out, quite surprisingly, many advantages over Box2D:
- Chipmunk performance around 2 times faster than Box2d on the same scene and comparably similar number of iterations (your mileage may vary) .
- Chipmunk has much simpler API, and you don't need to take such a meticulous care of unit scale like in Box2D.
- Overall physical objects behave much more naturally in Chipmunk than Box2D - Box2D usually requires a lot of fine tuning, plus I found that Box2D simulation is much easier to mess up.
- I may be wrong here, but it seems to me that Chipmunk Moai binding offer more information about collision (through Arbiter), plus there are some very handy methods to check manually if a point, rect, circle or a line intersects with anything in the scene.

That said, I repeat that I didn't test Chipmunk enough to see how it behaves using more complex joint structures, and things like bullets (where I assume Box2D would be more accurate as it can turn on continuous collision detection which prevents the fast bullets to fly through the bodies).
But overall I am very surprised to see how much more comfortable using Chipmunk is, and it's worth looking into.

Re: Box2D body rotation and applyForce each frame

PostPosted: Fri Jun 27, 2014 12:39 pm
by ezraanderson
~
I like chipmunk also, Chipmunk also uses spatial-hashes which can be a massive improvement on collision when scenes have lots of objects. Chipmunk Pro which costs a lot has some interesting feature that I haven't tried.

Chipmunk2D Pro is specifically optimized for speed by offering a multi-threaded and vectorized solver



Chipmunk vs box2d bullets perform about the same, there is a lot of pass-through with both :)

That being said, I do use box2d in "Dead Dark", and I really wish I had stayed with chipmunk(I might switch back).

Re: Box2D body rotation and applyForce each frame

PostPosted: Sat Jun 28, 2014 12:10 am
by stun
Interesting. Chipmunk is based on Box2d isn't it? Is the joint and fixture functionality similar? Would it be possible to map Box2d scenes logically to Chipmunk? I've been be throwing together a RUBE editor scene loader in Moai. Wondering if I can translate my scenes to Chipmunk...

Re: Box2D body rotation and applyForce each frame

PostPosted: Sat Jun 28, 2014 6:28 am
by nosheet
What I've read recently that in the beginning Chipmunk had a solver based loosely on Box2D but then over the years it went to a completely different direction. There are some differences between the two, I guess the biggest one is that the CpSpace is not the same thing as Box2DWorld - where Box2d uses world as a container for all objects, Chipmunk uses space only for objects that need to be updated on frame by frame basis (equivalent on Box2D dynamic bodies). However, bodies that are sensors are not to be inserted into CpSpace - and although they are not inside of the space, they will still capture collisions, etc... This is different from Box2D where if something is not in the world it is completely discarded.

There are also some differences on STATIC bodies in Chipmunk (I never tried MOAICpBody.newStatic(), so far I always used CpSpace.getStaticBody() which means basically I use one static body per scene, adding different shapes to it).

Collision-wise, Chipmunk offers more control that Box2d, offering GROUPS and TYPES. If two objects share the same group (and the group is not 0), they will not interact (ie. if you want to avoid player's bullets to interact between them, put them in the group). This is similar to Box2D filter.
Additionally, bodies can have a TYPE. TYPES offer easy collision detection, so you can easily check detection between the bodies of two collision types through:

space:setCollisionHandler ( 1, 5, MOAICpSpace.BEGIN, onCollision )

which will capture all collisions between the bodies of type 1 (ie. player bullets) and 5 (ie. enemies), which I find vastly easier to use (and update) than setting collision handlers per body.

I didn't try joints so can't tell you how that works.

Re: Box2D body rotation and applyForce each frame

PostPosted: Sat Jun 28, 2014 12:34 pm
by ezraanderson
~
@noSheets, Excellent replay and spot on.

Wondering if I can translate my scenes to Chipmunk


unless performance is an issue I wouldn't bother.

Is the joint


I have never tried joints.

basically I use one static body per scene


This is how I use box2D, I use one "Static object" for all my static objects.



Here is a good comparison between box2D vs Chipmunk: