Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining the power of Processing.js and Web Workers

I've been doing some reading about two (relatively) new concepts in the Javascript language - Web Workers and John Resig's awesome Processing.js (well, not really a new 'Javascript concept', but you get my idea). Some great examples of both wander the internets, but I have yet to find one that employs both techniques effectively. It looks pretty interesting and powerful to me, so I thought I'd better just give it a try.

However, I can't really figure out the best script design to integrate the two of them... It seems to me that usually, when Processing.js is employed, some classes are defined within the 'Processing-application'. It allows you to use a Java-like syntax to go about this. However, these classes are only accessible within the Processing-application - which is obvious. But then we've got the Workers... In this amazing example, a Javascript function object is first defined in a separate script, and if Worker-usage is desired, the Worker-script imports that object's prototype and kind of 'bolts' itself onto it.

To me, the two don't seem 'interchangeable', in that you can't access the class that you defined in the Processing-application, when you're in your Worker script. Probably for a reason, as the Processing-like classes are definitely not very Javascript-like. As far as I can see, I'll have to make a similar definition of the class (in the form of a new function prototype) in my Worker script - which isn't very good for maintainability, and just seems like terribly bad design to me, even though I'm still a big newbie on this subject.

Am I overlooking something? Do I want something that's just not supposed to be? Or have I just misunderstood some fundamental concepts?

Thanks for the help!

Edit:

Went on to try messing with the Worker's prototype in order to 'shape' it like the object it's supposed to do work for, but realized pretty soon this isn't the way to go.

Let's try an outline to work with: I have a class 'Ball', which pretty much doesn't do anything except store a two-dimensional position. On every draw() cycle, Processing.js calls its update() method, which makes the Ball adopt a new position. Afterwards, the display() method is called, which has the Ball draw a small circle on its current position.

Nothing complicated to begin with. Now, assume that determining the ball's new location is a pretty expensive operation - for example, if it involves the movement of the ball through a 'complex' gravitational field. If this calculation has to be done every single time before drawing, it'll cause at least some delay. However, if you'd manage to do this stuff simultaneously, it might have a smoother run. So, I figured out I could give the Ball class an extra 'positions' array in its property list, which will hold all of its consecutive locations. When the Ball is instantiated, it creates a new Worker that will start calculating positions, and each time it has completed one, it will post back a message to the Ball, containing a new two-dimensional position. The Ball will then push this one on its positions array, so each time it has to update its position, it just walks to the next record in the array.

All in all - good or bad idea? If good, any suggestions on how to design this?

like image 293
JorenB Avatar asked Aug 23 '09 15:08

JorenB


Video Answer


2 Answers

3D game physics sims (like on the xbox360) typically run at a fixed rate, independent of framerate. That's because physics is far too complicated to model analytically, so you do numeric approximations, so you need to synchronize error deterministically. Additional benefit is framerate is decoupled from physics performance, so you could update your physics at 5hz and interpolate, etc.

So the model you describe is exactly how the pros do it.

like image 74
Dustin Getz Avatar answered Sep 30 '22 09:09

Dustin Getz


you can't access the class that you defined in the Processing-application, when you're in your Worker script. Probably for a reason

This is to prevent errors due to multiple workers changing the same shared data at the same time. In messages the data is copied and each Worker gets its own copy so it doesn't have to worry about simultaneous writes causing errors. This is a simple way to avoid concurrency errors that handles it without the programmer having to worry about it (no semaphores or synchronized, et)

like image 44
donut Avatar answered Sep 30 '22 08:09

donut