A Game of Swift: Making an iOS Game with Swift and SpriteKit

107
I’ll be discussing the exciting new language Swift. I’ll also talk about SpriteKit and my experiences releasing a game to the App Store using Swift and SpriteKit. Please feel free to ask me something at any times, if you can read a slide or want me to clarify or give examples or whatever, don’t feel the need to wait until the end. Also give some sort of indication if you can’t understand me because I’m talking too fast or mumbling, I promise I won’t be oended.

Transcript of A Game of Swift: Making an iOS Game with Swift and SpriteKit

Page 1: A Game of Swift: Making an iOS Game with Swift and SpriteKit

I’ll be discussing the exciting new language Swift.I’ll also talk about SpriteKit and my experiences releasing a game to the App Store using Swift and SpriteKit.Please feel free to ask me something at any times, if you can read a slide or want me to clarify or give examples or whatever, don’t feel the need to wait until the end.Also give some sort of indication if you can’t understand me because I’m talking too fast or mumbling, I promise I won’t be offended.

Page 2: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Swift is a new programming language created by Apple. It's the heir to Objective-C, so it's very difficult to talk about Swift without first talking in detail about Objective-C.How many people here have written code in Objective-C?Not trying to do weird presenter tricks…

Page 3: A Game of Swift: Making an iOS Game with Swift and SpriteKit

A lot of you may already know the Apple drama over the past few decades but I'll quickly cover it for those who don’t.Objective-C was created in the early 1980s and descended from the language Smalltalk.

Page 4: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Smalltalk is an object-oriented language that called methods using "messages", which we'll talk about a little later.

Page 5: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Steve Jobs during his exile from Apple formed a company called NeXT.This company licensed Objective-C in 1988, and they used the language to build an operating system called NextStep.

Page 6: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Flashforward to 1996, Apple's in bit if a rut and they're looking to update their operating system.

Page 7: A Game of Swift: Making an iOS Game with Swift and SpriteKit

+

Apple acquires NeXT and uses NeXTStep as the basis of Mac OS X.

Page 8: A Game of Swift: Making an iOS Game with Swift and SpriteKit
Page 9: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Things were fine for a few years.Developers were able to make mac applications….

Page 10: A Game of Swift: Making an iOS Game with Swift and SpriteKit

…but in 2007 the iPhone was released which as you know changed everything.In 2008 developers were able to start creating 3rd party apps for the iphone…

Page 11: A Game of Swift: Making an iOS Game with Swift and SpriteKit

… and this is when Objective-C really blew up because the iPhone OS and related apps all used Objective-C.

Page 12: A Game of Swift: Making an iOS Game with Swift and SpriteKit

What’s wrong with Objective-C??

So what's the problem? Why can't we just use Objective-C until the end of time?In short, Objective-C was never intended to be as popular as it became.It was used for the OS and mac apps…

Page 13: A Game of Swift: Making an iOS Game with Swift and SpriteKit

… there wasn't a mobile app industry at the time and no one could anticipate what a game changer the iPhone would be.

Page 14: A Game of Swift: Making an iOS Game with Swift and SpriteKit

[[wh@t is going on here]]] @[][]@@@;

Objective-C has a somewhat tough barrier to entry because it doesn’t look like a lot of the languages that descended from c, like c++, java or c#.As far as aesthetics go, Objective-C is fairly hideous.

Page 15: A Game of Swift: Making an iOS Game with Swift and SpriteKit

NSString *myString = [[NSString alloc] initWithFormat:@"I have %@ donuts", donutsNum];

Here's a sample of objective-c code, and here is how you'd accomplish the same thing in Java

Page 16: A Game of Swift: Making an iOS Game with Swift and SpriteKit

NSString *myString = [[NSString alloc] initWithFormat:@"I have %@ donuts", donutsNum];

String myString = "I have " + donutsNum + "donuts"

This can be intimidating to programmers who aren't used to this syntax

Page 17: A Game of Swift: Making an iOS Game with Swift and SpriteKit

NSString *myString = [[NSString alloc] initWithFormat:@"I have %@ donuts", donutsNum];

String myString = "I have " + donutsNum + "donuts"

Page 18: A Game of Swift: Making an iOS Game with Swift and SpriteKit

NSString *myString = [[NSString alloc] initWithFormat:@"I have %@ donuts", donutsNum];

String myString = "I have " + donutsNum + "donuts"

Let’s take a look at some of the issues here…We have a bunch of square brackets all over there place, here's two right next to each otherWe've got an asterisk here, ok we've seen that in some other languagesWhat about all these at symbolsAnd there's a lot of extra words cluttering up, alloc, initWithFormatWhat's with this NS why is that cluttering up the String?

Page 19: A Game of Swift: Making an iOS Game with Swift and SpriteKit

NSWTF???

You'll see this in a lot of classes in Objective-C: NSArray, NSString, NSDictionary. It's a nightmare for autocomplete.Because Objective-C doesn't have a concept of namespaces, class names have to be unique so you need to add a prefix like NS.

Page 20: A Game of Swift: Making an iOS Game with Swift and SpriteKit

The prefix NS is a relic from when Objective-C and its Foundation framework was built using NextStep.Again, this was created way before anyone could anticipate how popular it would be to code in the language.

Page 21: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Over the years Objective-C has gotten friendlier with more features you'd expect out of a programming language like blocks and literals.But Apple was looking for a lighter language with less barrier to entry and clean up some of the relics of the past, and Swift is their answer.

Page 22: A Game of Swift: Making an iOS Game with Swift and SpriteKit
Page 23: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Concise

• Semicolons ;

• Square brackets [ ]

• Import statements for classes

• Alloc/init, lengthy method names

No more:

Page 24: A Game of Swift: Making an iOS Game with Swift and SpriteKit

NSString *myString = [[NSString alloc] initWithFormat:@"I have %@ donuts", donutsNum];

var myString = "I have " + donutsNum + "donuts"

Back to that previous example with the strings, below is same line in Swift and you can see it has done away with all the weirdness we pointed out in the other slide and looks a lot more like a modern language.You can also overload the arithmetic operators with your own custom functionality.In Objective-C there is no overloading, you had to create a new method name if you wanted to have different types of parameters for the same method, so autocomplete would get pretty cluttered with all these extra methods.

Page 25: A Game of Swift: Making an iOS Game with Swift and SpriteKit

self.myProperty = 54; [self performSomeMethod:self.myProperty];

In Objective-C you need to access properties with the self keyword and also call methods on self.

Page 26: A Game of Swift: Making an iOS Game with Swift and SpriteKit

self.myProperty = 54; [self performSomeMethod:self.myProperty];

myProperty = 54 performSomeMethod(myProperty)

In Swift, the self is implied in properties.You can write it out if you want but you can omit it.If you call a function it is also implied to call on self, so you don’t need to declare that either.Much more concise.

Page 27: A Game of Swift: Making an iOS Game with Swift and SpriteKit

if (myDelegate != nil) { if ([myDelegate respondsToSelector:

@selector(scrollViewDidScroll:)]) { [myDelegate scrollViewDidScroll:myscrollView]; } }

This is an example they used in the Apple Keynote when they first introduced Swift.Here you see some code you’d commonly see in an Objective-C app where you spend a lot of time checking if the delegate is nil, checking if the delegate has a particular method before you call it.

Page 28: A Game of Swift: Making an iOS Game with Swift and SpriteKit

if (myDelegate != nil) { if ([myDelegate respondsToSelector:

@selector(scrollViewDidScroll:)]) { [myDelegate scrollViewDidScroll:myscrollView]; } }

myDelegate?.scrollViewDidScroll?(myScrollView)

In Swift they’ve cut down on a lot of typing with Optionals, which is indicated by the question marks here.Optionals will come up later when we talk about safety.

Page 29: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Stricter collections = more concise

Another change that results in more concise code is strict types in collections.

Page 30: A Game of Swift: Making an iOS Game with Swift and SpriteKit

- (void)eatDonutFromArray:(NSArray *)donuts { NSDonut *donut = [donut firstObject]; [donut eatDonutMethod]; }

Here is a sample method from objc.You pass in an array of donuts but the compiler doesn't know that the array only contains NSDonuts.We know it because of clues from the method name and maybe the documentation but for all the compiler knows, there could be strings in that donut array.**** So we create a donut variable and cast it as nsdonut to assure the compiler that it's ok to call eatDonutMethod on it.Here's how this same method could be implemented in Swift.

Page 31: A Game of Swift: Making an iOS Game with Swift and SpriteKit

- (void)eatDonutFromArray:(NSArray *)donuts { NSDonut *donut = [donut firstObject]; [donut eatDonutMethod]; }

func eatDonutFromArray(donuts: [Donut]!) { donuts.firstObject.eatDonutMethod }

The syntax is a little flipped, but we have the same name of the array, donuts, but instead of a general array type, this has an array of donuts,*** That's what this syntax with the brackets around Donut means, this array can only contain donuts.This allows us to call donut methods on any object in the array without needing to cast it because it has to be a donut, the code won't compile if you try to send an array of strings to this method.

Page 32: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Safety!!

It's a great win for more concise code, but this also demonstrates another feature of Swift - its emphasis on Safety!

Page 33: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Statically Typed

var donutArray:[Donut] = [jellyDonut, powderedDonut]

All variables are statically typed in Swift.Meaning, you have to declare if a variable is an Int or a String, you can’t just say it’s a variable and call any method you want on it later.While Objective-C was also statically typed, it also used the id property in collections as we discussed a few slides ago.This would often lead to errors happening at runtime when the collection ended up having a type that you weren’t expecting.In Swift, collections are of a particular type so if you do pass the wrong type into a collection, there will be an error before you compile rather than at runtime.

Page 34: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Statically Typed

var donutArray:[Donut] = [jellyDonut, powderedDonut]

var donutArray = [jellyDonut, powderedDonut]

Type can also be inferred as you see in this example, you don’t need to explicitly declare the variable type.Here it is inferred that donutArray is an array of donuts based on the assignment.Under the hood this is still statically typed, donutArray is an array of Donuts even though you didn’t have to explicitly type it out like the line above.You get the safety of static typing but it’s also concise.

Page 35: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Variables and Constants

var donutArray = [jellyDonut, powderedDonut]

let donutArray = [jellyDonut, powderedDonut]

In swift variables are only able to be changed if you declare them a var.The preferred practice is to declare your variables as constants using the ‘let’ keyword.Not only does it optimize the code and make it faster, it adds safety by throwing you a warning if you try to change the contents.

Page 36: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Variables and Constants

var donutArray = [jellyDonut, powderedDonut]

let donutArray = [jellyDonut, powderedDonut]

donutArray = [glazedDonut, onionDonut] // Ok!!

donutArray = [glazedDonut, onionDonut] // Error!!

In the variable version of donutArray you can change contents no problem.*** But if you had instead declared donutArray as a constant, you would get an error on the new assignment and the code wouldn’t compile.Swift really tries to get you to think about how you’re going to use each variable, which we also see with Optionals.

Page 37: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Dealing with Nil

Nil or null pointers cause a lot of problems in programming and different languages have different ways of dealing with it.In a lot of languages it will crash your program if you try to call a method on a null object.

Page 38: A Game of Swift: Making an iOS Game with Swift and SpriteKit
Page 39: A Game of Swift: Making an iOS Game with Swift and SpriteKit

[donut returnSugarContent];

Because Objective-C was inspired by the SmallTalk language, it uses message passing to invoke methods.This statement is sending the message returnSugarContent to donut and depending on the circumstances you can get away with calling a method on a variable that doesn’t have the method and the compiler won’t complain.In Objective-C messaging nil returns nil, so no harm no foul, no crash.

Page 40: A Game of Swift: Making an iOS Game with Swift and SpriteKit

[donut returnSugarContent];sugarGrams =

And yet, this isn’t ideal. What if you need the return value from this method and getting back nil will crash your program?You could wrap this in a nil check, or respondsToSelector, and that is what we have to do all the time in Objective-C.Swift is looking for a better way to handle the nil problem.

Page 41: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Optionals

var donutArray:[Donut] = [jellyDonut, powderedDonut]

donutArray = nil // Error!!

Enter Optionals.I should mention that when you declare a variable or constant you must initialize a value right away or in the initializer method.It’s another safety feature of Swift.Here’s an example from earlier. Let’s say later on you want to clear out the donuts and set the variable to nil.*** You cannot do this because then donutArray would no longer be an array of donuts, nil is not an array.

Page 42: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Optionals

var donutArray:[Donut] = nil // Error!!

Now let’s say instead you wanted to create donutArray now but fill in its contents later.*** You cannot do this with a regular variable. A var always expects a value.

Page 43: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Optionals

var donutArray:[Donut]? = nil

How you can accomplish this is by making donutArray an Optional.An Optional is its own type.This would be an optional array of donuts, the question mark shows its an optional.An Optional is like how every variable in Objective-C is, they can be nil at any time.This variable can equal nil at any time, it doesn’t need to be initialized to a value.Optionals should be used only when necessary because they work around the safety Swift has created to try to eliminate runtime errors that crop up around surprise nil variables.

Page 44: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Optionals

var donutArray:[Donut]? = nil

defaults.setObject(donutArray!, forKey: "donutArray")

if let unwrappedArray = donutArray { defaults.setObject(unwrappedArray, forKey: "donutArray") }

When you use an optional, you sometimes have to force unwrap them using the exclamation point.*** Optionals are generally meant to be used with a question mark, meaning that there may be an object there or it may be nil.Sometimes though you need to guarantee that there’s a value there and this is the sort of brute force way of saying “just trust me, there’s a value there”.This should be avoided unless absolutely necessary because it goes around the safety of optionals and the program will crash if it turns out you were wrong and there’s no object there.*** The preferred way to handle this is using a new statement, “if let”, also known as Optional Binding.This creates a new local constant equal to your optional only if there’s a value there.It’s similar to a nil check, so that seems to go against Swift’s push for Concise Code.I think that as Swift develops the syntax for this situation it will become more concise but for now this is the way to safely handle optionals when you need to guarantee they’re non-nil.

Page 45: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Other Safety Features

Swift also has a few other safety features, most of these are taking away some of the options that let us be lazy when coding.

Page 46: A Game of Swift: Making an iOS Game with Swift and SpriteKit

if (boolIsTrue) { // do something } if (boolIsTrue) // do something

In Objective-C both these statements work exactly the same.If you only have one line inside the body of an if statement, you had the option of omitting the curly braces.The problem is, it’s really easy to think that you’re just going to need one line, then you come back to your code sometime later and add more lines not realizing that you needed to go back and add braces.

Page 47: A Game of Swift: Making an iOS Game with Swift and SpriteKit

if (boolIsTrue) { // do something } if (boolIsTrue) // do something

// do this too // and that

But when you don’t add the braces,*** only the first statement is inside the if statement.*** The other lines here will always run, probably causing you problems.The insidious part is that there are no errors here, this will compile and you may not realize you have a bug until much later.Maybe years later.

Page 48: A Game of Swift: Making an iOS Game with Swift and SpriteKit

if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail;

A famous instance of this was the goto fail SSL bug.*** Apple was using the shortcut and ended up creating a really bad security bug.So Swift decided this convenience wasn’t worth the risk and got rid of the option, you have to use curly braces now.

Page 49: A Game of Swift: Making an iOS Game with Swift and SpriteKit

let direction = "up"

switch (direction) { case "down": println("Going down!") case "left", "right": println("Going sideways!") case "up": println("Going up!") default: println("Going nowhere.") }

Another feature removed for safety reasons was the “break” statement within switch statements.In many C-based languages each case you have to tell it to break so it doesn’t fall through to the next statement, but Swift removed this because it is an easy thing to forget to add break and caused runtime errors.The default statement is also required in Swift if your cases aren’t exhaustive, and it’s smart enough to know if you’ve covered all your bases.Also you may notice that switch statements finally aren’t limited to numbers and enums!This one uses strings, you can also check multiple cases in one line as you see with the “left”, “right” case.

Page 50: A Game of Swift: Making an iOS Game with Swift and SpriteKit

There are lots of other examples, too much to go through them all here.The main takeaway is that Swift was designed to be easier to learn, faster to run, and safer to code than Objective-C.

Page 51: A Game of Swift: Making an iOS Game with Swift and SpriteKit

So onto SpriteKit.SpriteKit is a game development framework Apple released with iOS 7.

Page 52: A Game of Swift: Making an iOS Game with Swift and SpriteKit

It is very heavily influenced by Cocos2D which was the leading open source 2d game framework.SpriteKit and Cocos2d each have their own advantages.

Page 53: A Game of Swift: Making an iOS Game with Swift and SpriteKit

vs.

SpriteKit has the advantage of being created by Apple, so it’s optimized to run with iOS and the syntax has more of an Apple feel.It’s basically guaranteed to be compatible with future platform updates, while sometimes things break in Cocos2D when a new OS version comes out.SpriteKit also includes a native physics library which Cocos does not.Though Cocos2d does include Chipmunk and Box2d you need to use C or C++ which can be complicated.Cocos has the advantage of being open source, so you can peak under the hood and change any implementation you want as suits your needs.

Page 54: A Game of Swift: Making an iOS Game with Swift and SpriteKit

One disadvantage for SpriteKit is that it isn’t cross platform.While Cocos2d is written in Objective-C, its cousin Cocos2d-x is written in C++ and is cross platform.

Page 55: A Game of Swift: Making an iOS Game with Swift and SpriteKit

All these 2d frameworks revolve around Sprites which are individual 2d images.

Page 56: A Game of Swift: Making an iOS Game with Swift and SpriteKit

In 3d animation, an entity would have a physics body that moves based on physics and space.You then put a skin on top of the body.A 3d scene is laid out just like if you created a model town using toys, and then a camera views the scene wherever you point it.

Page 57: A Game of Swift: Making an iOS Game with Swift and SpriteKit

In 2d games, you create the illusion of animation the same way you would a flipbook, by quickly changing one image for another so it looks like the same picture is moving.Here is an example sprite sheet.

Page 58: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Sticky Balls

I’ll be using a lot of examples from a game I made called Sticky Balls.This was written in Swift and used a combination of SpriteKit and the standard Apple UIKit.Since I have a full time job I knew I wouldn’t have a lot of time to work on a game.I wanted to create a simple game that I could get out to market quickly.

Page 59: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Coming up with an innovative gameplay concept would be really time consuming and it also could be very likely to fail.I think a lot of indie devs believe they need to create the next Minecraft right away but that’s a little like winning the lottery.Instead I chose to do research on which gameplay styles are popular right now and use those as a starting point.

Page 60: A Game of Swift: Making an iOS Game with Swift and SpriteKit

One game that stuck out to me was Amazing Brick.It was pretty fun and had a minimal style which is great because I didn’t want to pay an artist.It was successful so I knew there was a demand for this kind of game.

Page 61: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Now I’m not saying that you should just clone an existing game, or reskin it.Model and improve is the philosophy.Take inspiration from the game and make it better.But don’t just clone it, because then users have no reason to use your game over one that’s already established.

Page 62: A Game of Swift: Making an iOS Game with Swift and SpriteKit

To improve on the gameplay I made the game faster and tweaked the obstacles, which became Sticky Balls.Rather than the game ending when you hit a sticky ball, they just made it harder and harder to fit through the platforms.

Page 63: A Game of Swift: Making an iOS Game with Swift and SpriteKit

I mentioned that I used a combination of UIKit and SpriteKit.Here is a storyboard which is the standard way to organize your user interface elements in Xcode.I created a main menu, a game over screen, and a pause menu here because Interface Builder and the associated View Controllers are really good for simple things like buttons, and showing modal screens.

Page 64: A Game of Swift: Making an iOS Game with Swift and SpriteKit

All the SpriteKit code exists in a class called SKScene.This scene contains the logic for your game universe.*** Here I highlighted which elements I made in the Storyboard Interface Builder, everything else was created in the SpriteKit scene.One reason that I create these outside of SpriteKit is because of the different device sizes.

Page 65: A Game of Swift: Making an iOS Game with Swift and SpriteKit

iPhone 4SiPad

Having different sized devices is a problem.How I addressed it was to have all of the action happen in the middle of the screen, and just cut off the top and bottom of the views.*** Here is the area you will see on a 3.5” device, and here*** is the area you’ll see on an iPad.A player on an iPhone 5 or 6 has an advantage in that they can see a little father ahead, but that’s a compromise I had to make.The user interface elements I showed on the previous slide, the banner ad and the buttons at the top, they will adjust to the size of the device because they’re positioned using AutoLayout.So that’s a cool thing about SpriteKit, you can mix and match with the standard Apple UI depending on your needs.

Page 66: A Game of Swift: Making an iOS Game with Swift and SpriteKit

let sceneSize = CGSize(width: 640, height: 1136) let scene = GameScene(size:sceneSize) scene.scaleMode = .AspectFill self.view.presentScene(scene)

And since this presentation is also about Swift, here is some sample code to display the scene.I created a size that is the most stretched out aspect ratio for the iPhone 5 and 6,created a scene that scales to fill the space, and then the view controller presents the scene.It doesn’t take that much code to get a SpriteKit scene showing.

Page 67: A Game of Swift: Making an iOS Game with Swift and SpriteKit

let player = SKSpriteNode(imageNamed: "megaMan") addChild(player)

If you’re creating a simple sprite, it’s pretty easy.You just use a convenience initializer and pass in the name of the image for the sprite.You then call addChild on self, which means add child node, and pass the player in as a parameter.***

Page 68: A Game of Swift: Making an iOS Game with Swift and SpriteKit

class Player: SKSpriteNode { init(textureName: String) {

let texture = SKTexture(imageNamed: textureName) super.init(texture: texture, color: SKColor.redColor(), size: texture.size())

name = "Player" physicsBody = SKPhysicsBody(circleOfRadius: 50.0/2.0) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = PhysicsCategory.Player physicsBody?.collisionBitMask = PhysicsCategory.Platform | PhysicsCategory.Edge physicsBody?.contactTestBitMask = PhysicsCategory.Edge | PhysicsCategory.Platform | PhysicsCategory.StaticBall | PhysicsCategory.StickyBall | PhysicsCategory.Diamond | PhysicsCategory.BottomSensor }

This is the custom class I used for the player sprite.

Page 69: A Game of Swift: Making an iOS Game with Swift and SpriteKit

class Player: SKSpriteNode { init(textureName: String) {

let texture = SKTexture(imageNamed: textureName) super.init(texture: texture, color: SKColor.redColor(), size: texture.size())

name = "Player" physicsBody = SKPhysicsBody(circleOfRadius: 50.0/2.0) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = PhysicsCategory.Player physicsBody?.collisionBitMask = PhysicsCategory.Platform | PhysicsCategory.Edge physicsBody?.contactTestBitMask = PhysicsCategory.Edge | PhysicsCategory.Platform | PhysicsCategory.StaticBall | PhysicsCategory.StickyBall | PhysicsCategory.Diamond | PhysicsCategory.BottomSensor }

It’s a subclass of SKSpriteNode and it takes the name of the image to use as a parameter.I decided to use an image of a circle rather than create it programmatically for performance reasons.SpriteKit is really good at handling sprites and less good at handling vector drawings.

Page 70: A Game of Swift: Making an iOS Game with Swift and SpriteKit

class Player: SKSpriteNode { init(textureName: String) {

let texture = SKTexture(imageNamed: textureName) super.init(texture: texture, color: SKColor.redColor(), size: texture.size())

name = "Player" physicsBody = SKPhysicsBody(circleOfRadius: 50.0/2.0) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = PhysicsCategory.Player physicsBody?.collisionBitMask = PhysicsCategory.Platform | PhysicsCategory.Edge physicsBody?.contactTestBitMask = PhysicsCategory.Edge | PhysicsCategory.Platform | PhysicsCategory.StaticBall | PhysicsCategory.StickyBall | PhysicsCategory.Diamond | PhysicsCategory.BottomSensor }

This is where the sprite’s physics body is created.Notice that the property is accessed using physicsBody, no need to call self.physicsProperty.You can make different types of Physics Bodies, a rectangle is the easiest but you can use a circle or a more complex shape.Notice that the physicsBody is an optional.A sprite doesn’t need to have a physics body it can be nil and unaffected by physics.The category bit mask is like a tag that for this sprite’s physics body.This tag will be used by the next two properties.It’s just an enum I set up earlier so this is just setting the tag to 1 in this case.

Page 71: A Game of Swift: Making an iOS Game with Swift and SpriteKit

class Player: SKSpriteNode { init(textureName: String) {

let texture = SKTexture(imageNamed: textureName) super.init(texture: texture, color: SKColor.redColor(), size: texture.size())

name = "Player" physicsBody = SKPhysicsBody(circleOfRadius: 50.0/2.0) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = PhysicsCategory.Player physicsBody?.collisionBitMask = PhysicsCategory.Platform | PhysicsCategory.Edge physicsBody?.contactTestBitMask = PhysicsCategory.Edge | PhysicsCategory.Platform | PhysicsCategory.StaticBall | PhysicsCategory.StickyBall | PhysicsCategory.Diamond | PhysicsCategory.BottomSensor }

The collision bit mask property determines what other physics body this sprite will collide with, which other sprites it will bounce off of.If you don’t set this property, then by default it will collide with everything that has a physics body.The player here will bounce off platforms and the edge around the play area.It will not bounce off the other bodies, like the sticky balls and the diamonds, it passes through them as if they didn’t have physics bodies.

Page 72: A Game of Swift: Making an iOS Game with Swift and SpriteKit

class Player: SKSpriteNode { init(textureName: String) {

let texture = SKTexture(imageNamed: textureName) super.init(texture: texture, color: SKColor.redColor(), size: texture.size())

name = "Player" physicsBody = SKPhysicsBody(circleOfRadius: 50.0/2.0) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = PhysicsCategory.Player physicsBody?.collisionBitMask = PhysicsCategory.Platform | PhysicsCategory.Edge physicsBody?.contactTestBitMask = PhysicsCategory.Edge | PhysicsCategory.Platform | PhysicsCategory.StaticBall | PhysicsCategory.StickyBall | PhysicsCategory.Diamond | PhysicsCategory.BottomSensor }

The contact bit mask is different than the collision bit mask.This player’s physics body will not collide with a sticky ball, it won’t bounce off of it, but it will still register a contact.

Page 73: A Game of Swift: Making an iOS Game with Swift and SpriteKit

In this screenshot I made the physics bodies visible.You can see the physics bodies are slightly off from the sprites because the physics is simulated first in the update cycle, the sprites move a fraction of a second later but it catches up right away and you can’t tell if you can’t see the physics bodies.Here a contact happens - the player’s physics body has contacted a platform’s physics body.

Page 74: A Game of Swift: Making an iOS Game with Swift and SpriteKit

func didBeginContact(contact: SKPhysicsContact) { let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask if collision == PhysicsCategory.Platform | PhysicsCategory.Player || collision == PhysicsCategory.Platform | PhysicsCategory.StickyBall { loseGameByFalling(false) } else if collision == PhysicsCategory.StaticBall | PhysicsCategory.Player || collision == PhysicsCategory.StaticBall | PhysicsCategory.StickyBall { // Stick the ball to the Player }

Here’s a snippet of the contact function.When any physics body hits another physics body this function is called.*** Because the property is a bit mask you can combine them into one number which simplifies the code.You take one of the body’s category bit mask which I said was sort of like its tag, so the Player’s tag is 1, then let’s say it bumps into a platform which has a category bit mask of 2, this collision variable equals 3.

Page 75: A Game of Swift: Making an iOS Game with Swift and SpriteKit

func didBeginContact(contact: SKPhysicsContact) { let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask if collision == PhysicsCategory.Platform | PhysicsCategory.Player || collision == PhysicsCategory.Platform | PhysicsCategory.StickyBall { loseGameByFalling(false) } else if collision == PhysicsCategory.StaticBall | PhysicsCategory.Player || collision == PhysicsCategory.StaticBall | PhysicsCategory.StickyBall { // Stick the ball to the Player }

This first conditional would be met, because collision does equal Platform and Player, so the loseGameByFalling function would be called.

Page 76: A Game of Swift: Making an iOS Game with Swift and SpriteKit

func didBeginContact(contact: SKPhysicsContact) { let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask if collision == PhysicsCategory.Platform | PhysicsCategory.Player || collision == PhysicsCategory.Platform | PhysicsCategory.StickyBall { loseGameByFalling(false) } else if collision == PhysicsCategory.StaticBall | PhysicsCategory.Player || collision == PhysicsCategory.StaticBall | PhysicsCategory.StickyBall { // Stick the ball to the Player }

Had the collision been between the Player and one of the balls during gameplay, then I call the methods to attach the ball to the player using a joint which is beyond the scope of this presentation.Each combination of contacts is tested and then handled accordingly.

Page 77: A Game of Swift: Making an iOS Game with Swift and SpriteKit

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

let touch = touches.first as! UITouch let touchPoint = touch.locationInNode(self) let direction = touchPoint.x > player!.position.x ? 1 : -1 let impulse = CGVector(dx: 15*direction, dy: 120) player!.physicsBody!.applyImpulse(impulse) }

How the player moves is by taps.There’s a factory apple method which you override.You grab a touch from the collection of touches provided, then get the location of the touch.Notice that this is a generic set, rather than a set of touches.I suspect that Swift will evolve and this will be a strict set of Touches rather than NSObjects so that we don’t have to cast the touch, as we discussed earlier.Check if the spot that you touched was to the left or right of the player, then you move the player in the direction of the touch.You apply an impulse to the physics body which is a vector, it’s a point in this case up and slightly to the side.

Page 78: A Game of Swift: Making an iOS Game with Swift and SpriteKit

One of the first problems you run into is how to scroll the game.In a 3d environment you can have a camera that attaches to the player and the problem is solved.In 2d that won’t work.*** So instead of moving the player up like you might think, like you would in a 3d game,you have to move everything else down.*** Everything in SpriteKit is descended from SKNode, which is basically like an NSObject with additional properties useful for games.I created a Node called enemyBackground and added everything other than the player to this node.Then when you tap the screen it moves the entire background node down….

Page 79: A Game of Swift: Making an iOS Game with Swift and SpriteKit

This creates the illusion that the player is moving up.

Page 80: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Sticky Balls

That’s about how the game works.I’ll go over some of the libraries and tools I found helpful when making Sticky Balls.

Page 81: A Game of Swift: Making an iOS Game with Swift and SpriteKit

It used to be more difficult to access the user’s twitter and Facebook but iOS made it very easy to share content from within your app.This little modal that pops up is a UIActivityViewController and you actually don’t need any special framework to use it, it’s accomplished by this bit of code…

Page 82: A Game of Swift: Making an iOS Game with Swift and SpriteKit

let textToShare ="I got to level” + score + ” in the #StickyBalls game on iOS!!)

let objectsToShare = [textToShare, screenShot]

let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil) activityVC.excludedActivityTypes = [ UIActivityTypePostToWeibo, UIActivityTypeMessage, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr, UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo, UIActivityTypeAirDrop];

presentViewController(activityVC, animated: true, completion: nil)

You just create an array of the items you want to share, in this case it’s a string telling your score and a screenshot of when you died.You create a UIActivityViewController, pass in that array, and then this big block in the middle is just a list of the types of services you don’t want to include in your sharing options.It doesn’t make sense for me to share my screenshot to Vimeo for example, so I exclude it to keep the options from getting cluttered in the users popup.You then just present the view controller, and it’s all handled.If I were to tap the twitter button….

Page 83: A Game of Swift: Making an iOS Game with Swift and SpriteKit

It brings up my string, the screenshot, and the keyboard for the user to change the message if they want.It’s all really easy, you don’t have to check if they have a twitter account and worry about signing them in, the UIActivityController handles all that.

Page 84: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Most if not all of you are probably familiar with Google Analytics.Google makes it really easy to track screen views, button clicks, and any event that you send it.It tracks new users, daily active users, average session time, what countries your users are from, what devices and operating systems they’re using, just a lot of good information.

Page 85: A Game of Swift: Making an iOS Game with Swift and SpriteKit

The revenue model for Sticky Balls is free with ads.I use Applovin for both the banner ad at the bottom of the game and the full screen interstitial ad that pops up every 8 playthroughs or so.

Page 86: A Game of Swift: Making an iOS Game with Swift and SpriteKit

I was drilling down into the Applovin data and this is the breakdown of ads impressions for some period of time.GRAPHIC is the banner ad that’s always at the bottom of the screen and VIDEO is the interstitial that pops in every so often after you lose a game.You can see that even though the video only shows up 1/20th as often as the banner, those interstitial ads have a much higher click through rate and are responsible for almost half of the revenue.With this data and google analytics I can start to tweak how often I show a video ad and make a lot more money.

Page 87: A Game of Swift: Making an iOS Game with Swift and SpriteKit

This tweaking can be done server side using parse.I first released the app and hard coded everything like whether or not to show ads, how often to show them, and other settings.Later I added Parse to make all these settings configurable.Parse is just a simple and usually free back end that can be your cloud database, can handle your push notifications and gives you analytics as well.*** Thanks to Parse it’s an easy thing to change how often my interstitial ads or even whether ads are on at all.If my game got a ton of traffic because some site covered it, I might turn ads off for a bit in the hopes that they have a better experience and are more likely to share the game.It’s nice to be able to make these changes instantly without having to push a new build out and wait for Apple to review it.

Page 88: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Crashlytics is another good framework to include, I think it’s called fabric now I’m not sure if crashlytics is completely gone or what.Especially if you don’t have the resources to do a huge beta test of your app, you’re likely to find out that crashes are happening that you would never find out about without a tool like this.I use an iPhone 6+ usually when I test, it’s rare that I try out my app on an iPod running an old version so I might not see bugs that a more realistic user will see.The worst thing is to get a one-star review in the App Store telling you about the crash, better to find it and fix it first.

Page 89: A Game of Swift: Making an iOS Game with Swift and SpriteKit

So once you have your app created, you need to get it discovered.A lot of this depends on your marketing budget, which if you’re an indie developer is likely $0.The main way your app will be discovered is probably through searches in the app store.One of the most efficient ways to get discovered is App Store Optimization.

Page 90: A Game of Swift: Making an iOS Game with Swift and SpriteKit

ASO is to apps like SEO is to websites.ASO is actually a lot easier than SEO because even though it feels like there are so many apps, it’s a tiny fraction of the web content out there.So here are some basic tips for getting discovered in the app store.

Page 91: A Game of Swift: Making an iOS Game with Swift and SpriteKit

ASO Tips• Use all 100 characters • Commas not spaces • Use best keywords in app title • Don’t repeat • Use low competition, high traffic

keywords

Apple’s search results pull from your app title and your keywords.It doesn’t pull from your description, your review comments, or anywhere else.*** Make sure to use all 100 characters available to you for keywords.Don’t just spend 2 minutes brainstorming keywords, you should spend a lot of time coming up with keywords and perfecting your list.You can change your keywords only when you submit a new version of your app to the sore.*** Separate your keywords with commas and do not leave spaces after the comma.That just wastes precious characters*** Not only can you get extra keywords by cramming them in your app title, they are also weighted more heavily than regular keywords.This is why if you search my app it’s called “Sticky Balls - Simplest Game to Learn, Easiest to Get Addicted”I don’t think that even makes sense, syntax wise, but I don’t care I’m just stuffing keywords I’m targeting in there and trying to get it to somewhere resemble an English sentence*** Don’t repeat keywords, it doesn’t help your ranking.In my case, I wouldn’t want to put the keyword “balls” in because it’s already in my title.Again, you want to really stretch those 100 characters out as much as possible.*** An easy mistake to make is to target keywords that you’ll never rank for.There’s no reason to even try to rank for “fun” or “angry birds” because too many other games are using them.Instead of “fun” you may need to target a lower competition word like “silly”.

Page 92: A Game of Swift: Making an iOS Game with Swift and SpriteKit

To do research for keywords I use Sensor Tower.Sensor Tower has free services but to get the really good stuff you have to pay a monthly fee.You can also write a blog post reviewing them and they’ll give you some extra features without having to pay.

Page 93: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Sensor Tower keeps track of what keywords you are ranking for.It also lets you research keywords to see if they’re worth targeting.The Traffic column is an estimate of how much search traffic this particular keyword gets, and then there are difficulty scores for iPhone and iPad, followed by how many other apps are using this keyword.

Page 94: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Let’s look at the keyword “pleasant”.It has a good traffic score but more importantly it has a really low difficulty, less than 1.All of these scores are ranked 1-10.Not too many apps are using this keyword, only 141 for iPhone.I’m using this as one of my keywords and I’m ranking 21 on iPhone, which isn’t all that great.Ideally you want to be in the top 10 or lower, so this is a keyword I should probably take out and try one or two more keywords in its place since it’s a fairly long word.

Page 95: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Now if we take a look at “simplest” it has a much higher difficulty but Sticky Balls is actually ranking better, number 2 for iPhone and 1 for iPad.This is because I used simplest in the title which gives it that extra ranking.If I trusted these traffic scores more I may try to rank higher for pleasant by putting that in the title but you have to keep in mind how relevant your keywords are.I think someone searching “simple game” or “simplest” is probably looking for a minimal game which would give them more reason to download my app.When you’re deciding which keywords to target, I also choose the keywords with the lowest difficulty.To me, I’d much rather rank 2 for a moderately searched keyword than rank 250 for an extremely popular keyword.If you’re not in the top 10 it’s pretty unlikely that a user will ever see your app in my opinion.

Page 96: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Things I learned / wish I did earlier

I’ll end the presentation with some takeaways and advice I would give to myself at the beginning of this project.

Page 97: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Internationalization

When I first put the app out it was English only with the idea that I would internationalize later.I think this was a mistake because you tend to get a big influx of new users the first time your app launches from different features Apple has of new games.Today non-English speaking countries account for about 10% of my downloads, which is a decent amount to be missing out on for the first month or so of my app, particularly that initial rush of downloads.

Page 98: A Game of Swift: Making an iOS Game with Swift and SpriteKit

And the thing is, translating a simple app like this isn’t all that hard.Early on I used text instead of icons in all the buttons.By changing over to icons, it cut down on the translations.I also changed the text instructions to a simple animation that anyone regardless of language should be able to figure out.

Page 99: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Playtest

I wish that I would have play tested more thoroughly, preferably on multiple devices.My 1.0 version had a bug where you couldn’t get higher than level 60.I first noticed this when the Game Center leaderboards had five people with a high score of 59, and then some friends started telling me about the crash.If you can create a beta community that would be ideal.

Page 100: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Don’t assume you know how users will use your game.I was so used to playing Sticky Balls while developing that I couldn’t imagine not knowing how to play it.When I watched new people pick it up, they didn’t seem clear on how to move.They would drag their fingers, tap up in the direction they wanted to go, all sorts of things.Don’t assume that everything is obvious, hold people’s hands and make things explicit.

Page 101: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Keep em coming back

Games are so competitive and so many are released all the time.The average user has a pretty short attention span, so you have to give them a reason to come back.One thing that I implemented recently was a local notification that asks the player to come play Sticky Balls every few days.If I were to start over or start a new game, I would want to build a mechanic into the game that makes players want to come back.

Page 102: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Keep em coming back

For example Crossy Road gives you a free gift every 6 hours, but you need to come into the app to claim it.You can try to remember to go in every 6 hours, but the best thing to do is to just let Crossy Road send you a notification when you have a new gift ready.They’re smart about it too, they let you get a few gifts first and buy some cool stuff, they get you into it, and then on the third time or so they ask “Hey, want us to just send you a notification when your gift is ready?”That’s a great incentive to say yes, while usually 60% of people say no when that pop up comes up asking you to opt in to notifications.Bake it into your gameplay that your user inherently wants to come back.

Page 103: A Game of Swift: Making an iOS Game with Swift and SpriteKit

Another reason to come back to the app so the player can build some sort of progress.In Crossy Road you use the coins you gain to unlock new adorable characters.In another game you may level up and get new abilities.In a simple game like Sticky Balls there is main goal is to get a high score and kill time.There are achievements if the user is hooked up to Game Center, but if I were to redo it I would probably add some sort of currency in the game and different things to unlock.

Page 104: A Game of Swift: Making an iOS Game with Swift and SpriteKit

I’d also recommend steering clear of a free app unless you have a really good marketing budget or some other way to promote your game.There’s just so much competition for free apps, and the people at the top are the AAA game companies.I think it would be better to create a really good paid game because there’s a lot less competition.

Page 105: A Game of Swift: Making an iOS Game with Swift and SpriteKit

This might sound a bit strange since this is a presentation on Swift and SpriteKit, but it is probably a good idea if you’re an indie to develop using a cross-platform application.Had I made my game in Unity’s updated 2d module, I could have released Sticky Balls on Android, PC, Mac whatever.Making 2 or 3 times as much for the same amount of work is enticing when you’re restricted by how much time you’re able to contribute to your project.

Page 106: A Game of Swift: Making an iOS Game with Swift and SpriteKit

And last, if at all possible I’d recommend working in a team.I created Sticky Balls alone, only later on asking for help in marketing, but I think if you’re going to make a real quality game you probably need at least two programmers, an artist, and a marketing specialist.If you can get your artist to specialize in marketing then that’s all the better but good luck with that.

Page 107: A Game of Swift: Making an iOS Game with Swift and SpriteKit