Hacker News new | past | comments | ask | show | jobs | submit login
Planck.js – JavaScript rewrite of Box2D physics library (github.com/shakiba)
245 points by vivaladav on April 6, 2017 | hide | past | favorite | 67 comments



Planck.js developer here! I have posted this to reddit before, so I'm just going to include it here too:

I have ported/rewritten Box2D physics engine to JavaScript, for cross-platform HTML5 game development. Planck.js includes entire Box2D algorithms, a simple HTML5 Testbed, more than 50 examples and some new game prototypes. The project is pre-released and there may still be minor issues, which I'm working to fix. So far I have spent more than 400 hours for developing this project and it consists of around 20k lines of code.

https://github.com/shakiba/planck.js

My main motivations for working on this project are:

- Taking advantage of Box2D's efforts, achievements and community knowledge

- Developing readable and maintainable JavaScript code

- Optimizing the library for web and mobile platforms

- Providing a JavaScrip-friendly API

Your feedback is highly appreciated, and I hope you use Planck.js to make some awesome games soon!


The more things change the more they stay the same...I did a manual port of http://www.box2dflash.org/ to JS a few years back to make educational simulations:

http://schoolnotez.com/ http://appynote.com/app-store/ (see the pendulum example.)

good job.


Great work! I decided to directly rewrite Planck.js from Box2D C++ code, so that I can keep it updated (as far as I remember that flash port was few years old).


I remember using your site to learn and play around with Box2d. Thank you for your effort


Wish this was around back when the only other option was Box2DJS, which was a Flash conversion, maybe even nothing more than a trans-pile. I haven't had a use for it in years, but I will definitely keep it on hand. A commendable contribution! I thank you 100 times over!


I used that version just fine in my projects.


How does this compare to Box2DJS, the automatic conversion of the ActionScript version of Box2D?

http://box2d-js.sourceforge.net/


Box2DJS is based on an old Flash port and as far as I remember it didn't work well when I tested it (for example second example on the website doesn't work currently, right click to switch to next example). I decided to directly port from C++ so that I can keep it updated.


How does this compare to other 2d physics libraries like p2.js?


P2.js was a great effort and is a nice project. It is also inspired by Box2D and its API is very similar, however Box2D algorithm and architecture are more sophisticated and stable, and is already used in many popular games (such as AngryBirds) and game dev libraries (such as Apple's SpriteKit) so I decided to rewrite Box2D to make it available to JS/HTML5 game developers as well.


Why not just compile to asm.js?


Really great work, gives me some ideas. Thank you.


It baffles me that all those JS physics library never provide proper docs or even an API reference and always link to the C++ Box2D manual as if it was an acceptable alternative. Always have to guess what the JS equivalent is but even then you're in for a surprise: https://github.com/shakiba/planck.js/blob/master/CHANGES.md


I'm guessing it comes down to "writing docs takes lots of time, and when you're a lean operation priority goes to making stuff work."

I'm sure once the project matures it'll get a documentation pass, but the project is quite young.


As a dev of an unrelated lib who cares about making good documentation this is a really valuable comment; I'm guilty of doing this partially for example in https://github.com/franciscop/drive-db where I link to MongoDB platform for the more advanced selectors.

In my experience good documentation takes around 3x-5x of the time of writing the code (excluding tests and tutorials), so while I hate seeing libraries without a decent documentation I totally understand it.

Edit: also it is in alpha, where writing documentation many times backfires you and you have to remove large pieces of it wasting your time.


I've found writing documentation and trying to explain to others why the API is the way it is frequently makes me completely reconsider and redesign the API to be better. So no, you really should start on documentation right away, because what you're calling "waste" right now is a feature.


That is interesting, I think the way I do it is quite similar: normally I write the examples that would go in the documentation first then work around it, but I don't write the whole text+proofreading which is what takes most of the time for me.

Edit: see this "others" folder for example: https://github.com/franciscop/server/tree/master/others


That does help, but I've found that getting people to try using your API does an even better job of informing you about your design decisions.

Last time I was building a novel API, I opted to provide commented example code for documentation, recruited several members of the intended audience to try out the API, and just offered to answer questions directly. I wrote out actual documentation in preparation for the "official 1.0 release."

At some point it comes down to choosing how to spend your limited time. Writing documentation isn't going to be a "waste," but it's probably not high ROI because your early adopters are likely familiar with the problem domain anyway.


Oh cmon I never ever said writing documentation is a waste!

What I mean is that writing the final documentation with all that implies before you even know what the API is going to look like is a waste. Though I agree with the parent, stubbing some docs to get a better feeling of what the docs look like is valuable.


Those are changes to internals, there are only few API differences which are explained on readme page. Anyway, I agree with you, a new API doc would be very helpful.


On one hand, I agree with you that linking to the documentation of another library, in another language, isn't very helpful. On the other hand, it's an open-source project. It has to start somewhere, and referencing the original docs is better than nothing. If you've looked at a variety of libraries along these lines and found them lacking, perhaps you're an ideal person to contribute better docs to this project.


For me, an example is worth 10 pages of documentation. The documentation is good for reference but only after you understand the ideas behind it.

One of the biggest criteria I have for using a library is whether they have a rich set of examples to draw from.


Conversely, after the initial struggle getting the ideas behind it, examples are worthless and documentation is king.


Sometimes. Examples are good at giving concrete working code to use as a basis but they only express a few ideas. Documentation will let you understand the different pieces so you can build what you like.

Both are beneficial for different scenarios. I find I use examples much more often but when examples fail, documentation is necessary.


Good documentation has tons of examples! For me the gold documentation is jQuery. When I didn't know enough JS the beginning was cryptical but the examples below made it, when I was experienced I could just read the beginning for the footprint.


You reminded me, that I made a Javascript game with Box2D five years ago: http://www.loudrider.com/

I was using Box2DWeb https://github.com/hecht-software/box2dweb . It could be good to mention other javascript versions of Box2D and say, what are the differences between them and your library.


Neat game. The time trial scores seem a bit strict though. I mean, I can't seem to get 3 stars on the first level of the tutorial even though it's literally just holding down a single button. Am I missing something? :P


You should "lean backwards" to push on the back wheel to decrease friction and accelerate faster :) BTW. you can play it on your phones and other devices with browsers, too :)


IvanK, your demos are pretty cool and renderer looks solid. You should put your work on GitHub for others to build on. These days I don't know of a solid 2D WebGL renderer that is decided for games specifically. There is pixi, which is great, but its not made necessarily for game dev


Thank you. I made the library IvanK.js mainly for myself (but there are hundreds of people using it, too). I fixed all known bugs during the last 5 years and implemented all I wanted to implement, so now I consider it to be a "complete thing". The rest should be built on top of it, not inside the library.

PIXI.js is cool (actually they use some of my code), but I think that my library is easier and more comfortable to use.


that sounds awesome - can you put your IvanK.js library on github and link to it? I'd love to use it as well, specifically together with planck.js


It has its own website http://lib.ivank.net/ . You could find it using Google. This website is already known to Google and others and I think it would be confusing to have it on two different places.


The game is very cool! :)


I love that you kept the tried and true Box2D API as that'll make porting what I'm working on much easier. I've been using the emscripten version [1] but the automatic port from C++ makes the JS API quite painful at times, especially with the manual memory management that's required to prevent leaks. Thanks for doing this!

[1]: https://github.com/kripken/box2d.js


In most of the demos, you can grab the objects and drag them around. In other demos (like 8 ball) you can 'shoot' them.

I wasn't expecting it to be so smooth and precise... this is really great work. It makes me realize why I got a C in physics, because I could never make this!


It's not just physics though, as I remember Erin the author of box2d mentioning that most of the work is concerned with allocating and deallocating tiny pieces of memory. After that the physics are rather simple Newtonian equations.


But then, in order to calculate those newtonian equations, you need an integrator, right?


This seems like really great work.

I could have sworn this was done already but looking at all the search results that came up the alternatives seem awful at first glance. At the very least this project is better at marketing.

As an aside, does it bother anyone else that the 8-ball demo has two extra pockets in the table?


Thank you! Just fixed it! I actually LOLed very hard!


Since these types of projects are way outside my day to day I've had a hard time keeping track of them and also could have sworn I've seen something similar. I rather enjoyed the additional pockets. But I also enjoy bumper pool.


Or that the asteroids game has (a lot of) friction?


space dust


Off topic:

I'm interested in a physics library based on waveform collapse. It seems like performance would be so much better. A body could arc through empty space, without writing any new data to the GPU, just the clock changing, until an "observation" event where you wanted to check whether it interacted with anything, at which point you collapse some number of waveforms into particles, do rigid body math, and then generate new wave equations for the subsequent timeline. There would be no centralized "tick" just a tree of nested timelines forking whenever your code decided to do an observation. When rendering you'd just render all the waves, which means you can do arbitrary precision. You could do 90hz rendering of the waves for head position, while only collapsing particles every half second or so. Do that at multiple scales and you have a physics system with arbitrary fidelity traded off for performance. You can have different ticks at different scales (waves within waves). The properties of a given surface would just be the sum of maybe 3-4 waves at different levels of detail. You could collapse these independently depending on how much compute you wanted to devote at different levels. I think this would pair well with an SDF-based renderer, which lets you have screen-aligned surfaces that kind of act like particles already.

It would lead to bizarre physics bugs, but I suspect they would be very interesting and could lead to interesting gameplay. Perhaps they might even help us learn things about how our own universe works.


Cool! Is there a big advantage to a manual rewrite vs emscripten? With emscripten folding in updates from Box2D 'native' would be easier, it seems.


Thanks! Repost from reddit:

The main reasons that I decided not to use Emscripten port was usability:

- First, it is generated and unreadable code, therefore it is impossible to understand how it actually works in JS to use it optimally, debug it or improve it for JS. While it possible to improve Planck.js if it is not as fast in some cases, it is not possible to do anything with Emscripten port.

- Second, API of Emscripten port does not follow JavaScript conventions and is inconvenient to use in JavaScript. For example it returns an empty object, instead of no object (null or undefined) as last element of a linked list (which is very confusing in JS). Here are some more usage comparisons:

    // emscripten
    var bd_ground = new Box2D.b2BodyDef();
    var ground = world.CreateBody(bd_ground);
    var shape0 = new Box2D.b2EdgeShape();
    shape0.Set(new Box2D.b2Vec2(-40.0, -6.0), new Box2D.b2Vec2(40.0, -6.0));
    ground.CreateFixture(shape0, 0.0);    

    // planck.js
    var ground = world.createBody({});
    ground.createFixture(planck.Edge(Vec2(-40.0, -6.0), Vec2(40.0, -6.0)), 0.0);

    // emscripten
    var bd = new Box2D.b2BodyDef();
    bd.set_type(Box2D.b2_dynamicBody);
    bd.set_position(ZERO);
    var body = world.CreateBody(bd);

    // planck.js
    var body = world.createBody({
      type: "dynamic",
      position: Vec2(0, 0),
    });
    // or just world.createDynamicBody();

    // emscripten    
    myQueryCallback = new Box2D.JSQueryCallback();
    myQueryCallback.ReportFixture = function(fixturePtr) { };

    // planck.js
    myQueryCallback = function(fixture) { };


One advantage is that the planck [1] is over 4x smaller than the emscripten build [2].

[1]: https://github.com/shakiba/planck.js/blob/master/dist/planck...

[2]: https://github.com/kripken/box2d.js/blob/master/build/Box2D_...



Awesome, thank you!


Great work! This is really impressive stuff, and it's applaudable that you saw this project through to the very end!

I'm actually seeing some hitching in the car demo on my reasonably fast dev machine, particularly when I'm interacting with the bridge (computing contact forces of a bunch of bodies connected with joints is a lot of work): http://piqnt.com/planck.js/Car

Have you looked at perf yet? How does the performance of your rewrite planck.js compare to a compiled emscripten version?

Would you ever consider using something like ASM.js or WebAssembly? Physics libraries are definitely one of those performance-critical applications where this kind of stuff actually matters a whole lot.


Thank you!

I have not seen any problem with car example on my own laptop, but I will try it on some more different devices to find the issue.

Regarding performance, because Planck.js code is hand-made and readable it is not difficult to improve it if it is not fast enough with some cases.

asm.js looks promising, I'm going to have a closer look at it.


I guess I fixed the issue that you pointed out, it was a new bug in testbed. Thanks for reporting!

You may need to force-reload the example to see the update. Please let me know if the issue still exists for you.


I made a graphics library IvanK.js and made a Box2D demo for it (using Box2DWeb). It ran smooth even back in 2012 :) http://lib.ivank.net/?p=demos&d=box2D


Cool.

Did you contact the Phaser people( Or well, that one guy mostly)? This could replace Box2d there.


Thanks! It is easy to integrate Planck.js with other liraries and dev tools.


I've messed around with various incarnations of Box2D, including at least one other Javascript port. How does this one compare performance-wise? Does doing a full rewrite perform better than the automatically generated Javascript of the other ports?


The main difference is that it is a hand-made rewrite, so the code is readable and improvable, so performance can be improved and optimized even if it is not fast enough in some cases. Also see my other comment about comparison with emscripten port.


Awesome!! Makes it a delight to use


I'm currently using Box2D intensively in one of my games: www.braains.io What would be the easiest way for me to replace the existing Box2D implementation with Planck.js?


What I remember from Box2D is that the simulation wasn't deterministic but rather dependent on frame rate for example. Is it the same case for this?


If you tie the frame rate to the physics step, then yes - that will be true for pretty much any physics engine.

The classic advice here is http://gafferongames.com/game-physics/fix-your-timestep/


In JS, if you pass same input it will give you same results. With box2d/planck frequency needs to be constant anyway, and I have not seen any nondeterministic component in the code. (I think in box2d docs it refers differences in execution platforms not the library itself.)


Not even if you always pass the same frame step from your engine independently of your actual frame rate?


Then you used it wrong, as you should never tie your simulation to the frame rate. Given same input, Box2d is deterministic.


How difficult would it be to integrate with Phaser? I believe Phaser currently has Box2D support but only through a closed source commercial plugin.


Probably it would be easy, I would be happy to help with that, please feel free to open an issue on github.


Nice job!! Love the 8 ball example ... really fun :)


Nice demos! I like how in the soccer example you can play as a self-driving ball :D




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: