My feet wandered back into the area of old Millbrook this weekend, and I expect they will tread that way again soon, and hopefully for years to come. This region, like the Pine Barrens in the Southern part of the state, completely fascinates me, and for the same reason. For such a small state New Jersey must be unique in having two such areas of restored wilderness. I say restored because in both the Pine Barrens, which make up much of the Southeastern corner, and the Highlands, which take up the Northwestern, civilization once thrived. Agriculture, mining, lumbering, manufacturing, transportation; every major enterprise of eighteenth and nineteenth century America was engaged in on these Northern slopes, and those Southern plains. Today there are, for the most part, just the woods, the hills, the sandy trails and woodland tracks that were once arteries, and the little dots on old maps that mark the towns.
I entered the woods near Chester, New Jersey by stepping over a thin cable slung between two wooden posts and heading up a narrow gravel-covered track that disappeared in leafy dimness. The better part of forty-five minutes later I was barely a mile in, but then I had the camera with me, and had seen many things worth a short delay: a spring from which orange, iron-laden water bubbled; remnants of a 19th century sewage system; ancient stone walls lining a suspiciously regular cut in the earth; century old black cinders born in the firebox of a steam engine. The path I followed was unmistakable as an abandoned railroad right of way: unlike any forest track a railroad cuts long smooth slices through the terrain: no tight curves; no steep grades. It’s why they make such nice walking trails once the trains no longer need them. The starkly artificial features of these constructions remain visible against the fractal chaos of nature long after the rails themselves have been pulled up and melted down.
Kittatinny Mountain begins at the place that is truly a water gap, thrusting its granite shoulder to the sky just East of the spot where the slim ribbon of interstate 80 skips across the Delaware River and enters the state of Pennsylvania. For many people this is perhaps all of the mountain that they see, as they speed across and over to the outlet stores of Stroudsburg, or the great expanse of the nation beyond. But the hill stretches more than forty miles Northeastward, well into southern New York’s Orange County, and is but one stony promontory of many in the long range that runs from New England deep into the south. Atop Kittatinny’s knife-edge summit runs the famed Appalachian trail, while at its feet the river lies like a sleepy snake, seeming in places to lap right up against the long ridge, marking New Jersey’s northwestern border in white-flecked silver.
At the end of the last section I tied off a discussion of the graphics rendering in AvalonLife with a look at its performance running a large model on a large grid. There is so much happening under the hood that I had sworn it would crawl when it came time to actually draw anything. And yet, the performance when I got it running was more than acceptible. This is interesting, but why is it notable or important? Nobody is actually going to program games in the WPF, are they? A few weeks ago I would have said “no.” Now… well, I’m not so sure. The framework is efficient and very well designed, and there is a whole layer of 2D and 3D animation support that hasn’t even been touched on here. I can see those facilities being used for some relatively low-velocity games, and if it turns out that there are good ways to interop WPF and Direct3D, such that you can use WPF and C# to script and drive the interface, and then overlay it on a rendered 3D scene, then things could get much more exciting. It’s the “overlay” part that is the problem now, as I understand it, but perhaps Microsoft will come up with a solution. Even if the graphics model works for games, there are others reasons to be wary about designing a game with thousands of on-screen objects the way this one is designed. For one thing, it eats gobs of memory. AvalonLife takes up something like 80 megs running a 100 x 100 model.
Drawing the Grid
When I first started mucking around with the implementation of Conway’s Game of Life in WPF my thought was that I would create a drawing surface and use System.Drawing objects to paint in my grid. I went as far as looking into which WPF object would be right to do the drawing on, settling on Canvas, because it offered absolute x,y positioning. I started to examine the Canvas object more closely, and compare it to the drawing tools that you find in System.Drawing. It quickly became clear that I was on the wrong track. None of the tools in System.Drawing line up with the way things are defined in the WPF. Take the most basic facility of 2D drawing in Windows.Forms: the Graphics class. This class implements IDeviceContext, and is what you paint on. There are two ways to get one: in the arguments of a Paint event (WM_PAINT message); and by calling the CreateGraphics() method on a Form. Well, there isn’t a CreateGraphics() defined on a System.Windows.Controls.Canvas object. Nor is there one on a System.Windows.Window object. There also isn’t a Paint event on a WPF window or control (although you can embed a WPF control into a System.Windows.Forms.ElementHost, and that has a Paint event). Something wasn’t right, and that something was the fact that I wasn’t yet thinking in WPF. I was thinking in terms of the old way of creating 2D images in a window. I started Googling, and that’s when I ran into Scott Allen’s article on OdeToCode. When I saw what Scott did to paint the grid in his version of the Game of Life, I was a little startled, and more than a little intrigued. As you’ll see in a minute it is just about the last way you would think of painting an interface if you were writing a game, and I’m sure it’s the last way Scott would think of doing it if he were writing one.
Resources and Styles
In the previous section I illustrated the basic XAML declaration of the AvalonLife main window, and talked about the resulting structure of the application’s interface both in terms of the layout and object hierarchy. The code that I presented, however, would not create anything of interest if it were compilable, because most of the detail had been removed for clarity’s sake. There’s no way I can cover all the details regarding how to instantiate, position, style, and interact with GUI elements in this article. But I do want to take a quick tour of a couple of very important subjects, with emphasis on how I applied the illustrated techniques in AvalonLife. These two topics are resources, and styles, and how they effect controls. To get going let’s take a look at a section of XAML that was redacted from the example posted in the last section. The code is takern from the Window.Resources section of the ALMainWin.xaml file. I have presented two resource declarations, and following them the declarations of the two controls that use the resources. Bear in mind that all the declarations of the containing panels and other controls have been removed. Here it is:
XAML and the User Interface
What good is a simulation without an interface? Not much. Of course, the word interface can be interpreted in various ways. I have worked with simulation models in the past that chugged along behind the scenes for hours or days, a blinking cursor in a command window the only sign that anything was happening, and then ended by spitting out a bunch of data. That’s an interface, but for AvalonLife I wanted something much more interactive. The pleasure in running Life models is in watching them evolve, so the program needed a display that could render the model to screen after each iteration. There were also a number of controls implied by the design and the needs of the simulation: timing interval settings, grid size, grid type, etc. It was actually a rather simple set of requirements for an interface, and as the visual end of a project is nearly always the most satisfying for me, I didn’t have any reluctance about diving in and starting to design what AvalonLife would look like. I had this little problem, though: as a server-side developer, even as one with a long history of Windows GUI development going back to HWNDs, I had always found it hard to keep pace with the changes in Windows interface technology. I had obtained a working competency at Windows Forms development, but now as I approached the AvalonLife project I had to face the fact that Microsoft had gone and changed it all again.
Most of this article is about the new GUI technologies in Windows Presentation Foundation, but I think it is worth devoting a few free web column-inches to the nature of the model and controller. I’ve always enjoyed simulation programming, and although this is a very simple simulation it does illustrate some interesting techniques. Some of the decisions made in the design of the model and controller are driven by the needs of the interface, however they have been implemented in a way that preserves layer autonomy and avoids creating couplings, so I hope to be forgiven this minor breech of architect-iquette. Since the heart of any simulation is its model of the world, let’s start with that.
The Game of Life
The Game of Life was invented by Cambridge University mathematician John Conway, probably some time in the late 1960’s. It first gained widespread attention after being mentioned in a 1970 Scientific American column on mathematical games. If you’re interested in the history of it, there is a very good dissertation on Wikipedia, and I have also included some information in AvalonLife’s help file. What we need to know here is fairly straightforward: Life is a cellular automaton implemented on an idealized 2D grid. On each iteration of the automaton cells in the grid are turned on or off according to rules that determine their state based on that of their immediate neighbors. The rules themselves are inordinately simple. They are:
For cells that are ‘on’:
– If the cell has 1 or 0 live neighbors it is turned off
– If the cell has 2 or 3 live neighbors it remains on
– If the cell has 4 or more live neighbors it is turned off
For cells that are ‘off’:
– If the cell has 3 live neighbors it is turned on
I set out a few weeks ago to build a simple example application that takes advantage of the new user interface technologies in Microsoft’s Windows Vista. These technologies are packaged as .NET 3.0, which is an extension of the 2.0 version of the framework. Extension is the right term, I think, despite the fact that the extending bits are pretty significant. Basically .NET 3.0 retains all of 2.0 unaltered, and adds three major new layers of types. Really these are three new frameworks within the larger .NET space. They are: the Windows Presentation Foundation (WPF), formerly called Avalon; the Windows Communication Foundation (WCF), once named Indigo; and the Windows Workflow Foundation (WWF), which probably also had a codename, but I don’t know what it was. The WPF targets Windows user-interface development, the space that Windows Forms has inhabited for a few years now. The WCF is focused on enabling advanced networking applications, while the WWF is a standardized means of representing and executing logical workflows. There are some very cool possibilities in all of it – I’ve recently read about peer-to-peer information sharing apps on WCF, and I know of one or two people fooling with using workflows to drive game agent behavior – lots worth writing about there. But for now I will stick with WPF, because it is enough of a revolution for one article. If you want a place to start digging in you can’t go wrong with Microsoft’s .NET 3.0 website.