this space intentionally left blank

October 3, 2012

Filed under: tech»coding

Teachable Moments

When you're on top of the world, it's the perfect time to start kicking the little people who lifted you up. At least, that's the only conclusion I can draw from Bret Victor's newest post on teaching code. After he did his presentation on "Inventing on Principle" a while back, the tech community went nuts for Victor's (admittedly impressive) visualization work and approach to live programming. This admiration culminated in Khan Academy's computer science curriculum, which integrates a live Processing environment very similar to Victor's demos. In response, he's written a long post bashing the crap out of it.

Instead, he has a plan to redesign programming itself in a new, education- oriented direction. I'm generally a fan of Victor's presentation work (his touch-based animation UX is phenomenal), but I find that his ideas for teaching tend to be impractical when they're examined closely, and I suspect that's the case here. I don't think it's a coincidence that Victor doesn't seem to spend a lot of time asking if anyone else has solved these problems. A little research should have turned up that someone already wrote the language he's proposing: Scratch.

Scratch isn't terribly pretty--it's designed for kids, and it shows--but it provides almost everything Victor claims he wants. Variables are provided in context, with an instant visual environment that lets users examine routines at any time. The syntax is all drag-and-drop, with clear indications of what is nested where, and there's a stepping debug mode that visually walks through the code and provides output for any variables in use. And as much as Victor wants to push the comparison to "pushing paint," Scratch's sprite-based palette is probably as good as that'll get for programming. That no mainstream programming languages have followed its lead doesn't necessarily indicate anything, but should at least give Victor pause.

In his essay, however, Scratch is nowhere to be found. Victor draws on four other programming paradigms to critique Processing: Logo, Smalltalk, Hypercard, and Rocky's Boots. To say that these references are dated is, perhaps, the least of their sins (although it does feel like Victor's research consisted of "stuff I remember from when I was a kid"). The problem is that they feel like four random things he likes, instead of coherent options for how to structure a learning program. They couldn't possibly be farther from each other, which suggests that these lessons are not easy to integrate. Moreover, using Logo as a contrast to Processing is ironic, since the latter's drawing instructions are strikingly similar (I typically use the Logo turtle to introduce people to canvas graphics). And in Smalltalk's case, the syntax he's applauding is deceptively complicated for beginners (even I find the message rules a little confusing).

Meanwhile, where are the examples that aren't twenty years old? The field hasn't stood still since the Apple IIGS, but you wouldn't know it from Victor's essay. Scratch is the most well-known educational programming environment, but there's no shortage of others, from the game-oriented (Kodu, Game Maker) to actual games (The Incredible Machine, SpaceChem). Where's the mention of the vibrant mod community (UnrealScript is many a coder's first language, and I've had several students whose introduction to coding was writing Lua scripts for World of Warcraft)? Like his Braid-inspired live coding demonstration, Victor's essay gives the impression that he's proposing some incredible innovation only by ignoring entire industries working on and around these problems. It's unclear whether he thinks they're not worth examining, or if he just can't be bothered to use Google.

There's also a question of whether these essays solve problems for anyone but Bret Victor. His obsession with visual programming and feedback is all well and good, but it ignores the large class of non-visual problems and learning styles that exist. As a result, it's nearly all untested, as far as I can tell, whereas its polar opposite (Zed Shaw's Learn Code the Hard Way) has a huge stream of actual users offering feedback and experience.

Let me clarify, in case it seems like I'm simply blaming Victor for failing to completely reinvent computing in his spare time. These essays repeatedly return to visualization as the method of feedback: visualization of time, visualization of data, and code that itself performs visualization. Unfortunately, there's an entire field of programming where a graphical representation is either impossible or misleading (how much of web programming is just pushing strings around, after all?).

Frankly, in actual programming, it's counterproductive to try to examine every value by stepping through the code: if I reach that point, I've already failed all other approaches. My goal when teaching is explicitly not for students to try to predict every value, but to think of programming as designing a process that will be fed values. In this, it's similar to this Quora answer on what it's like to be an advanced mathematician:

Your intuitive thinking about a problem is productive and usefully structured, wasting little time on being aimlessly puzzled. For example, when answering a question about a high-dimensional space (e.g., whether a certain kind of rotation of a five-dimensional object has a "fixed point" which does not move during the rotation), you do not spend much time straining to visualize those things that do not have obvious analogues in two and three dimensions. (Violating this principle is a huge source of frustration for beginning maths students who don't know that they shouldn't be straining to visualize things for which they don't seem to have the visualizing machinery.) Instead... When trying to understand a new thing, you automatically focus on very simple examples that are easy to think about, and then you leverage intuition about the examples into more impressive insights.

"Show the data" is a fine mantra when it comes to news graphics, but it's not really helpful when coding. Beginning coders should be learning to think in terms of data and code structure, not trying to out-calculate the computer. Working with exact, line-by-line values is a distraction at best--and yet it's the primary focus of Victor's proposed learning language, precisely because he's so graphically-focused. The idea that the goals of a visualization (to communicate data clearly) and the goals of a visualization programmer (to transform that data into graphics via abstraction) are diametrically opposed does not seem to have occurred to him. This is kind of shocking to me: as a data journalist, my goal is to use the computer to reduce the number of individual values I have to see at any time. A programming language that swamps me in detail is exactly what I don't want.

I'm glad that people are pushing the state of tech education forward. But changing the way people learn is not something you can do in isolation. It requires practical research, hands-on experience, and experimentation. It saddens me that Victor, who has some genuinely good feedback for Khan Academy in this essay, insists on framing them in grandiose proclamations instead of practical, full-fledged experiments. I don't know that I could honestly say which would be worse: if his ideas were imitated or if they were ignored. Victor, it seems, can't decide either.

March 29, 2012

Filed under: tech»coding

Test Driven Testing

Next week a new quarter of Intro to JavaScript will start, and while I'm almost sick of writing about it, it's been constantly on my mind. I've talked a little here about some of the changes I'll be making--primarily I'll be teaching jQuery first--but there's another big experiment I'm going to try: using test-driven development tools to give students feedback on assignments and quizzes throughout the class. I did this in a limited way during the Winter quarter, with an assignment and an exam built using unit tests, but now I want to make it much more widespread. Why use testing this way? Two reasons: to force students to code, and to encourage them to think more critically about their mistakes.

The first reason may seem odd--they're in a programming class, shouldn't that force them to code already?--but it is really an extension of drill learning. I am not good at teaching via drills: I appreciate the value of repetition when I'm learning myself, but I hate standing in class and going through the same exercise again and again. I'd much rather give lectures about theory and application than do drills. But it's clear from last quarter that many students do not get enough practice from lectures. They may be too busy to write code at home, and assignments don't usually force them to use all the constructs of the language.

Drill and repetition are important because, just as with a spoken language, it's not enough to learn the rules of grammar. You need to go out and practice, so that the mechanics become natural and you can concentrate on expressing yourself. That's the motivation behind Zed Shaw's Learn Python the Hard Way series, and I tend to agree. Take the humble for loop, for example. I've written loops for so long I could do them in my sleep, but if you're just starting out there are a lot of moving parts that need to be grasped: for (var i = 0; i < list.length; i++) { //loop goes here } We've written a keyword (for), a series of semicolon-delimited statements inside parentheses, a block (represented by the curly braces), and we haven't even gotten to the actual loop. Just within this boilerplate, we're initializing a counter with the arbitrary name of "i" and giving it an initial value, testing it, and incrementing it. All of this is expressed in a peculiar syntax (the test and increment are tossed in after the setup statement, not placed in the order where they actually get executed), with a lot of very particular punctuation, plus a lot of bookkeeping to track mentally.

Writing for loops (or conditionals, or functions, or almost anything else) is therefore as much about learning a very specific arrangement of characters as it is about the overarching concepts. Languages can make this slightly easier to grasp (as with Python's comprehension-style loops and no-braces indentation), but I don't think you ever get away from it entirely. It is my goal this quarter to make students write as many of any given construct as possible in class, so that the low-level syntax becomes automatic, while using tests to keep the high-level goals in sight.

Which brings us to the second reason for using constant testing: students need to learn how to find mistakes by thinking critically about their output. Part of that process involves teaching them to use the developer tools: how to read a Firebug log, understand an interpreter error, and examine values in the debugger. But it also means they need to learn to check their code constantly, and to have thought about what they expect to get out of any given block. While I'll be providing tests on quizzes and homework assignments, so that students can immediately see if their answer was correct, the ultimate goal is to have them write their own simple tests to check their own code.

It's my belief that most of my students know what they want to do at the very highest level, but they're not able to break those goals into smaller pieces, and they don't know how to figure out when the smaller pieces stop working. My hypothesis is that writing tests may not be enough to create critical thinking where none exists, but it will serve as a good starting place for discussions of problem-solving strategy: what caused this test to fail? What were our expectations, and how were the results different? Was this test actually a good test to begin with, even if it "passes?" These are questions that good programmers ask, perhaps naturally, but I refuse to believe that they can't be encouraged in any student.

March 7, 2012

Filed under: tech»coding

jQuery as a Second Language

At this point, with the winter quarter at SCCC drawing to a close, I'd like to add onto my earlier comments on teaching JavaScript. I would still argue that it's not a great first language--too much reliance on other technology stacks (the browser, HTML, CSS), among other things. But John Resig's original post also talks about working around that complexity with libraries, and that speaks to a deeper divide in the JavaScript community: should newcomers learn "JavaScript," or "jQuery?" In this, I'm increasingly on Resig's side.

It's easy to understand why many JavaScript programmers are so adamant that newcomers should learn the language first. Sites like Stack Overflow are full of people whose answer to every JavaScript question is "use jQuery," even in response to simple problems that should be solved more directly. There are a lot of people out there whose idea of being a JavaScript programmer means "I can include jQuery and a few plugins on my page." Not that there's anything wrong with that.

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.

In fact, it probably gets in the way of doing any real, productive learning. This quarter, caught up in the desire to do things "the right way," I taught JavaScript from the DOM methods up. As a result, we didn't get to jQuery until the sixth week--halfway through our time!--and several students asked "why would we ever use this?" The jump from the DOM to actually being effective is just too far for beginners, and without that reinforcement, they're likely to throw up their hands and give up.

The other argument for JavaScript-first education is that learning jQuery will leave you with blind spots in the underlying language. That sounds reasonable, but is it true? I myself didn't learn the DOM methods first--I started with jQuery, and then I picked up the lower-level functions as I went along, usually as a way to write more efficient event listeners or work with XML. I would have a hard time pointing out any ways in which learning jQuery held me back from learning the language.

I suspect the opposite is actually true: jQuery serves as a better introduction to modern JavaScript than the DOM methods do. Over the last few years, the way people write JavaScript has evolved rapidly: greater use of closures and functional coding, creative abuse of objects as hashes, and a variety of inheritance methods. Using the DOM will not help you learn these common patterns, while jQuery relies on them heavily. Teaching the DOM methods first means less time to cover the many uses of first-class functions, meaning that students who go on to use underscore.js or d3.js (among others) are likely to be completely baffled by the code style they see there.

Ultimately the call to teach "real JavaScript" first is exactly the kind of macho posturing that's far too common throughout tech culture, like saying that only assembly programmers are "real programmers" and only people who build their own computers "really understand" them. It's ridiculous there, and it's still ridiculous in the browser. No-one would suggest starting a basic programming class by introducing the Win32 COM API, but we're supposed to force JavaScript programmers to learn at the lowest, least-useful level of abstraction? Most tellingly, if you asked people who are advocating for DOM methods, I have no doubt that they're all using jQuery (or another library) when it comes time to get work done.

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.

February 23, 2012

Filed under: tech»coding

JavaScript as a Second Language

In December, jQuery creator John Resig (who is now working as a coder for self-education startup Khan Academy) wrote a post about teaching JavaScript as a first programming language. I'm a big fan of JavaScript, and by that point I knew I was going to be teaching it to all-new programming students, so I read it with interest. As Resig notes, there's a lot going for JavaScript as a starter language, mainly in the sense that it is ubiquitous, in high demand from employers, and easy to share.

But after spending some time teaching it, I'm not sure that JavaScript is actually a good language for first-time programmers at all--and it has little to do with the caveats that Resig raises, like its falsy values or block scoping. Those are tricky for people who have previous programming experience, because they don't work the way that other languages do. But students who have never programmed before have more fundamental problems that they're trying to wrap their heads around, and JavaScript (in the browser, at least) adds unnecessary complications to the process. My students so far have had the most trouble with:

  • Loops - JavaScript has two kinds, one for objects and one for arrays, and they're both confusing for beginners.
  • Input - apart from prompt(), there's no standard input. Learning to write "real" inputs means dealing with event listeners, which are complicated.
  • Output - There's document.write(), or alert(), or console.log()... or the DOM. I don't know which is worse.
  • The difference between defining a function and running a function - including figuring out what arguments mean, and why we use them.
These are common beginner hurdles in any language, but JavaScript does not make them any easier. Unlike, say, PHP, JavaScript does not offer a loop construct that can be used on any collection (foreach), and it doesn't offer an output mechanism that students will be able to rely on: the console is developer-only, and the other methods (while simple and effective) are deprecated in place of the DOM for displaying information to users.

And don't get me started on the DOM. As a complex, tree-shaped data structure, it's already tough enough to teach students how to traverse and alter it. When you start getting into the common ways that JavaScript interacts with data stored in HTML and CSS, even in relatively simple ways, it becomes extremely confusing for people who have never tried to write a program before--particularly if they're not very experienced with HTML/CSS in the first place. Now they're effectively learning three languages, each with its own quirks, just to do basic things.

This quarter I taught Intro to Programming using JavaScript. I built a simple scratchpad for students to use, so they wouldn't have to install any browser tools or understand HTML/CSS, but the result felt clunky--a lot of work to monkey-patch flaws in the language for the purposes of learning. Next quarter, while there's little I can do about all-new programmers who jump right into Intro to JavaScript, I do plan on using Processing for Intro to Programming itself. While the language syntax is similar to JavaScript, the all-in-one nature of the Processing environment--an editor with a built-in, always-visible console and a big "play" button for running the current sketch--means that I can spend my time teaching the fundamentals of coding, instead of explaining (or hiding) the idiosyncrasies of scripting in a browser.

September 21, 2011

Filed under: tech»coding

Typedefs

I spend a lot of time at work straddling four programming languages: PHP, SQL, JavaScript, and ActionScript. Many of our projects use at least three of these, if not all four. Yet while there's certainly some degree of domain-specific knowledge in each, there's more technique shared between them, floating off in the indefinite space of "software engineering."

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.

The result is Typedefs, a simple blog where, in each entry, I pick an item from Wikipedia's list of data structures, implement it in JavaScript, and then explain how I did it and provide a quick demonstration. So far, I've done linked lists (the old classic), AA trees, and heaps. Next I want to try a chunk-based file, like PNG, and also a trie or bloom filter for text lookup.

I can already tell that working through these examples has been good for me--not because I expect to implement a lot of AA trees, because in my experience that's pretty rare, but because building these structures gives me a better understanding of how languages actually work, and a wider range of algorithms for solving other problems. The mechanics of a heap, for example, define a set of interesting ways to use arrays for storage and processing. AA trees really force you to examine the implications of pass-by-reference and pass-by-value. Linked lists are always a good experiment in miniature API design. As bite-sized, highly-technical exercises, they give me a chance to stretch my skills without having to build a full-sized JavaScript application.

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.

March 31, 2010

Filed under: tech»coding

Ticket to Ride

Here's what I've learned from releasing Underground to the Android Market:

  • Mobile software is like blogging. Both have a direct relationship between good will and update frequency. People love updates. Every time I upload a new version, there's a spike of new downloads and positive comments, probably because it kicks Underground back up to the top of the Market listings where people can find it. If I were doing this for money, the lesson would be clear: update often with small tweaks. Indeed, Android's no-approval update process makes this a lot more feasible.
  • Code for yourself, it'll find an audience. Not a large audience, but one that's remarkably vocal. It's self-selecting, sure, but the comments for Underground in the Market have been largely positive, with several glowing reviews and people who like it enough to e-mail me. Some, in fact, who maybe feel they should e-mail me a little too much. In no small part, this is just a factor of scale: centralized distribution has its downsides, but the sheer reach of it is impressive.
  • Java is exactly as annoying as I remember. When I was in high school, I learned a little bit of Java--enough to think that it was a language designed by uptight Computer Science professors to make even small tasks many times more complicated than they needed to be. Years later and with a bit more experience, my opinion hasn't changed noticeably. Checked exceptions (those that require a try/catch block) may be the most annoying innovation of the last twenty years, but if you're used to dynamic languages (and what web worker isn't?), it'll be the ridiculous InterfaceListener abstract classes, lack of first-class functions, and overzealous static typing that'll really drive you nuts. I can be productive in Java, but I never stop feeling like I'm typing three times as much as I would in PHP or ActionScript.
  • Open source means education. Underground isn't incredibly complicated, but it has a couple of neat tricks up its sleeve--mostly in the code for capturing the home button and querying the package manager. It's unlikely I would have been able to figure these out if I hadn't had most of the Android source tree available to me, including the built-in launcher. And in turn, while nobody else has submitted any patches to Underground's code repository, I've had several people write to say that they appreciated being able to read through my code and learn from it. With that in mind, I spent about an hour last commit adding extensive comments. From my perspective, open source is only partly about getting outside input. It's more about leaving the process out there, encouraging transparency, and lowering the barrier of entry--increasing generativity, in other words.
  • Seriously, people, e-mailing me once is flattering. Ten times starts to get a little creepy.
  • The Android UI toolkit is relatively painless. I did almost no work to transition Underground to high-dpi devices, and it scaled beautifully (the use of device-independent pixels for layout is highly recommended). Being able to build a custom dialog box using the same tools as everything else, then just inflating it and throwing it into the AlertDialog Builder, is pretty cool. For a while, I had some builds that incorporated much more complex UI ideas--some fancy designs submitted by a user that added some graphical touches, including a frame around the main list. I was impressed by how simple it was--particularly the PreferenceScreen built-in class, which handles both preference getting/setting and look-and-feel for you. And while I'm not a huge fan of XML files, using them for layout also means that when you shelve large chunks of the design (as I eventually did), you can just comment those sections out. In a lot of ways (as with the rest of Android's design), it reminds me of the best parts of web programming translated onto a native platform.

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.

May 14, 2009

Filed under: tech»coding

Tribal Procedures

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.

April 29, 2009

Filed under: tech»coding

Voxel Populi

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:

  • Actionscript 3 is a surprisingly fast language with a nice built-in graphical library, but its methods for working directly with framebuffers are very limited. In C, I would have loaded the map data into an array and run through it with pointers, poking values into screen memory as I went. Actionscript, being a managed language, has no pointers, and its arrays kept giving me fits. When I did get the code running using data structures, it was often too slow, because the code had to be more complex (to add bounds-checking, casting, dereferencing, and index-manipulation). In the end, I went back to doing data retrieval using BitmapData.getPixel(). In comparison to array operations, getPixel offers two nice features: it fails gracefully when my rays overshoot the map, and it accepts floating point values. The end result is actually faster, even though getPixel itself is almost twice as slow as simple array lookup. As always, avoid premature optimization.
  • Likewise, I tried a lot of different methods to see if I could beat setPixel(), without any success. It's odd, but there doesn't seem to be any speed advantage to populating a ByteArray and then copying it into the BitmapData, either for the entire frame or for each column. And the bookkeeping's a lot easier this way.
  • You may notice that there's not much penalty for opening the SWF at full size. This is counterintuitive: voxels don't scale to high resolutions well, since they have to cast a ray for each pixel of the screen buffer. So figuring that it was always going to be pretty blocky anyway, this version renders internally to a 320x240 bitmap, then uses Flash's native scaling bring it up in size.
  • In fact, generally speaking, I try to write for the parts of the Flash API that are clearly implemented in native code. It just makes sense to let the VM do the heavy lifting. In this case, bitmap scaling and copying is very fast, and the blur filter is optimized for powers of 2. Put an 8-pixel blur on a 50% transparent bitmap copy, and voila! instant bloom effect with practically no performance penalty.
  • Actionscript may not have pointers, but some of the same rules apply. For example, property lookup on an object (dereferencing, if you will) is a lot slower than making a local reference variable. Also, creating objects (allocating memory) is expensive. I got a pretty significant boost early on by switching from "ray.x" to "rayX" for casting, initializing variables outside of loops, and storing references to object properties (particularly those behind two or three dot operators) whenever possible.
  • Most of the program is spent in a single loop, incrementing rays and checking for intersections with the landscape, so that's where optimization was really needed. I spent some time tweaking the operations there, but by far the most effective addition was LOD: effectively, lowering the accuracy of the ray as it gets farther from the viewpoint. Implementing level-of-detail alone was responsible for a 400% speed increase. It works by increasing the casting distance each time through the loop. To get a logarithmic increase, the increase is equal to the ray's length shifted to the right by a set number of places. When you change the LOD above using the [] keys, you're changing the amount of the bitshift. At 10, the ray is accurate out to 1024 units (which is the maximum view distance). On my laptop with the debug player, setting it to 7 (meaning that detail drop-off begins at 256 units) seems to be a good tradeoff between speed and accuracy. A setting of 5 or 6 is faster but with visible jumpiness. Below 5, some wacky (but fun) behavior emerges.
  • Another increase comes from being smart about the ray behavior. I render each column of pixels from the bottom up. Since the heightmap can only contain one height value, any given pixel's ray will never intersect the map in less distance than the pixels under it, so it can continue from the same X and Y coordinates as the previous ray, adjusted to a new height and vertical angle. Also, once a ray hits nothing but sky, all rays above it will do the same--so there's no need to bother with them.

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?

December 10, 2008

Filed under: tech»coding

DOM and Gloom

Against my better judgement, I've started working with JavaScript at work. It's a huge mistake, because learning new technical skills in a department that's weak in them is suspiciously like forming a debilitating drug habit: first you're just creating some tabs, then you work out how to stripe alternating rows in financial tables, and before you know it you've been assigned to build a searchable front-end for the video database. I specifically wanted to not be a programmer when I went into higher education, and look where that got me. But there doesn't seem to be any way around it, particularly after learning Flash--and Flash was itself unavoidable, since I strongly believe in using the right medium for the message, and CQ.com's messages happen to be very data-heavy and in need of visualization.

In any case, I'm conflicted. I actually really like JavaScript solely as a language. When I go to write something quickly in Visual Basic or Python now, I find myself missing features like dynamic objects (where objects can add properties and methods during runtime), long lambda functions (which are created in the middle of other code, for things like callbacks), and first-class functions (not everything has to be wrapped in a class, and functions can be passed around as objects). I feel like I finally get why people are so enthusiastic about LISP and Scheme, where a lot of these features originated: it makes for a very expressive, flexible language.

But using JavaScript means writing for the web browser, which means writing for the Document Object Model (DOM), which is a dreadful affair. I apologize for writing that, since it's rehashing something that everyone knows, but it's absolutely true. Even using a library like JQuery, thus eliminating some of the frustration of cross-browser incompatibility, cannot make this enjoyable. It's all the pain of writing a web page, compounded by rewriting it dynamically through a set of clumsy, half-blind interfaces, hopefully without breaking anything beyond recognition. JQuery doesn't solve that problem. It makes it slightly less annoying, at the cost of forcing coders to type "$()" about a million times, at which point I might as well be using LISP anyway.

In order to see how nice JavaScript could be, I think you have to write something in ActionScript, where an actual API library is provided for things like UI elements, file access, events, and graphics. Freed from having to use the HTML DOM as a layer for presentation and interaction (something for which it was arguably never designed), it's actually possible to get into a rhythm and discover the good parts of JavaScript/ActionScript/ECMAScript. It's a real wake-up call--with the downside that it makes going back to the browser even more depressing.

October 7, 2008

Filed under: tech»coding

In Defense of Flash

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.

You don't have to tell me that Flash has flaws. It's a pain to deep-link, particularly since it has no access to the browser's address bar--doing it requires adding extra Javascript to the page. The plugins on anything other than Win32 can be cumbersome, slow system-hogs. And yes, there are a lot of annoying Flash ads out there (although that's certainly not Adobe's fault).

But all this pales in comparison to what they've accomplished with Flash. If nothing else, look at it pragmatically: in only a few years, using a platform that started out with far less functionality, Flash basically took over the rich Internet application space. Java applets have been left to languish in backwaters like the Facebook photo uploader (the Flash plugin's comparatively quick startup and tiny download size no doubt has a lot to do with it). Javascript/HTML support for video and canvas drawing is still limited--without Flash, the Internet video sea change probably wouldn't have happened.

And in the meantime, the technical aspects really can't be set aside. Flash started out as a tool for doing frame-based animation, and a lot of its features still exist on that basis. But ActionScript, the Javascript variant that runs Flash's interactive components, has gotten more and more sophisticated, especially after it was revamped into a fully object-oriented language with Flash 9. At this point, despite accusations of sluggishness, it's still fast enough that the Tamarin VM Adobe created will be folded into Firefox for executing Javascript, and it competes favorably with the new engines powering Chrome and Safari.

There's a common criticism that the kinds of things done in Flash could also be done in Javascript without the proprietary plugin. But speaking as a web multimedia producer, the problem with that approach is that it would require me to use Javascript, which means diving into the vast sea of browser incompatibilities (or, more likely, relying on a browser framework like jQuery). And even then, support for custom drawing or multimedia is strictly limited. What Flash brings to the table is a reasonably well-written API for performing those kinds of functions, backed up with a reliable level of cross-browser performance. Eventually, browsers may catch up to that. But right now, if I want to do rich interaction with no headaches, my best option is probably Flash (or Silverlight, but it's not widespread enough yet).

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.

Past - Present - Future