But is the solution to teach people the DOM? That seems like cruel and unusual punishment--a kind of Protestant work ethic: real programmers suffer. The browser document object model ranks up there in the history of terrible API design: it's overly-verbose, inconsistent, and tedious. If you use it for any amount of time, you will end up recreating at least the traversal parts of jQuery--searching up and down the tree for related elements--if not the animation and CSS methods as well. Traversal isn't a hard problem per se, but as with anything involving recursion, it's kind of a lot to throw at a beginner.
As with any subject, foundation is important. But that doesn't always make it the right starting place. When teaching bass, for example, we wouldn't make someone master chord theory before we taught them a simple scale. Instead, we can start at one level of abstraction and work both up and down. It's the same when coding: by starting people with jQuery, I suspect it's easier to get them into the DOM later. We can still teach the fundamental patterns of the language without being caught up in the implementation of a bad API.
Granted, I didn't study computer science in college. I had done some programming before and didn't really want anything to do with it professionally--I wanted to work for the Travel Channel! So when I fell into doing data journalism for CQ, a job that's halfway between storytelling and interactive coding, I knew there were skills where I was probably behind. And now that I feel like I'm relatively up to speed on the languages themselves, I want to catch back up on some of what I missed, starting with various low-level data structures.
These posts are also intended to leverage a truism: that the best way to learn is to teach someone else. By writing the blog as a teaching tool for other people, it forces me to organize my thoughts into a logical, coherent narrative: what are the foundations of this structure? What's it actually doing during this algorithm? Why is this useful? When the goal is to educate, I can't just get away with refactoring someone else's example. I need to know how and why it's built that way--and that knowledge is probably more useful than the example itself.
Here's what I've learned from releasing Underground to the Android Market:
Overall, I've really enjoyed learning the platform and joining the community. I did some other hobby work on Android the other week (wrote a Locale plug-in for detecting headphones and started a utility/plug-in for launching arbitrary custom Intents), and I think it's lived up to my initial impressions of a smart, interesting API design. That said, now that Underground's in decent shape (most of the requested features have been added), I'm taking a break from Android coding for a while to give my hands a rest and concentrate on other hobbies. When I get the urge again, I'm thinking about contributing to the official NPR client--it's not a particularly good citizen on Android, and I think it'd be a good way to get involved with other digital journalists.
Again, click in the window and press space to begin playing. This time, I've added player controls: arrow keys steer and move forward, A jumps and double-jumps, and holding Z while jumping will switch from strafing to turning. Press space again when you're done, to pause rendering and keep it from hammering the CPU.
This time, the landscape is made up of 16 procedurally-generated tiles, each colored differently so you can tell between them. I apologize if there's a pause while you load the page--the noise functions I'm using tend to lock Flash for about two seconds on my machine. There's also some primitive gravity operating on the stars that you can see at the beginning.
I'd been thinking about various game-related uses for this while working on it, and the frontrunner was a kind of "jetpack delivery service" that combined Tribes with Crazy Taxi--hence the control scheme. The problem is that A) it would require an enormous landscape, and B) I'm not really sure how to balance it. For a game like that, players need to enjoy the process of movement itself, while still being limited in ways that don't have a steep frustration curve. You could do it with platforming, but I'm not really sure this engine is well-suited for that kind of thing. More importantly, implementing it well would require building levels by hand, a process for which I probably don't have the tools or temperament.
It occurred to me tonight that a better setting might be underwater--like Seaquest, without the annoying dolphin voice. That would be ideal for use with procedural height and texture maps. It'd be a natural fit for the look of a voxel engine, while still providing a good excuse for fog. It'd be kind of a neat change from the usual genres. And it would bypass one of the pitfalls of doing a first-person game in Flash, which is that mouselook is expected but not really possible due to limitations of the plugin. So I'm going to fork the code and start playing with a different control scheme, as well as a different method of generating the heightmaps that provides a bit more natural variation.
Behold, the mighty voxel terrain engine:
Click on the Flash window to give it focus, then press space to start/stop the animation thread. The two numbers at the top are the framerate and the level-of-detail (LOD) constant. You can adjust the LOD, and thus the framerate, by pressing the [ and ] keys. The ' key cycles through three post-processing options: poor-man's light bloom, simulated drunkenness, and none.
I've been working on this in my spare time for a couple of days now, just as a kind of mental exercise. Also, the techniques that I figure out on problems like this could be useful for work--I'd love to do a scatter plot or density map of the US using this kind of approach. Finally, it's a chance to get back to the kind of frame buffer-centric graphics hacking that I used to do.
So why voxels? Well, for one thing, they're easy to debug. An engine like this works by casting rays out from the viewpoint for each pixel of the display, stopping when they intersect the landscape, and drawing a texture point at that position. The heightmaps are pulled straight from images that I can make in Photoshop (thus keeping my toolset fast and simple). There aren't any BSP trees or polygon normals to compute (usually). Voxel engines may have fallen out of popularity with professionals because they can't be easily hardware accelerated (although some coders hope that will change), but they have relatively few points of failure and mistakes tend to be pretty obvious.
Getting this to work was easy. Getting it to run at 30fps or more was a bit harder. A few notes:
Although it's simple, coding this was a lot of fun. The next goals are to add support for tiled heightmaps (for building bigger worlds), multiple landscape textures, and sprites. If the framerate would support it, I'd put a second, inverted landscape on the "ceiling" for creating more complicated structures. One thing I didn't anticipate was how much I like the look of the bold colors and gradients in the current "programmer art" texture--maybe that's a look I'd like to preserve. And of course, somewhere along the line, I'll have to figure out what I'm doing with it. Any ideas?
Flash has a bad rep in the tech press. It resurfaces whenever Adobe updates the player plugin, which is the only part they actually control anymore, or when the discussion turns to Flash content on mobile platforms. And it's not wholly inaccurate, but it's way out of proportion to what Flash deserves, and what it achieved.
Even so: let's pretend that YouTube, decent APIs, and speed aren't important to us. What's Flash got going for it? As XKCD pointed out, it spawned a tiny renaissance in simple, fun, 2D gaming. As a tool for making everything from the sadly-departed Scrabulous to Alien Hominid, Flash provided a slick platform allowing artists and novice designers to experiment and get exposure. It's done for 2D what Duke3D and Doom did for the mod scene. Say what you like about it, if you love retrogaming, Flash deserves some credit for its recent success.
Thee examples of why scripting is an essential part of a "smart" phone:
Example 1: Belle recently switched to Sprint and got an Instinct, of which she will extol the virtues to anyone who will listen. Seems like a nice enough phone to me. But it doesn't rotate photos, so she has to hold the camera the right way when adding images to contacts. We didn't figure this out until after she'd gotten a picture she liked.
My phone also does not rotate photos--as a "business" phone, Nokia treats the camera in the E51 as an afterthought. I can rotate them while viewing, but it's not a permanent change. But since I'd already run into another limitation (the inability to resize photos), I'd taken a half-hour to write a Python script that rotates and resizes images, most of which was spent learning Python's syntax (dear Nokia: ECMAscript variant, please?). So Belle sent me the file via Bluetooth, I ran it through the script, and sent it back. Now she can see a truly dismaying (but correctly-oriented) picture of my face when I call her.
Example 2: A while back I wrote that life for colorblind people often doesn't come up roses (monochromatic ones, even). Why, I wondered, couldn't you use a phone camera to identify colors? Well, you can. I wrote a script called Color Dog that opens up a viewfinder, paints a little rectangle in the center, and displays the average RGB values for pixels in that square.
Example 3: The last call for me on my old phone was that I couldn't easily record calls from it--there's no headphone jack on a RAZR, and taping via Bluetooth is no fun at all. The E51 does have a jack for various audio attachments (for some reason, Nokia calls these 'enhancements') and can even discriminate between inputs and outputs, so I could continue to talk into the phone while taping the conversation through the jack. It's even got a decent voice recorder that can run during calls, for up to an hour (memory permitting).
But let's say I'm paranoid, or I'm forgetful, or I'm being targeted by obscene phone calls. For whatever reason, I want all my calls taped, automatically, and filed under the date and time they were made. That's probably only 40 lines of code, if that--a phone status callback, a basic UI screen, and a function for starting the recording with timestamped filenames. I haven't written this. Yet. This and my idea for an app that responds to SMS with a link to the phone's latitude and longitude on Google Maps (for people who lose their phones regularly) are at the top of my list.
None of these examples are things that any smartphone--or even most camera phones--couldn't do. But they are things that most smartphones don't do. And that difference between "could" and "does" is the important point here.
Is it possible that someone could write an app on another smartphone that would permanently resize and rotate a user's photos, or help identify color values, or automatically tape calls? Sure--even in a walled garden this is possible, although technical issues (limitations on access to filesystem, background processes, or low-level hardware) could make it more difficult. But for example two it's fairly unlikely, and example three much more so, for reasons involving both barrier to entry and (in the latter case) legal liability issues.
However, on a platform that's not walled off, I can freely write these kinds of little scripts to address those problems or add capabilities. And then I can share them with other people, who can just run them, or they can tinker with them and make them better (here you go: ImageTool.py and ColorDog.py). I don't have any problems with walled gardens for buying apps, if that's your thing. But as far as I'm concerned, it's not really a smartphone--a truly adaptable, innovative device--unless it also offers the option of tweaking it on the go this way. It needs to be the equivalent of a digital swiss army knife: if you're going to carry around a Turing machine in your pocket, why settle for anything less?
I understand the desire to get a platform-independent language onto mobile devices. But I have to ask, now that I'm messing with it--who exactly thought it would be a good idea to put Python, a language that describes its program blocks using indentation, onto Symbian phones, most of which have a screen that's less than 2 inches across?