WP7 and the Phone Controls Toolkit
September 6, 2011 Leave a comment
I started hooking up events to my Panzer General Port over the weekend. There are some see events I want to capture and react to: a tap to activate a cell, a double tap to display information about the cell, a pinch to make the screen smaller or larger, and a swipe to move to a different location on the screen. Of these event, the pinch was the easiest to handle:
private void GestureListener_PinchCompleted(object sender, Microsoft.Phone.Controls.PinchGestureEventArgs e) { if (e.DistanceRatio < 1) { if (Game.CurrentViewLevel > 1) { Game.CurrentViewLevel--; UpdateHexes(); } } else { if (Game.CurrentViewLevel < 3) { Game.CurrentViewLevel++; UpdateHexes(); } } }
with the UpdateHexes basically redrawing the hexes that make up the board:
private void UpdateHexes() { this.MainCanvas.Children.Clear(); Game.CurrentBoard = BoardFactory.GetBoard(1); foreach (Hex hex in Game.CurrentBoard) { this.MainCanvas.Children.Add(hex); } this.MainCanvas.Width = BoardFactory.BoardWidth; this.MainCanvas.Height = BoardFactory.BoardHeight; }
It works great – here is the same view with the different zoom levels.
One of the more annoying things is that the screen “bounces” when you drag it past its designated screen size. Apparently, this is by design and no one has an easy way to disable this “feature”. You can ready my dialog on AppHub here.
The next event was the tap. This was easy to implement on the hex level, however, it was really hard to implement on the board level. I need it at the board level because the Hex class is unaware of its surroundings and many of the units actions in the game are dependent on its surroundings – what hexes it can go to, can it attack, etc… I solved this problem with alot of trial and error and my old friend, the Pythagoriem Theorem:
private static Hex GetClosestHex(Point point) { double testDistance = 0; double finalDistance = 99999; Hex closestHex = null; double a = 0; double b = 0; foreach (Hex hex in Game.CurrentBoard) { a = point.X - hex.CenterPoint.X; b = point.Y - hex.CenterPoint.Y; testDistance = Math.Sqrt(a * a + b * b); if (testDistance < finalDistance) { finalDistance = testDistance; closestHex = hex; } } return closestHex; }
The point is found in EventArgument for both Tap, Dopuble Tap, Drag Complete events:
private void GestureListener_Tap(object sender, Microsoft.Phone.Controls.GestureEventArgs e) { Hex closestHex = GetClosestHex(e.GetPosition(this.MainCanvas)); if (closestHex.CurrentUnit != null) UpdateHexes(closestHex); }
I finally added in a Kludge to determine the adjacent hexes for the selected hexes like so:
private static List<Hex> GetAdjacentHexes(Hex currentHex) { List<Hex> adjacentHexes = new List<Hex>(); //Above int targetColumnNumber = currentHex.ColumnNumber; int targetRowNumber = currentHex.RowNumber - 1; adjacentHexes.Add(GetHex(targetColumnNumber, targetRowNumber)); //Below targetColumnNumber = currentHex.ColumnNumber; targetRowNumber = currentHex.RowNumber +1 ; adjacentHexes.Add(GetHex(targetColumnNumber, targetRowNumber)); //Top Left targetColumnNumber = currentHex.ColumnNumber -1 ; if (currentHex.ColumnNumber % 2 == 0) targetRowNumber = currentHex.RowNumber - 1; else targetRowNumber = currentHex.RowNumber; adjacentHexes.Add(GetHex(targetColumnNumber, targetRowNumber)); //Bottom Left targetColumnNumber = currentHex.ColumnNumber - 1; if (currentHex.ColumnNumber % 2 == 0) targetRowNumber = currentHex.RowNumber; else targetRowNumber = currentHex.RowNumber +1; adjacentHexes.Add(GetHex(targetColumnNumber, targetRowNumber)); //Top Right targetColumnNumber = currentHex.ColumnNumber + 1; if (currentHex.ColumnNumber % 2 == 0) targetRowNumber = currentHex.RowNumber - 1; else targetRowNumber = currentHex.RowNumber; adjacentHexes.Add(GetHex(targetColumnNumber, targetRowNumber)); //Bottom Right targetColumnNumber = currentHex.ColumnNumber + 1; if (currentHex.ColumnNumber % 2 == 0) targetRowNumber = currentHex.RowNumber; else targetRowNumber = currentHex.RowNumber +1; adjacentHexes.Add(GetHex(targetColumnNumber, targetRowNumber)); return adjacentHexes; } private static Hex GetHex(int targetColumnNumber, int targetRowNumber) { Hex targetHex = (from hex in Game.CurrentBoard where hex.ColumnNumber == targetColumnNumber && hex.RowNumber == targetRowNumber select hex).First(); if (targetHex != null) return targetHex; else return null; }
Note how the LINQ makes for search for the correct hex a snap. I know have a way of detecting the selected hexs, surrounding hexes for units, and moving units to an end of a swipe:
This is all very cool (and very easy in Silverlight). Up next is how to handle 2 unit interaction….