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.

Tuesday, June 9, 2009

Status?

pybox2d isn't dead just yet.

A few days ago, I started porting the bleeding-edge version of the library.

Some changes include the addition of b2Fixture, contact listener changes, a new way to create edge chains, and significant algorithm changes. More information on these C++-specific changes can be found on the forums and the Box2D SVN changelog.

As it is a departure from the previous builds, it will stay as a branch on here at least until it's significantly improved over the trunk. I'm not entirely happy about the significant API changes that are occurring, but I'm just bringing to Python what Erin Catto and others are making available to the C++-world. I guess what I'm trying to say is, well, don't shoot the messenger.

Friday, March 6, 2009

Project spotlight: Mekanimo


Mekanimo is a 2D physics simulator. In minutes, you can create simulations, interactive games and puzzles, dazzling graphics and share them with others through the Internet.
Mekanimo really surprised me with its professional-looking user interface. It allows for the creation of worlds with customizable scripting, various plots, and so many other things. I enjoyed trying out the exhibits like the marble pump, which require you to copy and paste the code into Mekanimo for now -- I think the author Fahri has been putting much more into the application itself than its website.

It's still got a ways to go and unfortunately is (for now?) closed source, but keep an eye on it. I expect it to turn into a really nice and polished learning/design tool some day.

pybox2d svn r184

Bugfix: Linux/x64 build issue.
Updated to Box2D r204:
b2Body now has these additional functions:
  • SetLinear/AngularDamping (additionally accessible by body.linearDamping = (x,y) )
  • SetStatic
  • SetFixedRotation (additionally accessible by body.fixedRotation = True)
b2Shape:
  • SetSensor
A few functions' names changed since some of the 2.0.2b1 accessor code was my own, but chances are you were using the properties anyway:

IsRotationFixed -> IsFixedRotation (property fixedRotation)
CanSleep -> IsAllowSleeping (property allowSleep)

Wednesday, February 25, 2009

2.0.2b1 Released!

Since 2.0.2b0, there have been a good deal of changes to pybox2d:

  • Code structure completely reorganized
  • Doxygen comments converted to docstrings (should be a bit more friendly now, but still a bit C++'ish in places)
  • Lists and tuples may be used anywhere in place of b2Vec2's, and all of the tests have been updated to reflect this
  • Save/load state (pickling support for worlds)
  • Bug fix: Seg faults during DebugDraw/etc callbacks
  • Bug fix: userData reference counting causing leaks
  • Bug fix: getType() didn't work on line joints
  • Bug fix: TestSegment now returns from (-1,0,1) and not a bool
  • b2PolygonDef.setVertices() added, supports either b2Vec2 or list/tuple, so no need to specify. Old setVertices_tuple/b2Vec2() are deprecated.
  • New pretty printing style. It takes up a good deal of space, but it's actually readable.
  • New examples: bezier edges with thin line segments, a simple belt, basic pickling example (might needs some updating)
  • (Optionally compilable) C++ assertion failures turned into Python exceptions
    Additional properties and accessors to make coding easier (see below)
  • Many tests were updated and rewritten to be cleaner
  • Added b2CheckPolygonDef and deprecated the Python ported version. This version adds (optional) additional checks to ensure that your shape is convex and properly sized to not have strange results
  • Added GetVertices() for b2EdgeShapes. Creating one b2ChainDef results in many b2EdgeShapes, so this properly loops through each connected shape and gets the vertices in order
  • Box2D source updated, b2GravityController fixed
  • A fix for not allowing b2Body/Joint/Controller/Shapes as dictionary keys. Don't know how I missed this one. Still won't be picklable unfortunately.
  • Basic iterators have been added: b2World (iterates over bodies), b2Body (iterates over shapes), b2Controller (iterates over bodies), b2PolygonShape (iterates over vertices)
There are several code-breaking features that you might run into:

  • The library is now called Box2D (and not the cumbersome Box2D2)
  • Controllers now follow the factory style (see the buoyancy test for more information)
  • b2Distance updated (see here if this affects you)
  • b2Body.GetShapeList() used to return only first shape, now returns actual list
  • b2World.GetBodyList/Joint() used to return only first body, now returns actual list
  • All occurences of the ugly 'm_' have been removed. This might require some changes in your code, since this applies to all b2Joint.m_* and others, not just testbed stuff.

The following are the additional properties added. Most are just for convenience and make the definition (e.g., b2ShapeDef) symmetric with the output (e.g., b2Shape). Ones with * are changeable; the rest are read-only:
b2Worldgravity*, jointList, bodyList, groundBody, worldAABB, doSleep
b2Shapefilter*, friction*, restitution*, density*
b2Jointtype, userData, body1, body2, collideConnected
b2CircleShape radius, localPosition
b2PolygonShapevertices, coreVertices, normals
b2Body massData*, position*, angle*, linearDamping, angularDamping, allowSleep*, isSleeping, IsRotationFixed, isBullet*, angularVelocity*, linearVelocity*, shapeList

Basic epydoc documentation is now available here. The testbed is no longer included in the installer, so please download it separately here.

Releasing for all these operating systems all by myself is time consuming, confusing, and tough at times. I'm sure I got something wrong, so please go easy on me. :) Do let me know if something doesn't work for you, though.

Enjoy!

Tuesday, January 20, 2009

Update on Pickling

As of this post, the latest svn revision, r148, has pickling support which is working great on the testbed. I'm rather excited about it, as it's somewhat of a powerful and unique feature.

For those who can compile the library, check out the testbed. It works like your regular quicksave (F5)/quickload (F7) system. There's an additional test, test_pickle.py, that shows how easy it is to load a pickled world. As far as the code itself goes, there's still some commenting to be done, but it should be readable.

Monday, January 12, 2009

SWIG and Pickle

I have yet to see any site that explains how to pickle swig objects well enough. SWIG objects exist both on the Python and C++ side.

Without calling the __init__ function on the Python class instance of a SWIG object, it doesn't exist as far as SWIG is concerned. So you'll get a TypeError on the 'self' parameter of your functions.

If we were using old-style classes, __getinitargs__ would work well enough. Since we aren't, as far as I can tell, it's necessary for us to call the initializer ourselves.
def generic_setstate(self, dict):
self.__init__()
for key, value in dict.iteritems():
setattr(self, key, value)

def generic_getstate(self):
return dict((var, getattr(self, var)) for var in
__pickle_vars__[self.__class__.__name__])
If you have the dict __pickle_vars__ set up such as:
__pickle_vars__ = { 'myclass' : ['x', 'y'], 'myclass2' : ['zz'], ... }
You can then set:
myclass.__getstate__=generic_getstate
myclass.__setstate__=generic_setstate


EDIT 2009/1/14:
If you use properties for all those C++ getters/setters (as you should be doing), you can then iterate over all of the properties for a much cleaner solution. It takes even more tweaking to get pickling to work with outputs from factory products (e.g., trying to pickle a b2Body instead of a b2BodyDef). Expect something like this to show up soon in pybox2d. :)

Friday, January 9, 2009

pybox2d svn r136

Added something I've wanted to for a long time.

Anywhere there's a b2Vec2, you should now be able to pass in a [length-2] list, tuple, or None -- (0,0). As I learn more about SWIG every time I try to throw some more functionality into Box2D.i, I'm more and more impressed with how much can be done with it.

Changes can be seen in test_ApplyForce.py and test_Web.py. I'll eventually update the rest of the testbed examples.

Oh yeah, also fixed a longtime standing bug with unset userData causing seg faults.

Any other things you can think of that would be convenient? I'll probably allow matrices in list format.

If you notice any side-effects, please let me know as always.

Friday, January 2, 2009

distutils, oh how I hate you...

It took me forever and a day to get the original setup.py working for pybox2d, and then some people came along and told me how it was unnecessarily complex. And that it didn't work in the standard way and was somewhat confusing. Great.

With a push from the user snickell, I worked on restructuring the code-base to get it to conform to standard distribution methods.

I've decided that I will no longer install the testbeds and things to c:\Python2x\Box2D for Windows users and will simply just offer them in a separate archive as I see some other libraries do.

*EDIT*
My problem has been resolved and everything is apparently working now. I'm ready for another release -- but with nothing really new on the Box2D end, I guess there's nothing to do but wait.

A few questions for you faithful few who reload this page every once in a while:
Windows users: Do you prefer MSI's or executables for your libraries?
Linux users: Any interest in an RPM distribution?

Any other comments/etc. about the releases are always welcome.