All this PPK "iPhone developers are stupid" awesomeness got me thinking. Now, if there's one guy I've got respect for, it's PPK. And if he tells me to ditch objective-c for JavaScript, then I'm damn well going to do it. Accordingly, I decide to create "Parcycle": a Particle Emitter system that I re-wrote from a set of great openGL iPhone tutorials by the good guys at 71Squared.
See the wonders of HTML5 Canvas!!
(here's a proof-of-concept version as an offline iPhone Web app)
After updating an old JavaScript platformer to work on the iPhone, I decided to step it up a notch. A full-featured Particle System: lots of particles, lots of colours, lots of fluffy clouds of pixels! I ported the 71Squared Particle Emitter code pretty-much directly: in fact, a bunch of it was straight copy/paste - I just had to change "->" to ".". Well, mostly.
...actually, the real reason for this undertaking was because I just learned about the "lighter" value for the canvas globalCompositeOperation
. In this mode, when you draw two things on top of each other the overlapping area will become lighter. Which makes the particles look fully-sick.
The particle system itself is straightforward enough, so I thought I'd tack on a couple of extra bits - I added a couple of extra parameters, made it bouncy, and also let you (kind of) save and load data. If you click the save icon you can copy/paste out the current parameters - and as an added bonus, the data is a very re-tweetable form.
"Why would you tweet it?" you ask, incredulously. Well... if you click the "Twitter" button, then it will search Twitter's public search service for saved "files": these are just tweets with lots of numbers and the #parcycle hash tag. Any saved settings get loaded them into the example containers, so you can see what other people have made. Pretty groovy - annnd, I don't have to worry about writing any server-side nonsense. Win-win!
I'm going to write a cut-down version for use on future iPhone Web games. Even my dodgy first-pass seems to function reasonably well with a hand-full of particles: with some optimizing it should be good enough to get rid of objective-c forever!*
So anyway, go See the wonders of HTML5 Canvas!!
*No.
32 Comments
This is frickin’ awesome! :-)
Oh my, it is beautiful and mesmeric. It is like the stars I see in my head when I accidentally poke myself in the eye with my glasses. But much better.
The beginning of the end for Flash? Could it be?
Cool work Earle.
Perdy!
Excellent implementation!
Very nice! I’m hitting the 3pm wall, and this makes for some excellent procrastination.
This is tops. And fireballed! Nice one.
Can you make it work in Opera?
You should make sure that r0 and r1 of createRadialGradient are not negative. This throws INDEX_SIZE_ERR per spec.
Also fillRect with negative width, height throws. Please fix those and it will work in Opera. A bit slowly but wait for 10.50. :)
It’s very nice and an interesting demo, but I take issue with you prefacing this article with PPK’s remarks about iPhone developers. As you’ll see if you load this demo on an iPhone, this is quite simply not a practical way to achieve such an effect — I got roughly 1 FPS on an iPhone 3GS.
If your intent was to show that yes, you can particle effects within the canvas element then I applaud your efforts because it works and works nicely. If however you intended to support PPK’s criticism of developers choosing native development tools over web standards ones then I’d say this demo falls flat on its face, as there’s no way you could use this in a production-quality app.
Very cool….you can see how webpages are going to evolve into much prettier things.
Thanks Rafal – great detective work! I’ll fix that as soon as I get a second. And Ben… nah, I was just being stupid about the native stuff – c’mon – I link to my post that says PPK is the kid from Degrassi Jnr High (though I _do_ really respect the guy) AND included what I thought was a redundant asterisked disclaimer! There’s just no subtlety on the intertubes I tells ya.
Of course, your comment was very balanced – but as this post hits the non-nerd world I’m sure there will be a storm of “OMG, it’s flipping slow!”… Still, I do reckon with a bit of optimizing (absolutely none is done with this example) that you could get some useful particle effects on iphone webapps. Not 1000 particles at 60fps, but good enough for simple explosions etc.
If you want it to be fast on the iPhone, your best bet is to use CSS transformed divs instead of the canvas. They are backed by the CoreAnimation library, which bar an actual WebGL implementation is the fastest method of displaying animated graphics in Safari.
Also, optimize the JavaScript. Despite improvements, it’s still miles slower than on the Desktop.
Regarding PPK’s (and like-minded developer’s) comments:
Nobody should forget that Apple spent the first year of the iPhone’s existence, telling developers to write web apps. Of course, way back then, you didn’t want to hear about it–you wanted instead to be able to write native apps.
Well, familiarity breeds contempt, and developers are no different from every other flawed human being.
It’s sad that we have to motivate ourselves with vengeance or with the idea that someone else has to pay the price for our mistakes and short-sightedness.
amazing and really brilliant use of JavaScript
What the hell is ~~? As in particle.js ->
var colString = “rgba(” + ~~col.red + “,” + ~~col.green + “,” + ~~col.blue + “,” + col.alpha.toFixed(2) + “)”;
Hey Mr Listener… that’s just a lil’ trick: the ~ is JavaScript’s bitwise NOT operator. Applying it twice (NOT NOT) is just a cheeky way of doing a Math.floor for positive numbers. But it’s waaaay faster than “Math.floor” (and just slightly faster than “<<0") - which is important if you are trying to update 300 particles every frame ;) Also, you appear to be looking at "yesterday code". Check out "today code" - it's much much cleaner!
Awesome stuff. Shameless plug: you could even make it work on IE w/ Chrome Frame: http://code.google.com/chrome/chromeframe/developers_guide.html
Renders just fine using the cf: prefix, AFAICT.
That’s 10 kinds of awesome. :)
Really fast and smooth graphics.
Something similar that I built, based on elasticity of particle bonds:
http://twinkler.in
It’s also based on HTML5 Canvas. It is not as fast as this one, but worth a look.
Please please make this open source! Can you put it up on GitHub or something?
Awesome.
The source for the particle system is up on GitHub: Parcycle. If you want the slider stuff, you’ll just have to view source ;)
This is awesome. But for some reason there was a setTimeout(func…..,100) which made it have a low framerate for me. I used the webkit inspector to change it from 100 to 0 and it was fully sick.
you should’nt change it to 0, but 75 should get somewhat about 25 times in a full second what’s enough for the human eye to recognize it as a clean animation
Thanks so much for the example, very nicely done and truly inspirational!
This is crazy! Came across this while doing some research for this iPhone Safari snowglobe check it out, would love your thoughts
http://www.mobileinc.co.uk/2010/12/experimenting-with-the-iphone-4-accelerometer-to-create-a-snowglobe-in-safari/
Great stuff! Stumbled upon this while trying to build my own, but now I just realised how far I am from building the real thing. I’ll most likely take alook on your source code and learn what I can from there.
Good job!
Nice article.
I also wrote a html5 particle effect tutorial with source code. Mind you I took a different approach. You can take a look here, if your interested: http://astronautz.com/wordpress/creating-realistic-particle-effect-with-html5-canvas/
Im trying to run this system from a button by lunching the Controller.init() from the onClick properties, the problem is that every time I click the button is a speed increase of the animation also if I dont ask for this in the script, is a normal thing?
I dont know if can be useful for someone, but i solved problem assigning an id to the Timeout and clearing it every time controller.init() was called…
If I set a duration for the animation loop, there is a way to run a function at the end of this loop, or is an event that run when loop end?
thanks
this is so great, first one that amazed me with the canvas. anyway I saw the Illuminated.js+Parcycle by Greweb and he made used of it really great. sir, how can I learn to do this? and include it in my first website?