iOS 7 adds a plethora of new APIs for deveopers to dig into, but most interesting ones, in my opinion, are UIKit Dynamics. UIKit dynamics adds the ability for developers to leverage a 2d physics engine in just a few lines of code. The following code example shows how easy it is to implement UIKit Dynamics using Xamarin.iOS on iOS 7. For this example, I created a very cheesy game that feels like a weird amalgamation of Plinko and those old Water Ring-Toss Games. The goal of the game is for the user to drop a coin into the playfield and try to hit the moving bar at the bottom of the screen. In the way of the bar are gems bouncing back that block the ring on its path to the goal.  It is not pretty and definitely rough, but it serves as a great example of how easy this API is to implement.

Code Walkthrough

To get started, we need to setup a few objects for our animation and behaviors.

animator = new UIDynamicAnimator(this.View);

The animator object will be in charge of running all of our behaviors. In this case, we pass it the view controller’s View object to manage the coordinate system and define the boundary. This will be helpful when we add collision detection and gravity to our objects, as it will keep our objects from flying off of the screen. Once we have our animator setup, we can start to add some behaviors to our objects. Now, let’s get things moving and give our coin catcher and our gems some motion. For each UIPushBehavior, I use the UIPushBehaviorMode.Continuous mode to keep the objects constantly moving. In the next step, we will add some simple logic to reverse the movement of the objects once they collide into the wall.

coinCatcherPush = new UIPushBehavior (new []{ivCoinCatcher}, UIPushBehaviorMode.Continuous);
coinCatcherPush.PushDirection = new MonoTouch.CoreGraphics.CGVector (0.25f, 0.0f);

redGemPush = new UIPushBehavior (new []{ivRedGem}, UIPushBehaviorMode.Continuous);
redGemPush.PushDirection = new MonoTouch.CoreGraphics.CGVector (-0.15f, 0.0f);

yellowGemPush = new UIPushBehavior (new []{ivYellowGem}, UIPushBehaviorMode.Continuous);
yellowGemPush.PushDirection = new MonoTouch.CoreGraphics.CGVector (0.35f, 0.0f);

greenGemPush = new UIPushBehavior (new []{ivGreenGem}, UIPushBehaviorMode.Continuous);
greenGemPush.PushDirection = new MonoTouch.CoreGraphics.CGVector (-0.2f, 0.0f);

Next, we setup the general bounds collision detection. Whenever an object comes into contact with the outer bounds of our screen, we want to reverse direction. Since we only initially specify a push direction on the x-axis, our gems and coin catcher will just bounce back and forth. Once we drop the coin though, all hell will break loose as the coin will collide with the blocking objects. If we detect that our coin has run into the screen bounds, we reset its position back to the starting point. For all of this collision detection we are subscribing to the BeganBoundaryContact event which is only fired when an objects collide with the boundary and not collisions between the objects.

foreach (var item in View.Subviews) {
    if (item is UIImageView) {
        containerCollision.AddItem (item);
    }
}

containerCollision.BeganBoundaryContact += 
    (sender, e) => {

        if(e.DynamicItem == ivCoinCatcher)
            coinCatcherPush.PushDirection
                = new MonoTouch.CoreGraphics.CGVector(-coinCatcherPush.PushDirection.dx, -coinCatcherPush.PushDirection.dy);

        if(e.DynamicItem == ivRedGem)
            redGemPush.PushDirection
                = new MonoTouch.CoreGraphics.CGVector(-redGemPush.PushDirection.dx, -redGemPush.PushDirection.dy);

        if(e.DynamicItem == ivYellowGem)
            yellowGemPush.PushDirection
                = new MonoTouch.CoreGraphics.CGVector(-yellowGemPush.PushDirection.dx, -yellowGemPush.PushDirection.dy);

        if(e.DynamicItem == ivGreenGem)
            greenGemPush.PushDirection
                = new MonoTouch.CoreGraphics.CGVector(-greenGemPush.PushDirection.dx, -greenGemPush.PushDirection.dy);

        if(e.DynamicItem == ivGoldCoin){
            ResetCoin();
        }
    };

Now that we have all of our objects setup to collide with our bounds, we want to add a special collision behavior for our coin and the coin catcher. We want to be able to be notified when these two objects come into contact. In this case, we subscribe to the BeganContact event. Since this CollisionBehavior only contains our coin and the coin catcher, we do not have to do any additional checks to see if we have the right object or not. When we detect a collision, we will call ResetCoin which removes gravity from our coin and moves it back to the starting position. Then we display a success message.

coinCollision = new UICollisionBehavior (ivCoinCatcher, ivGoldCoin);

coinCollision.BeganContact += 
    (sender, e) => {

    if(!IsSuccess){
        IsSuccess = true;

        ResetCoin();

        var message = new UIAlertView("A Winner Is You", String.Empty, null, null, new [] { "Great!" });
        message.Show();
    }
};

The last thing we need to do is add our behaviors to the animator and we are all set to go.

animator.AddBehaviors (new UIDynamicBehavior[]{ coinCollision, coinCatcherPush, containerCollision, coinGravity, redGemPush, yellowGemPush, greenGemPush });

In order to get the game kicked off, we subscribe to the TouchUpInside event of the btnDropCoin button. The button adds gravity to our coin which sends it out on its way.

async void DropCoinTouchUpInside (object sender, EventArgs e)
{
    IsSuccess = false;

    btnDropCoin.Enabled = false;
    coinGravity.AddItem (ivGoldCoin);
    await Task.Delay(500);
    btnDropCoin.Enabled = true;
}

The last bit of code that we have is to Reset the coin back to its starting position. Whenever an animated object is updated outside of the UIDynamicAnimator object, we need to notify it using the UpdateItemUsingCurrentState method, which we call after we update the position.

private void ResetCoin(){

    coinGravity.RemoveItem(ivGoldCoin);

    ivGoldCoin.Frame = originalCoinLocation;

    animator.UpdateItemUsingCurrentState (ivGoldCoin);

}

It is worth noting that even though we have removed gravity from our object, it does not mean that it will not still have some momentum behind it. So, there you have it in just over 100 lines of code, we have a fun little game. I am trying to think of ways on how this could be used for non-game purposes or a business application. I think it would be fun to have a UI where when validation failed or passed, the filled in form fields would just detach and fall to the bottom of the form. If you have any thoughts, send them to @TheEightBot on twitter. A full example of the solution can be found at the link below. Coin Drop Source Code