Project Description
Unscrambler is a multitouch WPF word game built with MVVM Light in order to show how to use the touch maniupation and inertia features included in WPF4. The object of the game is to form words from scrambled tiles of letters.

Introduction

Unscrambler was my first effort to use multitouch functionality in WPF. I've refactored it a bit, but that process is ongoing (of course!). I also used this exercise as an excuse to kick the tires on MVVM Lite and I was quite pleased with how it worked out for me.

If you are primarily interested in the actual multitouch API and how I consume it, have a look at TilePositioner and Gameboard.xaml.cs. I factored out TilePositioner and TileManipulator because I was not happy with the complexity of Gameboard.xaml.cs. Because both of those two "helper" classes are still very UI dependent they are not very testable right now.

Requirements

Unscrambler will only be useable on a Windows 7 machine with multitouch support. I have not built in any mouse support at this point

How To Play

Unscrambler is very simple. Start a new game and you will be presented with a group of Letter Tiles which will be randomly scattered over the board. Some of the tiles may we rotated and thus harder to read--you can twist that tile into an easier-to-read position by touching it with two fingers and rotating. To unscramble the word, move the Letter Tiles from the wood up into the chalkboard. It is very important that the tile be completely within the boundaries of the chalkboard in order for Unscrambler to know that you intend that letter to be used in your proposed answer.

Unscrambler will track what your current proposed answer is at the top of the screen next to "Your Answer:". Once you have correctly spelled out the word Unscrambler automatically notifies you that the word is correct and moves on to additional words in the round. The round consists of unscrambling 3 words, and the entire round is timed. You are trying to unscramble 3 words as quickly as possible. There is also the ability to skip a word if you simply can't get it. Additionally you can get "hints" where Unscrambler starts to spell out the correct answer one letter for each you time you click the "Get Hint" button. But each hint also incurs a 2 minute time penalty, so that can be counterproductive.

Technical Overview

I built Unscrambler trying to follow best practices for MVVM. Therefore I've separated the functional code into two projects to further emphasize the proper separation of concerns between UI code and ViewModels. I've also got a test project which quite thoroughly unit tests everything in the ViewModel projecty. I generally use a ViewModel first approach. The ViewModels try to be good citiziens that are intended to be truly agnostic of the view that goes with them--thus they throw exceptions when things are done incorrectly.

The UI project is not unit-tested. I hope over time to be able to rememdy this, but we'll see. The views in the project use DataTriggers bound to some key properties on the ViewModels to show or hide views as appropriate. I know DataTriggers are a controversial choice (not in Silverlight, some people see this as untestable conditional logic embedded in XAML) but I find them to be an intrinsically UI concern and therefore appropriate. Perhaps I will change that in the future, we'll see.

From a UI perspective, here's the heart of how the game works: the Gameboard UserControl contains a Canvas which in turn contains a custom control I created called AnswerCanvas. This is a subclass of the WPF Canvas class that exposes a few DependencyProperties such as Word, CurrentAnswer, and IsCorrect. It also contains a public method called UpdateAnswer() which in turn iterates through all its children and uses a custom comparer to order the tiles it contains by their x-coordinates--effectively allowing the panel to read what its children say "left-to-right" on the screen.

The Gameboard uses the TilePositioner to new up the appropriate LetterTile user controls and add them to the main canvas. Then it uses the TilePositioner to randomly create TranslateTransforms and RotateTransforms for each tile so that they appear scrambled. Gameboard also uses TileManipulator to wire up the WPF4 multitouch events to the tiles so that when the user rotates or moves tiles the transforms are updated appropriately. There is also functionality in TileManipulator to make sure the tiles cannot be dragged off the canvas. Gameboard's codebehind has code that will reparent the LetterTiles to the correct canvas--if it has been dragged entirely over the AnswerCanvas (which appears as a chalkboard on the UI) then it removes that LetterTile as a child of the main canvas and adds it as a child of the AnswerCanvas, allowing Unscrambler to know that that letter is intended to be part of the answer. Of course if the user drags the tile out of the AnswerCanvas then it parents that Letter Tile back in the main canvas again.

For a lightweight app like this I didn't use a true IOC container. Instead, I used App.xaml as a primitive IOC container. This isn't recommended since it only supports setter injection (which is not my preferance), but it did work and minimize this app's dependencies on other libraries. App.xaml also contains the XML list of words that Unscrambler uses as its word bank--it somewhat unusually takes that XML and uses ObjectDataProvider to call the XElement API to parse the XML and then pass that XElement into the RandomWordChooser.

That's it in a nutshell. I hope to continue to enhance and refactor this app.

Credits

Major thanks go out to Brian Peek (Multitouch Madness), Davide Zordan (http://multitouch.codeplex.com/), and Lester (http://blogs.msdn.com/llobo/archive/2009/11/24/new-wpf-features-multitouch.aspx) for their work--without it I would never have been able to build Unscrambler and learn about manipulations, inertia, etc.

Last edited Apr 26, 2010 at 10:18 PM by adajos, version 3