Monday, December 28, 2009

End of the year status

Hello to the loyal couple of you who continue to refresh this lonely blog. :)

I scrapped the branch I started on 6 months ago of the new version of pybox2d. The upstream library Box2D (now also hosted on Google Code) has seen a good deal of changes since then.

The most notable changes are:
  • The new dynamic tree-based broadphase
  • This makes it such that there will no longer be a maximum proxy count. So, you won't see b2_maxProxies assertion errors when you try to create too many colliding shapes.
  • Normalized and simplified class interfaces
  • The improved interface makes for an easier time in creating Pythonic properties.
  • Kinematic bodies
  • These special bodies are essentially static in that they don't respond to collisions, but they can have their velocities set. I'd imagine they would be most useful as, for example, rotating platforms in some side-scroller.
  • The removal of shape definitions and the addition of fixtures
  • I don't see this as offering much benefit to us on the Python end, but it allows shapes to be created and used without being attached to bodies. It makes for a great deal of changes for those attempting to port their code to the most recent version.
  • One-sided platforms
  • No more SetMassFromShapes() nonsense
  • New collision callback system
  • Weld and friction joints
  • Controllers have been removed
  • This is unfortunate, but was anyone actually using them?

Here are some things I'm trying to do with the upcoming version of pybox2d:
  • Unit tests
  • I'm attempting to use unit tests (suggestions would be welcome on this, as I'm fairly new to it) as I go along to ensure all of the properties work and I don't break things along the way.
  • Hide all getters and setters, while keeping things accessible in properties
  • I like this a lot, but I hate seeing the ugly __ClassName_GetterHere-type things when doing a dir(). Should I just skip the hiding and make it semi-private with _Getter to avoid the lengthy name-mangling? Should I re-implement __dir__ to hide these? I would just rather not have users calling the functions when there are perfectly good properties in place.
  • Properly downcast joints/shapes
  • So calls like b2Joint.downcast() (or previously getAsType()) are no longer necessary.
  • Custom __setattr__?
  • I've been toying with the possibility of using a custom setattr to keep the user from trying to set shadow class instance variables that don't exist in the real class. Maybe I'll make it an option or decide after performance tests.
  • Eventual 64-bit and Python 3.x compatibility
  • Pythonic-ish initializers?
  • I've also been considering having the ability to do, for example:
    body.CreateFixture(b2FixtureDef(shape=b2CircleShape(radius=1), density=1, friction=0.3))
    Any interest in that? It's simple sugar, but it could be useful.
  • Scrapping deprecated stuff, hiding unusable classes, pickling, etc.

Any thoughts? What would you like to see in the new version? Yell at me and tell me what I'm doing wrong before I get too far into it.


  1. Sounds very good. I would assign a low priority to name hiding and high priority to eliminating getAsType.

    Do you know if anybody uses the kinematic bodies for particle systems?

    I think the initializers with default values would be nice too.

  2. Thanks for the input, Fahri.

    I only know of the flash demos using the kinematic bodies (except for the original testbed) See here. There are some pretty fantastic ones there.

    My worry with name hiding is simply that wading through a dir() of an object leads to a page of obfuscated names, blocking the useful ones. With them in the way, I think the documentation would have to be that much better -- but I hardly have the patience for that. :)

    The initializers appear to be working well. Things like the one shown in this log message are now possible.

  3. Hey it's great to read about the status for pybox2d again :)

    I personally like the idea of hiding all getters and setters while keeping things accessible in properties. The cleanliness aspect appeals to me, where I feel like I'm using something that's integrated into the Python way of doing things, rather than being an API dump.

  4. Hi Michael,
    Thanks for the comment. :)
    I think I will do the accessor hiding.

    As a quick update: the kwargs for initializers works quite well now, and getAsType() is a thing of the past (yay). I ported a testbed example, ApplyForce, which you can see here. There are tons of other changes, if you're bored enough to read through the changelogs.

    My __setattr__ thing is only partially useful, I will likely scrap that idea. The thing is that you can pass the shadow classes to Python functions and still have access to properties outside of what is available on the C++-end. It's when you, say, set body.myvariable=1 and then get that body as a result of some Box2D callback -- it will be gone. Hardly intuitive. It could be "fixed" by an additional layer between userData and the user, buffering these additional variables while allowing access to the normal userData, but that would come at a great overhead, and I don't think I'm willing to do that.

    Anyway, do either of you have any thoughts on improving the testbed? I'd be up for rewriting most of it if I had a clear goal.

  5. I think this shows how nice dir() could be. But does it need to be fast?

  6. Good work. Personally, I wouldn't worry too much about the dir() stuff.

    I've started on a two-layer wrapper for Box2D, where the lower layer currently is pybox2d 2.0.2b1, though I intend to update it to bleeding edge. It seems promising so far.

    Have you considered a straight SWIG (or Boost.Python wrapper), then writing a pythonic wrapper on top of that?

  7. Looks interesting, Mikael.

    I know SWIG well enough by now that I'd be hard pressed to switch over to boost, though everyone speaks highly of it. I've also thought about writing nice and Pythonic ones on top of the library, but I'm probably not the most qualified to write it (as I can never seem to peg down exactly what people want).

    In any case, the new version should be much more nicely rounded on all sides -- I'll make an updated post later today after some coding.

  8. Sounds good. I agree that it's hard to tell what people want.

    I haven't used SWIG or Boost.Python a lot, so I can't say which one is better by me, but I guess either is fine.