4D Sudoku: development postmortem

The reason I haven't been updating this blog regularly for a long time is twofold: firstly, I haven't had anything particularly profound to say; and secondly, I've been busy working on 4D Sudoku, which has now launched.

4ds-shot-1Strangely, the roles have been reversed on this project, as I'm usually a server-side database and web developer. This time, I've bitten my lip and learned Flash, and someone else did the site.

Since about 1996, I've been preaching "Flash is Pants", as for the most part it has been, in my opinion. Even now, the original crappy API design shows through the cracks.

I mean, the history of Flash is basically one of a simple animation package that had extra stuff grafted on until it was unrecognisable as the original package. Even now, it has a slightly split personality: the traditional "timeline-with-bits-on" approach, and the more programmatic ActionScript approach where the timeline is pretty much ignored.

Now, Flex Builder (and other development tools, of course) offer the option of a "pure" ActionScript 3 project, which is akin to developing a Java application. None of that horrible timeline stuff, and the ability to engineer a "proper" application in a "proper" language. In fact, assuming the Flash authoring package is completely excluded from the mix, and apart from the slightly odd type syntax that Emacs can't quite figure out, I must say I really quite like AS3. It's not perfect, but it's a very comfortable language and API to write for.

Anyway, back to 4D Sudoku.

I didn't really intend to write this project: I was approached by my old friends/bosses/clients, Rus and Ben, to write the design for an online version of the puzzle game they were developing for manufacture. I was not in a position to actually write the game, as firstly, I was still recovering from major back surgery and couldn't work for more than a couple of hours a week if that, but also -- as I mentioned above -- because I'd never written any Flash before, let alone a 3D game.

So, the idea was that I was going to write a specification they could farm out to a Flash developer or an agency to build. However, it's one of those projects where we didn't really know what we wanted, so it was hard to write the spec. For a start, without any Flash development experience, I couldn't say what was possible and what wasn't. So, I had to learn a bit to research enough to write the spec.

Not long into that process, I realised writing a full 3D drag-and-drop game wasn't within the capabilities of most Flash developers we'd be able to find, especially since we didn't know how the game mechanics should work either. So, to cut a long story short (too late!) I ended up writing the damn thing. I figured (rightly) that the mechanics of the game in any language were more difficult to solve than the relatively easy task of learning a new programming language and API.

The game uses the Papervision3D graphics engine, although I got my hands fairly dirty underneath the intended public interface. For a start, when I was originally prototyping and kicking ideas around, PV3D was still pre-GreatWhite and the published API couldn't really do what I wanted... or maybe I couldn't figure out how to use the published API to do what I want, to be fair.

I'm not particularly impressed by PV3D's internal design. It's not a particularly clever design, but it is quite a simple one, and I suppose that's the point. However, it feels to me like most development is concentrating on effects, import/export and so forth, rather than the quality of the core rendering pipeline.

By subclassing and overriding a lot of the core objects (especially, DisplayObject3D, Scene3D and a few others) I managed to get it so objects were only projected when they moved ("lazy", or "smart"), as opposed to PV3D's insistence on recalculating everything all the time. This gave me a massive boost in performance.

The PV3D event model was largely ditched. It seems to be tied very closely to object interaction and also very strictly to the rendering pipeline, which makes unhindered drag and drop quite hard to implement. I ended up using a lot of invisible proxy objects (planes, mainly) for the drag-and-drop, and doing the intersection tests manually.

I also developed an unhealthy obsession with quaternions. I based all objects -- well, nearly all -- on two classes I created called SmartGroup and SmartTriangleMesh. As well as implementing the "smart" behaviour listed above, they also wrappered the main transformation matrix of DisplayObject3D and TriangleMesh with a quaternion (using my own Quat class), to allow the smooth rotations I needed for the game.

In hindsight, I think I went a little overboard with the quaternions.

Fortunately, I could do all of these overrides without altering PV3D at all, although it might have been better if I had. I'm not sure I'd pick PV3D again, as some of the other 3D engines might suit my needs better.

In developing the game I also used the Box2DFlash library for the cube floor physics. Of course, a proper 3D physics engine would be ideal for this game, but I didn't have one available for AS3 at the time, and it wasn't worth developing one for this project: it would have improved the game by 5-10% while taking up 90-95% of the development time.

Last but not least, I also used Tweener and GoASAP extensively. Tweener was used for the main game code, and my policy was to tween everything that moved if I could. I managed nearly all transitions, but some (particularly cube dragging) just follow the cursor. I tried to tween them, but getting them to work was just too time-consuming for little reward.

When it came to doing the Instructions, Tweener didn't quite cut it: it just wasn't built to simultaneously animate 27 or more 3D objects through coordinated, complicated paths with complex sequencing. By then, however, GoASAP had been released which did the trick. Rather than using a sequencing library built on GoASAP, I used GoASAP itself, building custom LinearGo classes and combining them with Sequences. This was quite a bit of work, but I think they turned out well.

I'm fairly happy with the end result. The code's a hack job in places, and is more complicated than it needs to be due to lack of design. If I were to write it again, I'd sit down and come up with some better (and more unified) class designs that would be more amenable to animation, interaction and manipulation.

In retrospect, this project took longer than expected for a few reasons: firstly, I had never done any Flash or ActionScript before. Secondly, PV3D wasn't quite mature and was fairly undocumented, so I had to do a lot of research and experimentation. Thirdly -- and most importantly -- I was working without a plan, spec or design. For this kind of experimental project, I like to work organically, but it's not an efficient way to work. Then again, if I had tried to come up with a spec, I would have come to two conclusions: firstly, the project's impossible, and secondly, I had no idea how to go about writing it. Fortunately, I would have been wrong on the first point.

It was a pleasure working with Simon (the site developer), Vince (the crayon pusher), Paul (the game's inventor) and as ever, Rus and Ben. In addition the rest of the Starberry gang pitched in, giving assistance, opinion and sometimes just kicking the tyres. I pushed pretty hard on most of the game design as it was my baby and I had very strong opinions on the way it should work, but the rest of the team supported me and also pushed back where appropriate.

Anyway. The next project's in the pipeline, and fortunately it looks a lot easier and quicker... as long as I can understand all this iPhone documentation!

Tags

Tracking

Leave a Reply