What a drag

I am getting more into the details of the User Interface of the WinPhone7 game I am writing. I am using the ScrollViewer and the WindowPhone Toolkit.

Using the ScrollViewer_ManipulationStarted event handler, I check to see if there is a hex active. If it is, I call the e.complete() method so that we don’t scroll off the screen where the active hex is.

Using that model, I wanted to use the Tap and Drag completed events from the Toolkit. If the user taps a hex, that hex becomes active. They tap that active hex again, then the hex becomes inactive:

private void GestureListener_Tap(object sender, Microsoft.Phone.Controls.GestureEventArgs e) { Hex closestHex = GetClosestHex(e.GetPosition(this.MainCanvas)); if (Game.ActiveHex == null) { EnableGameActiveHex(closestHex); } else { if (Game.ActiveHex == closestHex) DisableGameActiveHex(); } }

That works fine:


I then wanted to code up the drag event. If there is not an active hex, then dragging should do nothing and the scroll viewer will allow the user to inspeact any part of the board. If there is an active hex and there is not a unit in that hex, then nothing should happen. If there is an active hex and there is an active unit in that hex, then the unit should “move” to the hex where the drag completed (and the hex becomes inactive).

To that end, I coded up a quick event handler:

private void GestureListener_DragCompleted(object sender, Microsoft.Phone.Controls.DragCompletedGestureEventArgs e) { if (Game.ActiveHex != null) { Hex closestHex = GetClosestHex(e.GetPosition(this.MainCanvas)); if (Game.ActiveHex.CurrentUnit != null) { MoveGameActiveUnit(closestHex); } DisableGameActiveHex(); } }

Toolkit does not have an e.complete() method so I couldn’t call that on the drag end – but since I don’t enter the drag unless the hex is active, I should be OK.

Next, I added movement allowances to the active unit based on the movement cost of each hex. Like last week’s post on recursion, I created a monster method and used the VS2010 extract method to make the code, well, suck less. To that end, I created a method that all of the movable hexes for the unit based on their max movement points.

private static List<Hex> GetMovableHexes(Hex startHex) { List<Hex> movableHexes = new List<Hex>(); List<Hex> tempHexes = new List<Hex>(); Unit currentUnit = startHex.CurrentUnit; int totalMovementPoints = currentUnit.BaseMovement; int unitMovementCost = 0; int pathMovementCost = 0; List<Hex> adjacentHexes = GetAdjacentHexes(startHex); startHex.PathMovementCost = pathMovementCost; foreach (Hex currentHex in adjacentHexes) { unitMovementCost = HexFactory.CalculateMovementCost(currentHex, currentUnit); pathMovementCost = pathMovementCost + unitMovementCost; if (pathMovementCost <= totalMovementPoints) { currentHex.PathMovementCost = pathMovementCost; movableHexes.Add(currentHex); } pathMovementCost = 0; } for (int i = 0; i < currentUnit.BaseMovement; i++) { DetermineMovableHexes(movableHexes, tempHexes, currentUnit, totalMovementPoints, ref unitMovementCost, ref pathMovementCost, ref adjacentHexes); } return movableHexes; }


I then determined if I could get to the hex from the current location (note the argument overload from VS2010 Extract Method):

private static void DetermineMovableHexes(List<Hex> movableHexes, List<Hex> tempHexes, Unit currentUnit, int totalMovementPoints, ref int unitMovementCost, ref int pathMovementCost, ref List<Hex> adjacentHexes) { foreach (Hex currentHex in movableHexes) { adjacentHexes = GetAdjacentHexes(currentHex); foreach (Hex tempHex in adjacentHexes) { unitMovementCost = HexFactory.CalculateMovementCost(tempHex, currentUnit); if (tempHex.CurrentTerrain.RiverInd == true && tempHex.CurrentTerrain.RoadInd == false) { unitMovementCost = 99; } pathMovementCost = currentHex.PathMovementCost + unitMovementCost; if (pathMovementCost <= totalMovementPoints) { if (currentHex.PathMovementCost < pathMovementCost) tempHex.PathMovementCost = pathMovementCost; tempHexes.Add(tempHex); } pathMovementCost = 0; } } foreach (Hex hex in tempHexes) { var q = (from Hex h in movableHexes where h.HexId == hex.HexId select h).FirstOrDefault(); if (q == null) { movableHexes.Add(hex); } } }

Basically, each hex has 2 movement points – the cost for the hex by itself and then the cumulative cost for the hex as part of a path. If the path is too much, the hex is not selected. By looping though each hex then its adjacent hexes, all possible paths are covered. The results look good:


Up next – having the unit attack another unit. Fun!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: