views:

616

answers:

5

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?

A: 

In this example the calculation of the positions have to be finished before the drawing the ball - so asynchronous processing doesn't make sense?

p5 itself is very synchronous - there is one central draw method which does all the drawing.

Also web workers can't access the dom, so they can't be used for drawing.

For a more complex, event based application like a game there could be uses for web-workers.

Peter Krenn
No, this isn't the case - when drawing is initialized, the workers start calculating positions and every time a new one is found, it is submitted to the main thread. There, it is stored in a kind of 'caching'-array, so it can be used later on. However, calculation continues while drawing happens, so there's no delay every frame, and no delay before starting.
JorenB
A: 

Just a thought...but in signal processing what you do is come up with a sample rate that slices up the analog signal into digital info. The key is to retain just enough of the signal to recreate the original. Like the way MP3's are ripped from music files using 128, 192, etc.

So if you are moving the ball in a mathematically definable way (i.e. along a parabola), you should be able to convert the path into a set of coordinates that approximates the analog path. Those coords would be much quicker to calculate than the full path. It would also be tunable (by changing the sampling rate).

I know this doesn't address any of your questions about Processing.js or Web Workers. Just an idea to help you perform those calculations more efficiently.

Rake36
I didn't understand what Processing.js was before I submitted this answer. Pretty sure I'm way off base as to offering anything that might help. It looks like Processing.js is already doing a pretty good job of the signal processing concept I described above.
Rake36
+1  A: 

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.

Dustin Getz
A: 

This idea reminds me of Google's task queue idea being integrated into Google App Engine.

http://code.google.com/appengine/docs/python/taskqueue/

This might help you out.

For my asynch online board game, I'm going to implement a system where a history of messages are kept so players can see what happened when it wasn't their turn. Each thing that happens will get a unique ID and whenever the player is sent any messages, it keeps track of the latest one they've received. Then, when they come back they can see a quick animation of everything that occurred from the last message they've received.

And if I get to a point where I need the server to process something while the client isn't waiting, I'll use the task queue

Neo42