Phasors, Appletception, More Expressions, Pack200 is the shit!Posted: October 22, 2011
A while back I was struck by inspiration from an applet that was shown in my EE20 lecture about phasors. I went about writing my own version of this applet, but combined with the expression parsing powers of Scala. I decided to try some Appletception, putting no less than four PApplets contained within a normal Applet class. This was both a boon and a… uh…. unboon? anti-boon? noob? HA. Let me tell you why: (P.S. I’m also trying this bold important phrases thing that was semi-mostly-completely inspired by coding horror’s blogging style.)
Good things about embedding PApplets
- Different parts of code live in different methods; the concepts in my mind are reflected accurately in the hierarchy. Instead of having a huge setup/draw method that would do four things at once, I instead have four classes each doing one thing at a time. This keeps the code closer to our mental model, which is what we want.
- Swing’s windowed, focusable event system can be fully taken advantage of! I don’t have to worry about what “region” the mouse is in, or which applet should respond to my key-presses/mouse wheel scrolls, because swing does it for me.
- The positioning of the applets is determined by the layout manager; so I don’t have to. Again, swing does it for me.
- It’ll be simple to extend this sketch to include other swing-y things like easy resizing, or adding a border (which was implemented, to wonderful effect, in four lines).
- It’s multithreaded, so one PApplet may go really slowly (say 5 fps) but the other one will still be at 60 fps. This isn’t necessarily a good thing depending on how you look at it.
Bad things about embedding PApplets
- Multithreading bites you in the ass. Each PApplet starts its own thread, and only that thread will run the draw() method correctly, and there’s nothing you can do about it. I was able to keep my issues to a minimum by having only one method that might be called concurrently, and then just synchronizing that method. But it could easily get messy.
- Because they’re not all synchronized, the frames won’t line up. If you drag the Argand diagram quickly, you’ll notice that the plots for the Real and Imaginary parts get very blocky and very NOT function-y. This is because they depend on the state of the camera in the Argand diagram, which changes as they’re asking about it. The fundamental problem is that the rendering of the Real and Imaginary parts is much, much slower than the rendering of the Argand diagram, so one frame in one applet is actually 5-10 frames in the other.
- You have to connect the wires together. I forgot to override and delegate the start, stop, and destroy methods from my outer Applet to all my inner PApplets so my applet would freeze every time I refreshed the page. This isn’t too much overhead but can still bite you.
I wanted to finish this sketch for several weeks but silly, silly things like homework and midterms kept getting in the way, and I really wanted to polish this one up a little bit and make it usable. In particular, I re-wrote my parser library to return an Expr class instead of just a float (this effectively caches the parsed structure), resulting in speedups of ~600x. Drastic but not unexpected, considering the massive, complex machinery that parser combinators are.
I also finally figured out how to use pack200 compression; the resulting applet is down from 472kb to just 102kb, smaller than normal Java Processing applets. Amazing what Proguard + pack200 can do.