//---------------------------------------------------------// /// <summary> /// Animates two ScatterViewItems together and then merges the content of both items into one ScatterViewItem. /// </summary> /// <param name="pieceRemaining">The piece that will remain after the join.</param> /// <param name="pieceBeingRemoved">The piece that will be removed as a result of the join.</param> private void JoinItems(ScatterViewItem pieceRemaining, ScatterViewItem pieceBeingRemoved) { // Simultaneous joins on the same pieces (as in the case where two matching pieces are dropped next // to each other at the same time) eventually remove both matching pieces. Make sure only one join // happens at one time. if (!joinInProgress) { joinInProgress = true; Storyboard join = ((Storyboard)Resources["JoinPiece"]).Clone(); foreach (AnimationTimeline animation in join.Children) { // If this is a double animation, then it animates the piece's orientation DoubleAnimation orientation = animation as DoubleAnimation; if (orientation != null) { orientation.To = pieceRemaining.ActualOrientation; orientation.From = pieceBeingRemoved.ActualOrientation; // If two pieces are close in orientation, but seperated by the 0/360 line (i.e. 3 and 357) then don't spin the piece all the way around if (Math.Abs(pieceRemaining.ActualOrientation - pieceBeingRemoved.ActualOrientation) > 180) { orientation.To += orientation.From > orientation.To ? 360 : -360; } } // If this is a point animation, then it animates the piece's center PointAnimation center = animation as PointAnimation; if (center != null) { center.To = puzzleManager.CalculateJoinAnimationDestination(pieceRemaining, pieceBeingRemoved); } // Can't animate values that are set to NaN if (double.IsNaN(pieceBeingRemoved.Orientation)) { pieceBeingRemoved.Orientation = pieceBeingRemoved.ActualOrientation; } // Set up a callback that passes the ScatterViewItems that will be needed when the animation completes join.Completed += delegate(object sender, EventArgs e) { OnJoinAnimationCompleted(pieceBeingRemoved, pieceRemaining); }; pieceBeingRemoved.BeginStoryboard(join); } } }
//---------------------------------------------------------// /// <summary> /// Adds a ScatterViewItem to the ScatterView, and animates it /// on from the specified side of the screen (Left or Right). /// </summary> /// <param name="item">The item to add.</param> /// <param name="fromDirection">The direction from which puzzle pieces enter.</param> private void AddPiece(ScatterViewItem item, Direction fromDirection) { // Add the piece to the ScatterView at the correct location Debug.Assert(fromDirection == Direction.Right || fromDirection == Direction.Left); double screenHeight = scatter.ActualHeight; double screenWidth = scatter.ActualWidth; item.Center = fromDirection == Direction.Right ? new Point(screenWidth, screenHeight / 2) : new Point(-100, screenHeight / 2); item.Orientation = allowRotation ? random.Next(0, 360) : 0; scatter.Items.Add(item); // Load the animation Storyboard add = ((Storyboard)Resources["AddPiece"]).Clone(); foreach (AnimationTimeline animation in add.Children) { // If this is a double animation, it animates the item's orientation DoubleAnimation orientation = animation as DoubleAnimation; if (orientation != null && allowRotation) { // Spin the orientation a little. orientation.To = item.Orientation + random.Next(-135, 135); } // If this is a point animation, then it animates the item's center PointAnimation center = animation as PointAnimation; if (center != null) { var padding = 100; // Get a random point to animate the item to center.To = new Point( random.Next(padding, (int)(screenWidth) - padding), random.Next(padding, (int)(screenHeight) - padding)); } } // Set up a callback that passes the ScatterViewItem that will be needed when the animation completes add.Completed += delegate(object sender, EventArgs e) { OnAddAnimationCompleted(item); }; // Start the animation item.BeginStoryboard(add, HandoffBehavior.SnapshotAndReplace); }
//---------------------------------------------------------// /// <summary> /// Adds a ScatterViewItem to the ScatterView, and animates it /// on from the specified side of the screen (Left or Right). /// </summary> /// <param name="item">The item to add.</param> /// <param name="fromDirection">The direction from which puzzle pieces enter.</param> private void AddPiece(ScatterViewItem item, Direction fromDirection) { // Add the piece to the ScatterView at the correct location Debug.Assert(fromDirection == Direction.Right || fromDirection == Direction.Left); double screenHeight = RootLayout.ActualHeight; double screenWidth = RootLayout.ActualWidth; item.Center = fromDirection == Direction.Right ? new Point(screenWidth, screenHeight / 2) : new Point(-100, screenHeight / 2); item.Orientation = random.Next(0, 360); scatter.Items.Add(item); // Load the animation Storyboard add = ((Storyboard)Resources["AddPiece"]).Clone(); foreach (AnimationTimeline animation in add.Children) { // If this is a double animation, it animates the item's orientation DoubleAnimation orientation = animation as DoubleAnimation; if (orientation != null) { // Spin the orientation a little. orientation.To = item.Orientation + random.Next(-135, 135); } // If this is a point animation, then it animates the item's center PointAnimation center = animation as PointAnimation; if (center != null) { // Get a random point to animate the item to center.To = new Point(random.Next(0, (int)(screenHeight + 5)), random.Next(0, (int)screenHeight)); } } // Set up a callback that passes the ScatterViewItem that will be needed when the animation completes add.Completed += delegate(object sender, EventArgs e) { OnAddAnimationCompleted(item); }; // Start the animation item.BeginStoryboard(add, HandoffBehavior.SnapshotAndReplace); }