My iPod touch arrived about a month ago, and I've spent some time over the past few weeks learning its ins and outs in terms of development. After a successful jailbreak on the second attempt (my iPod came with version 1.1.1 of the firmware), and some fiddling to get the toolchain up and running, I was ready to go.
My first project was to create a variation of a plasma-effect implemented for the 'touch (many people consistently say "iPhone" when they refer to development for both the iPhone and the iPod touch. Since I have an iPod touch, I'll flip it around and just refer to it as the 'touch). Below is the very same fire effect running on the display wall at the lab where I work. (As an aside, you can take a look at my personal page for more info on my current research.)
Is it art?
I started off by grabbing the source to VNsea, as a starting point for getting input events and learning how to draw to the 'touch's screen. I already had code for doing the plasma effect from an older project -- an attempt many years ago at porting Hyperspeed to OS X, complete with improved explosion-effects -- so all that was really needed was for some way to get the pixels on screen, as well as getting input from the user.
It was a blast to discover how simple it was to get pixels on screen; I was able to reuse code from Desktop Transporter to create the necessary CGBitmapContexts, and updating the image on screen simply amounted to drawing the resulting CGImage created using the data from the CGBitmapContext.
The fire effect now running on the iPod touch.
The rest of this post will be about how the plasma effect in TouchPlasma works. To be relatively speedy, the plasma effect operates on 8-bit values, using a color table to map 8-bit values to RGB-pixels. In pseudo-code, the setup looks like this:
create color table from white (255) to black (0) initialize lookup table for random values for each new frame update_fragments() fade_pixels()
The code makes use of a lookup table for random numbers. The reason is that the number of random numbers required in the code's hot loop is very large. Profiling the code (admittedly years ago) showed that a large amount of time was spent generating random numbers rather than doing useful work, so instead I decided to go with the lookup-table approach. (It also exploits 16-bit integer overflow to avoid bounds-checking the random-table-index.) The hot loop of the code is in the fade_pixels() function, which does the following:
for y from transpose_radius to height+transpose_radius for x from transpose_radius to width+transpose_radius transpose_pixel = (random pixel within +/- transpose_radius) average = pixel + pixel[-1] + pixel[width] + pixel[-width] + pixel + transpose_pixel average /= 6 pixel = average zero transpose_radius wide edges of plasma buffer
The transpose_radius constant indicates the region around the pixel from which we will select a random pixel. That pixel will be used as one of the 6 components to calculate the current pixel's new value. The four pixels left, right, above and below the current pixel are also used to smooth the current pixel, in addition to the current pixel's value. To avoid excessive bounds-checking and unwanted edge-artifacts, the buffer allocated for the plasma-pixels is actually 2*transpose_radius+width wide and 2*transpose_radius + height high.
The final aspect of the code are the fragments, which are responsible for creating the appearance of explosions happening where you touch the iPod. New fragments are created in response to mouseDown events, and initialized with random speed vectors. The fragments are updated once every frame, where their speed is modified in accordance with the current gravity (as configured by the 'touch's rotation), and a constant deceleration factor, before the fragment's position is updated. Once updated, that value for the pixel at the fragment's position is set to the maximum available (255, which is usually white). This in turn seeds the buffer with new white pixels, which will eventually fade through yellow and red to black.
The code for TouchPlasma is available here. It also contains a compiled binary of TouchPlasma which you can scp to your 'touch's /Applications directory.
Comments by Disqus
Spaces.. Spaces.. Spaces.. (Retired)
Jul 28: Running iTunes in a debugger (gdb)
Jul 25: The /Volumes/MobileBackups directory
Jul 20: FolderGlance 3.0.1 supports Lion
Mar 03: Quick tip: Speeding up Xcode compilations
Mar 02: FolderGlance 3.0
Jan 07: Making Universal Back Button work on 10.6.5 and later
Sep 03: Creating pthreads in C++ using pointers to member functions
May 31: Quickly open URLs in Terminal
May 31: Snow Leopard and automatically submitted Crash Reports
May 27: Universal Back Button released for Mac OS X
May 22: The 22 Megapixel Laptop
Feb 09: FolderGlance on MacUpdate Promo
Sep 28: FolderGlance 2.5.3 is out
Sep 21: FolderGlance 2.5.1 adds features and fixes bugs
Sep 16: FolderGlance 2.5 released!
Sep 10: Intriguing: Snow Leopard ships with the iPhone's multi-touch API built-in
Sep 03: FolderGlance and Snow Leopard
Mar 15: Fixing Keynote '08 and '09 to work with the Scripting Bridge
Feb 26: A website in an image
Feb 09: Display wall multi-touch
Feb 19: Spaces.. Spaces.. Spaces.. retires
Feb 08: How-to: Reverse engineering the Dock to fix Spaces
Jan 25: Interacting with wall-sized displays
Dec 20: Interesting Finder bug
Dec 06: Developing applications for the iPod touch (and the iPhone)
Nov 15: Spaces.. Spaces.. Spaces.. and 10.5.1
Nov 15: Thread creation using pthread_create() on Leopard
Nov 13: Spaces.. Spaces.. Spaces..
Nov 07: FolderGlance, Leopard and the More... menu
Nov 06: FolderGlance and Screen Sieve now also on Leopard!
Sep 16: Mysterious window server hangs