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.
It’s been awhile since I’ve posted anything to this site, and while one excuse is that I was first looking for, and then ramping up in, a new job, another excuse is that I have spent the last four or five weeks checking out Windows Presentation Foundation and all the cool new interface programming techniques therein. The best way I know to get up and running on a new framework is to build something fun in it. The sample application I chose to immerse me in WPF was John Conway’s famous Game of Life. Yes, it’s Life! The game that has been implemented 1,195,043 times since 1970! Ok, so it isn’t a novel idea, and I am not even the first one to do it in XAML on the WPF. To make up for my sluggishness in getting up to speed on Vista-ness I obsessively massaged my implementation into a relatively polished state. Here’s a screenie:
AvalonLife running Gosper’s Glider Gun
I also wrote up a fairly exhaustive (others might say wordy, or long-winded) article on the design and implementation of the program. The article begins here. The program is available in .zip archive format with and without source code. Everything you need to run it is present in the default install of Vista. If you want to run it on XP you’ll need the .NET 3.0 runtimes, which are available here. If the source code is of interest you’ll need one or two other things. Instructions are at the end of the introduction to the article. Both packages include over 50 models in the AvalonLife .AVL native format, and you can also visit the Life Lexicon and drag the more than 100 models there onto the AvalonLife main window to load them. Have fun, and let me know what you think.
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.