

CoffeePhysics: A JS/CS Physics Engine - jashkenas
http://soulwire.co.uk/coffeephysics/

======
jashkenas
The really neat thing here is the _very_ accessible source code...

Vectors: [https://github.com/soulwire/Coffee-
Physics/blob/master/sourc...](https://github.com/soulwire/Coffee-
Physics/blob/master/source/math/Vector.coffee)

Collision Detection: [https://github.com/soulwire/Coffee-
Physics/blob/master/sourc...](https://github.com/soulwire/Coffee-
Physics/blob/master/source/behaviour/Collision.coffee)

~~~
functionform
Standard Coffeescript (in my experience).

edit: hah, just saw who i replied to.

double edit: the renderer hierarchy he created is yet another good example of
why I believe coffeescript needs interfaces...

~~~
jashkenas

        > the renderer hierarchy he created is yet another good example 
        > of why I believe coffeescript needs interfaces...
    

What exactly are you thinking of here? Because JS is as flexible as you can be
in terms of duck-typing and calling any function with any number of arguments
-- I don't see what having an explicit "interface" construct would gain you.

~~~
functionform
Compiler safety for the design. Implement a base class, and force
implementation for sub classes. I know that CS philosophically is about
keeping JS's openness, but I feel it would be a time saving convenience if the
compiler told me I was missing a method.

~~~
munificent
If you want a language that compiles to JS and has more compile-time checking,
I'd encourage you to check out Dart. It's not everyone's cup of tea, but if
you don't mind semicolons and curly braces, it gives you a pretty decent
amount of compile time checking while still generating nice JS.

------
mbostock
Nice; it's lovely how position Verlet lets you simulate geometric constraints
so naturally. If you're interested in learning more, I recommend Thomas
Jakobsen's "Advanced Character Physics" (I could only find a PDF link):

[http://www.pagines.ma1.upc.edu/~susin/files/AdvancedCharacte...](http://www.pagines.ma1.upc.edu/~susin/files/AdvancedCharacterPhysics.pdf)

The first demo reminded me of a collision-detection D3 demo I made last year.
This one uses a quadtree to accelerate collision-detection, as well as another
quadtree for the Barnes–Hut approximation of charge forces:

<http://mbostock.github.com/d3/talk/20110921/collision.html>

More here: <http://vimeo.com/29458354>

~~~
jashkenas
As someone who's had a lot of experience implementing these things for JS, I
wonder what you think of @soulwire's strategy and general structure for
applying (say, Verlet trajectories):

[https://github.com/soulwire/Coffee-
Physics/blob/master/sourc...](https://github.com/soulwire/Coffee-
Physics/blob/master/source/engine/integrator/Verlet.coffee)

... compared to your own approach:

[https://github.com/mbostock/d3/blob/master/src/layout/force....](https://github.com/mbostock/d3/blob/master/src/layout/force.js#L45-118)

~~~
mbostock
The Verlet integration is just this part here:

[https://github.com/mbostock/d3/blob/master/src/layout/force....](https://github.com/mbostock/d3/blob/master/src/layout/force.js#L104-114)

The rest of the function is calculating default forces and constraints for
graph layout; these can be disabled, and thanks to the resilience of Verlet
integration, you can easily implement custom forces or constraints in your
"tick" event listener (as Shan Carter did in the budget piece a few weeks
ago).

Given that it's a generalized physics engine, I like that @soulwire's code is
organized into clean, modular units. That makes it easier to test and modify
the internals. D3's force layout is specifically-tailored to graph layout, so
I don't consider it necessary to make the implementation so modular; the
requirements of the force layout are that it is fast by default, that it can
be customized with incremental additional effort, and that it is convenient
for the common cases.

Also, with larger graphs numerical integration is one of the few places where
JavaScript performance (not just rendering and DOM manipulation) actually
matters; while unfortunate, it's often necessary to make a trade-off between
generality and performance. Still, I'm considering more modular reusable
forces and constraints for a future iteration of the force layout (perhaps
similar to the older Protovis force layout). But since custom forces tend to
be very… well… custom, I think the best option is simply to modify the nodes'
positions as needed and let Verlet do the rest.

------
ricardobeat
The cloth simulation runs incredibly smooth, while the _attraction_ demo is
terribly slow (Chrome 17 OSX). Strange?

~~~
TheBurningOr
The attraction and collision demos are both doing collision detection, which
means N! calculations (for each particle check the location of all the other
particles that have not been checked relative to this one). Whereas the chain,
cloth and I can't recall the name of the third one, are on the order of N
calculations (constant interaction with only a fixed number of other
particles).

~~~
HardyLeung
You mean N^2, not N!

~~~
nlogn
He's right actually if the code is written sensibly. Well it should really be
(N-1)! but close enough. Think about it in terms of 3 balls. I check ball1
against ball2 and ball3 then move to ball2. It gains me nothing to re-check
ball2 against ball1 so I just check it against ball3. When I reach ball3, I
have already checked everything and I'm done.

The loop should look like this:

    
    
      for (i = 0; i < n; ++i)
          for (j = i + 1; j < n; ++j)

~~~
HardyLeung
I think you need to revisit your understand of complexity. It is O(N^2). If
you want the exact count, it is N(N-1)/2. N! is an exceedingly large number
even for very small N.

~~~
nlogn
Yep I'm wrong. Mixed up factorial just like mistercow said. Thanks for the
corrections. And here I was worrying that someone would complain that my loop
wouldn't address the issues of collision response necessitating more checks,
thus making a recursive solution necessary.

------
devongovett
Badass JS post if you're interested:
[http://badassjs.com/post/18503583619/coffeephysics-a-fast-
ne...](http://badassjs.com/post/18503583619/coffeephysics-a-fast-new-physics-
engine-written-in) Contains a great interview with creator Justin Windle.
Check it out for a unique perspective!

------
jahewson
Not so hot in Safari 5.1.2:

TypeError: 'undefined' is not a constructor (evaluating 'new Date.getTime()')

------
deepkut
Damn, 60 FPS? Makes me reminisce of celebrating ~30 FPS in Counterstrike

~~~
jiggy2011
I remember everybody obsessively upgrading their hardware just so that the fps
counter in CS never went below 99.

~~~
ricardobeat
They said it improved hitbox accuracy, easier headshots :)

------
dustingetz
so the interesting question is, would this have happened in javascript? is
coffescript so much better than javascript that projects are in reach now that
weren't reasonable before? can a team who wouldn't be able to build this in
javascript, build it in coffeescript?

nobody says coffeescript isn't nicer than javascript, but some people say its
not so much nicer that it's worth the "abstraction tax" - compare to C vs
assembly where nobody questions that the abstraction is worth it.

~~~
JackC
I don't know if that question is "interesting" so much as "impossible to
answer" and "extremely contentious." :)

But my personal answer is that I have, say, 50% more fun writing CS than JS,
so there are likely to be personal projects I write in CS that I just wouldn't
have bothered with or would have lost steam on before. When you're doing
something for the love of it, every moment that makes you think "dammit
[Javascript], why are you making me do this?" is a potential moment to walk
away and do something more fun. I (begrudge;every;semicolon) in an unnecessary
for loop.

So if other people are like me, I expect CS to bring new things to the world,
not because it's 10% faster but because the 10% it's taking out was the boring
part. If no one's like me, then I hereby award myself one Special Snowflake
from the many falling outside my window.

To put it another way: "The single most important lesson that people say they
have learned from the Ruby programming language is a lesson that _Why’s work
embodies in its code: Programming (or whatever you do) should be fun. There
must be joy in your craft, and there is precious value in tinkering and
playing around."[1]

Whether CoffeeScript or wire-wrapping individual transistors lights up your
eyes is up to you of course -- but we all benefit by giving creators tools
they like. Sermon for today over.

[1] [http://www.smashingmagazine.com/2010/05/15/why-a-tale-of-
a-p...](http://www.smashingmagazine.com/2010/05/15/why-a-tale-of-a-post-
modern-genius/)

------
eik3_de
What are the reasons those apps can't use all CPU cores? Is it possible to
develop multi-core JS apps on recent browsers like chrome?

~~~
dspillett
Until "web workers" are generally supported by common browsers, there is no
way to run more than on bit of Javascript at a time in any given tab. As all
the code is running in a single thread it will only use one CPU core (or if
the scheduler bounces the browser process between cores it will use at most
one core/second worth of CPU resource per second).

Depending on the how much cross talk there would be between the threads, web
workers might not be adequate for some algorithms anyway as the message
passing (the only way web workers can communicate, there is no "shared memory"
access or other such short cuts to communication) could add noticeable
latency. Caveat: I've not used them for anything myself so I don't know if any
such latency is large enough to be an issue.

You can create multi-threaded code using web workers, but you exclude your app
from browsers that don't support them. The major laggard on the desktop is IE,
which is due to gain support for them in version 10. As far as I know the only
current mobile browser that supports them is Safari under iOS5, apparently
they were present in Android's browser but removed/disabled in recent
releases.

~~~
aapl
There is also WebCL, an effort underway to put OpenCL in the browser, and
River Trail, an experiment to execute subset of JavaScript using OpenCL as a
backend. I don't know how difficult it is to write a CPU compute device
driver, so I don't know if WebCL will become a viable general stategy for
multicore execution in a browser though.

------
headbiznatch
Beautiful.

Performance question: why does window size affect FPS so drastically?

~~~
gb
Clearing or filling large areas of <canvas> is cripplingly slow in every
browser I've tried so far, so I'd assume it's that.

Hopefully that'll be worked on at some point in the not too distant future as
it's one of the biggest problems I encounter when dealing with canvas at the
moment.

~~~
headbiznatch
Thanks for the reply. It just seems counter-intuitive that canvas area should
matter so much when the drawing logic is essentially the same. We are creating
the same number of objects, just on a larger canvas and with different (X,Y)
coordinates. Thus, the creation speed of the canvas itself (in memory, before
flipping) should be roughly equivalent, right? The slow-down is simply from
having to re-render the larger canvas? I'll dig more, of course, but quick
insight from those in the know around here is always appreciated.

~~~
weixiyen
You just have to think lower level. There's the CPU to figure out what to
draw, then there's the CPU (or GPU if using webgl) to actually draw what it
figured out. More screen space increases rendering time b/c now you are
drawing potentially 4x as much in the same timeframe.

Similarly, an image of 30kb takes more time to draw than an image of 10kb,
even if they take up the same dimensions and space on the screen.

If you think this way, it's quite intuitive.

~~~
headbiznatch
True. I guess I'm just surprised by the magnitude of the effect. Thanks for
the input.

~~~
weixiyen
it doesn't manifest itself until you put it in a loop and try to draw every 16
ms.

~~~
headbiznatch
Good point :)

------
tzaman
This kind of stuff makes IE look like a bad joke. Oh and Jeremy, you're my
hero :)

~~~
jashkenas
Cheers, but it ain't got anything to do with me -- it's Justin Windle's:
<http://soulwire.co.uk/hello>

------
bionicbrian
That is freaking awesome.

------
dragosstancu
Impressive work!

~~~
paulbjensen
agreed, when I get time (ha), I'm going to build my 2d platformer, "escape
from corporate America"

