October 1, 2013

Make Games with Xamarin.iOS and Sprite Kit

By

Sprite Kit is the first game framework directly from Apple, and is fully supported by our recent Xamarin.iOS release for iOS 7. Sprite Kit is a framework for creating 2D games on iOS 7 and on OS X Mavericks, and includes support for many of the things you would expect in a 2D game platform including:

monkey

  • Animations

  • Collision detection

  • Particle systems

  • Rigid-body physics

  • Audio support

  • Video support

What’s more, Sprite Kit is is tightly integrated with iOS, easily allowing such things as blending UIKit within a Sprite Kit game, or even supporting Core Image filters.

With Sprite Kit, games are organized into scenes (SKScene), which represent each screen within a game. The view class to use with Sprite Kit is SKView. To display a scene you simply call the view’s PresentScene method, passing it an SKScene instance.

The following code shows how to use an SKView within a controller to present a scene:

public override void LoadView ()
{
    base.LoadView ();
    View = new SKView {
        ShowsFPS = true,
        ShowsNodeCount = true,
        ShowsDrawCount = true
    };
}
public override void ViewWillLayoutSubviews ()
{
    base.ViewWillLayoutSubviews ();
    var view = (SKView)View;
    if (view.Scene == null) {
        var scene = new MonkeyScene (View.Bounds.Size);
        scene.ScaleMode = SKSceneScaleMode.AspectFill;
        view.PresentScene (scene);
    }
}

As you can see, the SKView class includes several properties that can be set for diagnostics:

  • ShowsFPS – Shows the frame rate.
  • ShowsNodeCount – Shows the number of rendering passes.
  • ShowsDrawCount – Shows the number of visible nodes.

When these are set to true, the metrics are displayed in the lower right of the screen, as shown below:

Since games don’t often want the status bar displayed, it’s a good idea to hide it, which in iOS 7 you can take care of within the controller by overriding PrefersStatusBarHidden:

public override bool PrefersStatusBarHidden ()
{
    return true;
}

The MonkeyScene class inherits from SKScene:

public class MonkeyScene : SKScene
{
}

The scene is where you build up a hierarchy of nodes. The base class for all the visual elements in Sprite Kit is SKNode. The SKScene is an SKNode. Additionally all the sprites you add to a game are SKNodes as well. Sprites are nodes that represent the images that appear in the game. In Sprite Kit the SKSpriteNode class represents a sprite.

For example, the following code creates a sprite from an image called frame-1.png (the extension isn’t required), positions it in the center of the scene and adds it to the scene:

SKSpriteNode monkey;
public MonkeyScene (SizeF size) : base(size)
{
    monkey = SKSpriteNode.FromImageNamed ("frame-1");
    monkey.Position = new PointF (Size.Width / 2, Size.Height / 2);
    AddChild (monkey);
}

Running this displays the image:

Adding a sprite is the most fundamental thing you can do in Sprite Kit. But of course, to make a game, you’ll need the sprite to do more than just sit there. This is where actions can be used. Actions (SKAction) are a way to essentially script what you want to have happen in a game. There are a plethora of actions available, allowing everything from moving sprites, to rotating, scaling and animating them. There are even actions to chain other actions together in a sequence, as well as to group them.

Let’s make our monkey move around the screen to wherever the user touches. The simplest way to do this is by overriding one of the touch handling methods in SKScene (although you could use gesture recognizers as well). To run an action on a sprite we simply call the sprite’s RunAction method, passing it the action. In this case we use the MoveTo action to move the sprite to the touch location:

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    var touch = (UITouch)touches.AnyObject;
    monkey.RunAction (SKAction.MoveTo (touch.LocationInNode (this), 1));
}

Now the monkey moves to wherever the user touches the screen. However, it doesn’t look quite right to have the monkey sliding around. Let’s add an animation to make it look like the monkey is walking as he moves.

To accomplish, we can add a bunch of images to create a sprite based animation where each image represents an animation frame. We use another action, AnimateWithTextures, to cycle through the textures to create the animation, along with RepeatActionForever to loop the animation:

SKAction animate;
public MonkeyScene (SizeF size) : base(size)
{
    ...
    var textures = Enumerable.Range (1, 8).Select (
        (i) => SKTexture.FromImageNamed (String.Format ("frame-{0}", i))).ToArray ();
    animate = SKAction.RepeatActionForever (SKAction.AnimateWithTextures (textures, 0.1));
}

In the touch handling code, simply run the animation. Also remove all the actions when the movement stops so as to stop the monkey from running in place:

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    var touch = (UITouch)touches.AnyObject;
    AnimateMonkey (touch.LocationInNode (this));
}
void AnimateMonkey (PointF location)
{
    monkey.RunAction (animate);
    monkey.RunAction (SKAction.MoveTo (location, 1), () => {
        monkey.RemoveAllActions ();
    });
}

If we run the game now, the monkey animates as he moves around, as this video of the monkey running around on an iPhone 5 shows:

You can download the code from this blog post here.

TwitterFacebookGoogle+LinkedInEmail