Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all 4370 articles
Browse latest View live

watchOS 2 by Tutorials Updated for Xcode 7.3

$
0
0

watchOS 2 by Tutorials Now Available!

Good news – we have updated watchOS 2 by Tutorials for Swift 2.2 and Xcode 7.3.

Xcode 7.3 has a few small changes to Swift – mostly minor syntax things – but we wanted to make sure that all the instructions work without any issues.

In addition to updating the book for Xcode 7.3, we’ve fixed some errata pointed out by readers – thanks all!

This is a free update for existing PDF customers. Here’s how you can get your copy:

  • If you’re a watchOS 2 by Tutorials PDF customer, you can download the update for free on your My Loot page (version 1.1).
  • If you haven’t picked up a copy of watchOS 2 by Tutorials yet, grab your copy now.

At this point, all of the books on our site are fully up-to-date with Xcode 7.3 – w00t! We’ve done this for free as a way of saying thanks for supporting this site.

We hope you enjoy the updates, and again thank you! :]

The post watchOS 2 by Tutorials Updated for Xcode 7.3 appeared first on Ray Wenderlich.


Video Tutorial: Beginning Core Graphics Part 3: Contexts 1

Collection Data Structures in Swift

$
0
0
What kind of performance do you want from your data structure?

What kind of performance do you want from your data structure?

Update note: This tutorial was updated for Swift 2.2 and Xcode 7.3 by Niv Yahel. Original post by Tutorial Team member Ellen Shapiro.

Imagine you have an application that needs to work with a lot of data. Where do you put that data? How do you keep it organized and handle it efficiently?

If your program only manages one number, you store it in one variable. If it has two numbers then you’d use two variables.

What if it has 1000 numbers, 10,000 strings or the ultimate library of memes? And wouldn’t it be nice to be able to find a perfect meme in an instant?

In that case, you’ll need one of the fundamental collection data structures, such as Arrays, Dictionarys, and Sets. As you’ll learn, these collection data structures allow you and the user to manipulate huge databases with a swipe across a screen. Thanks to Swift and its ever-evolving nature, you’ll be able to use native data structures that are blazing fast!

Here’s how the tutorial will flow:

  1. First, you’ll review what a data structure is, and then you’ll learn about Big-O notation. It’s the standard tool for describing the performance of different data structures.
  2. Next you’ll observe these data structures by measuring the performance of arrays, dictionaries, and sets — the most basic data structures available in Cocoa development. Incidentally, it’ll also double as a rudimentary introduction to performance testing.
  3. As you proceed, you’ll compare the performance of mature Cocoa structures with newer, Swift-only counterparts.
  4. Finally, you’ll briefly review some related types offered by Cocoa. These are data structures that you might be surprised to learn are already at your fingertips!

Getting Started

Before you dive in and explore the data structures used in iOS, you should review these basic, key concepts about what they are and how to measure their performance.

There are many types of collection data structures, and each represents a specific way to organize and access a collection of items. A specific collection type might make some activities especially efficient such as adding a new item, finding the smallest item, or ensuring you’re not adding duplicates.

Without collection data structures, you’d be stuck trying to manage items one by one. A collection allows you to:

  1. Handle all those items as one entity
  2. Imposes some structure
  3. Efficiently insert, remove, and retrieve items

What is “Big-O” Notation?

Big-O notation — that’s the letter O, not the number zero — is a way of describing the efficiency of an operation on a data structure. There are various kinds of efficiency: you could measure how much memory the data structure consumes, how much time an operation takes under the worst case scenario, or how much time an operation takes on average. It’s not the raw memory or time that we care about here though. It is the way the memory or time scales, as the size of the data structure scales.

In this tutorial, you’ll measure how much time an operation takes on average.

Common sense will tell you that an operation takes longer to perform when there are larger quantities of data. But sometimes there is little or no slowdown, depending on the data structure.

Big-O notation is a precise way of describing this.

You write an exact functional form that roughly describes how the running time changes based on the number of elements in the structure.

When you see Big-O notation written as O(something-with-n), n is the number of items in the data structure, and something-with-n is roughly how long the operation will take.

“Roughly”, ironically enough, has a specific meaning: the behavior of the function at the asymptotic limit of very large n. Imagine n is a really, really large number — you’re thinking about how the performance of some operation will change as you go from n to n+1.

The most commonly seen Big-O performance measures are as follows, in order from best to worst performance:

O(1) — (constant time)
No matter how many items are in a data structure, this function calls the same number of operations. This is considered ideal performance.

O(log n) — (logarithmic)
The number of operations this function calls grows at the rate of the logarithm of the number of items in the data structure. This is good performance, since it grows considerably slower than the number of items in the data structure.

O(n) — (linear)
The number of operations this function calls will grow linearly with the size of the structure. This is considered decent performance, but it can grind along with larger data collections.

O(n (log n)) — (“linearithmic”)
The number of operations called by this function grows by the logarithm of the number of items in the structure multiplied by the number of items in the structure. Predictably, this is about the lowest level of real-world tolerance for performance. While larger data structures perform more operations, the increase is somewhat reasonable for data structures with small numbers of items.

O(n²) — (quadratic)
The number of operations called by this function grows at a rate that equals the size of the data structure, squared — poor performance at best. It grows quickly enough to become unusably slow even if you’re working with small data structures.

O(2^n) — (exponential)
The number of operations called by this function grows by two to the power of the size of the data structure. The resulting very poor performance becomes intolerably slow almost immediately.

O(n!) (factorial)
The number of operations called by this function grows by the factorial of the size of the data structure. Essentially, you have the worst case scenario for performance. For example, in a structure with just 100 items, the multiplier of the number of operations is 158 digits long. Witness it for yourself on wolframalpha.com.

Here’s a more visual representation of performance and how it degrades when there are more items in a collection, going from one to 25 items:

Big-O Notation

Did you notice that you can’t even see the green O(log n) line because it is so close to the ideal O(1) at this scale? That’s pretty good! On the other hand, operations that have Big-O notations of O(n!) and O(2^n) degrade so quickly that by the time you have more than 10 items in a collection, the number of operations spikes completely off the chart.

Yikes! As the chart clearly demonstrates, the more data you handle, the more important it is to choose the right structure for the job.

Now that you’ve seen how to compare the performance of operations on data structures, it’s time to review the three most common types used in iOS and explore how they perform in theory and in practice.

Common iOS Data Structures

The three most common data structures in iOS are arrays, dictionaries and sets, each of which deserves your attention. In this section, you’ll:

  1. Consider how they differ in ideal terms as fundamental abstractions
  2. Examine the performance of the actual concrete classes that iOS offers for representing those abstractions.

For the three types, iOS offers multiple concrete classes that work for the same abstraction. In addition to the old Foundation data structures available in Swift and Objective-C, there are new Swift-only versions of data structures that integrate tightly with the language.

Since its introduction, Swift has brought many performance improvements to Swift data structures and now outperforms Foundation data structures in the majority of cases. However, the “best” one to use still depends on the operation you want to perform.

Arrays

Arrays

An array is a group of items placed in a specific order, and you can access each item via an index — a number that indicates its position in the order. When you write the index in brackets after the name of the array variable, this is subscripting.

Swift arrays are immutable if you define them as constants with let, and mutable if you define them as variables with var.

In contrast, a Foundation NSArray is immutable by default. If you want to add, remove or modify items after creating the array, you must use the mutable variant class NSMutableArray.

An NSArray is heterogeneous, meaning it can contain Cocoa objects of different types. Swift arrays are homogeneous, meaning that each Array is guaranteed to contain only one type of object.

However, you can still define a single Swift Array so it stores various types of Cocoa objects by specifying that the one type is AnyObject, since every Cocoa type is also a subtype of this.

Expected Performance and When to Use Arrays

The primary reason to use an array is when the order of variables matters. Think about those times when you sort contacts by first or last name, a to-do list by date, or any other situation when it’s critical to find or display data in a specific order.

Apple’s documentation includes three key expectations for Array performance in the CFArray header:

  1. Accessing any value at a particular index in an array is at worst O(log n), but should usually be O(1).
  2. Searching for an object at an unknown index is at worst O(n (log n)), but will generally be O(n).
  3. Inserting or deleting an object is at worst O(n (log n)) but will often be O(1).

These guarantees subtly deviate from the simple “ideal” array that you might expect from a computer science textbook or the C language, where an array is always a sequence of items laid out contiguously in memory.

Consider it a useful reminder to check the documentation!

In practice, these expectations make sense when you think about them:

  1. If you already know where an item is, then looking it up in the array should be fast.
  2. If you don’t know where a particular item is, you’ll need to look through the array from beginning to end. Your search will be slower.
  3. If you know where you’re adding or removing an object it’s not too difficult. Although, you may need to adjust the rest of the array afterwards, and that’s more time-consuming.

How well do these expectations align with reality? Keep reading to find out!

Note: Swift officially became open source in December of 2015. You can look through the Swift source code yourself to see how these data structures are implemented under the hood!

Sample App Testing Results

Download the sample project and open it in Xcode. It’s time to play around with testing methods that will create and/or test an array and show how long it took to perform each task.

Note: In the app, the Debug configuration automatically sets optimization to a level equal to the release configuration — this is so that when you test the application you get the same level of optimization you’d see in the real world.

You need a minimum of 1000 items to run tests with the sample app, so that results are large enough to detect. When you build and run, the slider will be set to 1000. Press the Create Array and Test button, and you’ll be testing in no time:

Swift 2.1.1 Create 1000 items

Drag the slider over to the right side until it hits 10,000,000, and press Create Array and Test again to see the difference in creation time with a significantly larger array:

Swift 1.2 Create 10,000,000

These tests were run against an iPhone 6 running iOS 9.2 from Xcode 7.2, which includes Swift 2.1.1. With 10,000 times as many items, creating the array only takes about 1,537 times as much time.

Note: A while ago, when Swift was a little baby, this used to take…quite a bit longer. On an iPhone 5 running the iOS 8 Gold Master with the Swift 1.0/Xcode 6.0 Gold Master:

Swift 1000 Items vs 100,000 itesms

In this case, for around 106.5 times the number of items, it took roughly 1,417 times as much time to create the array. Any more than a few dozen items, and this was unusable.

Since the dark days of old, Swift has made tremendous performance improvements and you can now easily make huge arrays with few problems!

What about NSMutableArray? You can still call Foundation classes from Swift without having to drop back down to Objective-C.

Take a look inside the DataManipulators folder in Xode. Here you’ll find the various objects that handle the work of setting up the array and performing the various tasks that are then timed. You’ll notice there is a class called SwiftArrayManipulator. This conforms to ArrayManipulator which is where the methods are defined that the timing code uses.

There is also a class called NSArrayManipulator that also conforms to ArrayManipulator. Because of this, you can easily swap in an NSMutableArray for a Swift Array. The project code is simple enough that you can try an NSMutableArray with a single line change to compare the performance.

Open ArrayViewController.swift and change line 27 from:

let arrayManipulator: ArrayManipulator = SwiftArrayManipulator()

To:

let arrayManipulator: ArrayManipulator = NSArrayManipulator()

Build and run again, and press Create Array and Test to test the creation of an NSMutableArray with 1000 items:

NSArray Create 1000 items Xcode 7.2

…and then again with 10,000,000 items:

NSArray Create 10,000,000 items Xcode 7.2

Raw performance for creation is close to Swift, but not as good. Some of that, however, may come from the need to jockey between objects that can be stored in an NSArray and its Swift counterparts.

However, you only create an array once, and you perform other operations on it far more often, such as finding, adding, or removing objects.

In more exhaustive testing, such as when you’re using some of Xcode 7’s performance testing methods to call each of these methods 50 times, patterns begin to emerge:

  • Creating a Swift Array and an NSArray degrade at roughly the same rate between O(log n) and O(n). Swift is faster than Foundation, but both are in the region of 0.01 seconds. This is a significant improvement over Swift 1.2, where it took 3x as long as Foundation!
  • Adding items to the beginning of an array is considerably slower in a Swift Array than in an NSArray, which is around O(1). Adding items to the middle of an array is a bit slower in a Swift Array than in an NSArray. Adding items to the end of a Swift Array, which is less than O(1), is actually faster than adding items to the end of an NSArray, which comes in just over O(1).
  • Removing objects demonstrates similar in performance degradation across NSArray and Swift Array. From the beginning, middle or end, removing an object degrades between O(log n) and O(n). Raw time is much worse in Swift when you remove from the beginning of an Array, but the distinction is a matter of milliseconds.
  • Looking up items within an array is where Swift earns its name. Look ups by index and object grow at very close rates for both Swift arrays and NSArray. When you’re querying by index, large Swift arrays perform nearly 10 times faster in raw time than using comparable NSMutableArray objects.

Dictionaries

Dictionaries

Dictionaries are a way of storing values that don’t need to be in any particular order and are uniquely associated with keys. You use the key to store or look up a value.

Dictionaries also use subscripting syntax, so when you write dictionary["hello"], you’ll get the value associated with the key hello.

Like arrays, Swift dictionaries are immutable if you declare them with let and mutable if you declare them with var. Similarly on the Foundation side, there are both NSDictionary and NSMutableDictionary classes for you to use.

Another characteristic that is similar to Swift arrays is that dictionaries are strongly typed, and you must have known key and value types. NSDictionary objects are able to take any NSObject as a key and store any object as a value.

You’ll see this in action when you call a Cocoa API that takes or returns an NSDictionary. From Swift, this type appears as [NSObject: AnyObject]. This indicates that the key must be an NSObject subclass, and the value can be any Swift-compatible object.

When to use Dictionaries

Chaplin

Chaplin still knows when to use dictionaries. Do you?

Dictionaries are best used when there isn’t a particular order to what you need to store, but the data has meaningful association.

To help you examine how dictionaries and other data structures in the rest of this tutorial work, create a Playground by going to File…\New\Playground, and name it DataStructures.

For example, pretend you need to store a data structure of all your friends and the names of their cats, so you can look up the cat’s name using your friend’s name. This way, you don’t have to remember the cat’s name to stay in that friend’s good graces.

First, you’d want to store the dictionary of people and cats. Add the following to the playground:

let cats = [ "Ellen" : "Chaplin", "Lilia" : "George Michael", "Rose" : "Friend", "Bettina" : "Pai Mei"]

Thanks to Swift type inference, this will be defined as [String: String] — a dictionary with string keys and string values.

Now try to access items within it. Add the following:

cats["Ellen"] //returns Chaplin as an optional
cats["Steve"] //Returns nil

Note that subscripting syntax on dictionaries returns an optional. If the dictionary doesn’t contain a value for a particular key, the optional is nil; if it does contain a value for that key you get the wrapped value.

Because of that, it’s a good idea to use the if let optional-unwrapping syntax to access values in a dictionary. Add the following:

if let ellensCat = cats["Ellen"] {
    print("Ellen's cat is named \(ellensCat).")
} else {
    print("Ellen's cat's name not found!")
}

Since there is a value for the key “Ellen”, this will print out “Ellen’s cat is named Chaplin” in your Playground.

Expected Performance

Once again, Apple outlines the expected performance of dictionaries in Cocoa in the CFDictionary.h header file:

  1. The performance degradation of getting a single value is guaranteed to be at worst O(log n), but will often be O(1).
  2. Insertion and deletion can be as bad as O(n (log n)), but typically be closer to O(1) because of under-the-hood optimizations.

These aren’t quite as obvious as the array degradations. Due to the more complex nature of storing keys and values versus a lovely ordered array, the performance characteristics are harder to explain.

Sample App Testing Results

DictionaryManipulator is a similar protocol to ArrayManipulator, and it tests dictionaries. With it, you can easily test the same operation using a Swift Dictionary or an NSMutableDictionary.

To compare the Swift and Cocoa dictionaries, use a similar procedure as you used for the arrays. Build and run the app and select the Dictionary tab at the bottom.

Run a few tests – you’ll notice that dictionaries take significantly longer to create than arrays. If you push the item slider up to 10,000,000 items, you might even be able to get a memory warning or even an out-of-memory crash!

Back in Xcode, open DictionaryViewController.swift and find the dictionaryManipulator property:

let dictionaryManipulator: DictionaryManipulator = SwiftDictionaryManipulator()

Replace it with the following:

let dictionaryManipulator: DictionaryManipulator = NSDictionaryManipulator()

Now the app will use NSDictionary under the hood. Build and run the app again, and run a few more tests. If you’re running Swift 2.1.1, your findings should be similar to the results of more extensive testing:

  • In raw time, creating Swift dictionaries is faster than creating NSMutableDictionaries but both degrade at roughly the same O(n) rate.
  • Adding items to Swift dictionaries is roughly 10 times faster than adding them to NSMutableDictionaries in raw time, and both degrade close to the best-case-scenario O(1) rate promised by Apple’s documentation.
  • Removing items from Swift dictionaries is roughly as fast as removing items from NSMutableDictionaries, but the degradation of performance is again close to O(1) for both types.
  • Both Swift and Foundation dictionaries are able to lookup at roughly an O(1) rate. Like Swift arrays, dictionaries are faster in raw time than Foundation dictionaries, though the performance is very, very close.

These are amazing improvements over Swift 1.2. where creating dictionaries was significantly slower than creating NSMutableDictionaries. Back then, adding items to Swift dictionaries was also only three times faster. Removing Swift dictionaries was one – three times slower.

Swift 2.0 is what made native Swift dictionaries the better option.

And now, on to the final major data structure used in iOS: Sets!

Sets

Sets

A set is a data structure that stores unordered, unique values. Unique is the key word; you won’t won’t be able to add a duplicate.

Swift sets are type-specific, so all the items in a Swift Set must be of the same type.

Swift added support for a native Set structure in version 1.2 – for earlier versions of Swift, you could only access Foundation’s NSSet.

Note that like arrays and dictionaries, a native Swift Set is immutable if you declare it with let and mutable if you declare it with var. Once again on the Foundation side, there are both NSSet and NSMutableSet classes for you to use.

When to use Sets

Sets are most useful when uniqueness matters, but order does not. For example, what if you wanted to select four random names out of an array of eight names, with no duplicates?

Enter the following into your Playground:

let names = ["John", "Paul", "George", "Ringo", "Mick", "Keith", "Charlie", "Ronnie"]
var stringSet = Set<String>() // 1
var loopsCount = 0
while stringSet.count < 4 {
    let randomNumber = arc4random_uniform(UInt32(names.count)) // 2
    let randomName = names[Int(randomNumber)] // 3
    print(randomName) // 4
    stringSet.insert(randomName) // 5
    loopsCount += 1 // 6
}
 
// 7
print("Loops: " + loopsCount.description + ", Set contents: " + stringSet.description)

In this little code snippet, you do the following:

  1. Initialize the set so you can add objects to it. It is a set containing String objects.
  2. Pick a random number between 0 and the count of names.
  3. Grab the name at the selected index.
  4. Log the selected name to the console.
  5. Add the selected name to the mutable set. Remember, if the name is already in the set, then the set won’t change since it doesn’t store duplicates.
  6. Increment the loop counter so you can see how many times the loop ran.
  7. Once the loop finishes, print out the loop counter and the contents of the mutable set.

Since this example uses a random number generator, you’ll get a different result every time. Here’s an example of the log produced while writing this tutorial:

John
Ringo
John
Ronnie
Ronnie
George
Loops: 6, Set contents: ["Ronnie", "John", "Ringo", "George"]

Here, the loop ran six times in order to get four unique names. It selected Ronnie and John twice, but they only wound up in the set once.

As you’re writing the loop in the Playground, you’ll notice that it runs on a, well, loop, and you’ll get a different number of loops each time. In this case, you’ll need at least four loops, since there must always be four items in the set to break out of the loop.

Now that you’ve seen Set at work on a small scale, it’s time to examine performance with a larger batch.

Sample App Testing Results

Apple didn’t outline overall expectations for set performance as they did for dictionaries and arrays, so in this case you’ll just look at real-world performance.

The Swift Set documentation outlines performance characteristics for a couple of methods, but NSMutableSet does not.

The sample project has NSSetManipulator and SwiftSetManipulator objects in the SetViewController class similar to the setup in the array and dictionary view controllers, and can be swapped out the same way.

In both cases, if you’re looking for pure speed, using a Set probably won’t make you happy. Compare the numbers on Set and NSMutableSet to the numbers for Array and NSMutableArray, and you’ll see set creation is considerably slower — that’s the price you pay for checking if every single item in a data structure is unique.

Detailed testing revealed that since Swift’s Set shows that performance degradation and raw time for most operations is extremely similar to that of NSSet: Creation, removal, and lookup operations are all nearly identical between Foundation and Swift in raw time. Perhaps the extra time in the oven paid off for sets.

Creation degrades for both Swift and Foundation set types at a rate of around O(n). This is expected because every single item in the set must be checked for equality before a new item may be added.

Removing and looking up actions are both around O(1) performance degradations across Swift and Foundation, making set lookup considerably faster than array lookup. This is largely because set structures use hashes to check for equality, and the hashes can be calculated and stored in sorted order.

Overall, it appears that adding an object to an NSSet stays near O(1), whereas it can degrade at a rate higher than O(n) with Swift’s Set structure.

Swift has seen very significant performance improvements in collection data structure performance in its short public life, and will hopefully continue to see them as Swift evolves.

Lesser-known Foundation Data Structures

Arrays, dictionaries and sets are the workhorses of data-handling. However, Cocoa offers a number of lesser-known and perhaps under-appreciated collection types. If a dictionary, array or set won’t do the job, it’s worth checking if one of these will work before you create something from scratch.

NSCache

Using NSCache is very similar to using NSMutableDictionary – you just add and retrieve objects by key. The difference is that NSCache is designed for temporary storage for things that you can always recalculate or regenerate. If available memory gets low, NSCache might remove some objects. They are thread-safe, but Apple’s documentation warns:

…The cache may decide to automatically mutate itself asynchronously behind the scenes if it is called to free up memory.

This means that an NSCache is like an NSMutableDictionary, except that Foundation may automatically remove an object at any time to relieve memory pressure. This is good for managing how much memory the cache uses, but can cause issues if you rely on an object that may potentially be removed.

NSCache also stores weak references to keys rather than strong references.

NSCountedSet

NSCountedSet tracks how many times you’ve added an object to a mutable set. It inherits from NSMutableSet, so if you try to add the same object again it will only be reflected once in the set.

However, an NSCountedSet tracks how many times an object has been added. You can see how many times an object was added with countForObject().

Note that when you call count on an NSCountedSet, it only returns the count of unique objects, not the number of times all objects were added to the set.

To illustrate, at the end of your Playground take the array of names you created in your earlier NSMutableSet testing and add each one to an NSCountedSet twice:

let countedMutable = NSCountedSet()
for name in names {
    countedMutable.addObject(name)
    countedMutable.addObject(name)
}

Then, log out of the set itself and find out how many times “Ringo” was added:

let ringos = countedMutable.countForObject("Ringo")
print("Counted Mutable set: \(countedMutable)) with count for Ringo: \(ringos)")

Your log should read:

Counted Mutable set: {(
    George,
    John,
    Ronnie,
    Mick,
    Keith,
    Charlie,
    Paul,
    Ringo
)}) with count for Ringo: 2

Note that while you may see a different order for the set, you should only see “Ringo” appear in the list of names once, even though you can see that it was added twice.

NSOrderedSet

An NSOrderedSet along with its mutable counterpart, NSMutableOrderedSet, is a data structure that allows you to store a group of distinct objects in a specific order.

“Specific order” — gee, that sounds an awful lot like an array, doesn’t it? Apple succinctly sums up why you’d want to use an NSOrderedSet instead of an array (emphasis mine):

You can use ordered sets as an alternative to arrays when element order matters and performance while testing whether an object is contained in the set is a consideration — testing for membership of an array is slower than testing for membership of a set.

Because of this, the ideal time to use an NSOrderedSet is when you need to store an ordered collection of objects that cannot contain duplicates.

Note: While NSCountedSet inherits from NSMutableSet, NSOrderedSet inherits from NSObject. This is a great example of how Apple names classes based on what they do, but not necessarily how they work under the hood.

NSHashTable and NSMapTable

Map table?

Not this kind of Map Table. (Courtesy the Tennessee Valley Authority(!) via Flickr Creative Commons)

NSHashTable is another data structure that is similar to Set, but with a few key differences from NSMutableSet.

You can set up an NSHashTable using any arbitrary pointers and not just objects, so you can add structures and other non-object items to an NSHashTable. You can also set memory management and equality comparison terms explicitly using NSHashTableOptions enum.

NSMapTable is a dictionary-like data structure, but with similar behaviors to NSHashTable when it comes to memory management.

Like an NSCache, an NSMapTable can hold weak references to keys. However, it can also remove the object related to that key automatically whenever the key is deallocated. These options can be set from the NSMapTableOptions enum.

NSIndexSet

An NSIndexSet is an immutable collection of unique unsigned integers intended to represent indexes of an array.

If you have an NSArray of ten items where you regularly need to access items’ specific positions, you can store an NSIndexSet and use NSArray’s objectsAtIndexes: to pull those objects directly:

let items : NSArray = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
 
let indexSet = NSMutableIndexSet()
indexSet.addIndex(3)
indexSet.addIndex(8)
indexSet.addIndex(9)
 
items.objectsAtIndexes(indexSet) // returns ["four", "nine", "ten"]

You specify that “items” is an NSArray since right now, Swift arrays don’t have an equivalent way to access multiple items using an NSIndexSet or a Swift equivalent.

An NSIndexSet retains the behavior of NSSet that only allows a value to appear once. Hence, you shouldn’t use it to store an arbitrary list of integers unless only a single appearance is a requirement.

With an NSIndexSet, you’re storing indexes as sorted ranges, so it is more efficient than storing an array of integers.

Pop Quiz!

Now that you’ve made it this far, you can test your memory with a quick quiz about what sort of structure you might want to use to store various types of data.

For the purposes of this quiz, assume you have an application where you display information in a library.

Q: What would you use to create a list of every author in the library?

Solution Inside: Unique List of Author Names SelectShow>

Q: How would you store the alphabetically sorted titles of a prolific author’s entire body of work?

Solution Inside: Alphabetically-Sorted Titles SelectShow>

Q: How would you store the most popular book by each author?

Solution Inside: Most Popular Book by each author SelectShow>

Where to Go From Here?

I’d like to give special thanks to my fellow tutorial team member, Ellen Shapiro, who initially created this tutorial and updated it until Swift 1.2. I would also like to thank Chris Wagner, who started on an Objective-C version of this article before the SwiftHammer came down upon us all, for passing along his notes and sample project for me to use while pulling this tutorial together.

I’ll also say thanks to the Swift team at Apple — constant improvements to Swift have made the native data structures stay true to the Swift name. In the foreseeable future, it seems that we won’t have a need for the Foundation data structures anymore. :]

If you want to learn more about data structures for iOS, here are a few excellent resources:

Got more questions? Go nuts in the comments below!

The post Collection Data Structures in Swift appeared first on Ray Wenderlich.

Video Tutorial: Beginning Core Graphics Part 4: Contexts 2

Easier Auto Layout: Coding Constraints in iOS 9

$
0
0
auto layout

Coding Auto Layout just got a lot easier! Read on to find out more.

Do you find Auto Layout challenging? Do you find yourself making and unmaking constraints over and over in a never-ending attempt to find the seemingly random correct layout? Do you find it daunting when you have to modify Auto Layout constraints in code?

Never fear! In this Auto Layout tutorial instead of using Interface Builder and storyboards, you’ll create all your constraints in code using layout anchors, a new API delivered as part of iOS 9. Creating constraints in code will lead to a greater understanding of Auto Layout constraint relationships, and even make it easier for you create Auto Layout driven views in Interface Builder.

You’ll learn about:

  • iOS 9 layout anchors
  • Layout guides
  • Intrinsic content size
  • The Auto Layout update cycle
  • Laying out for different size classes

In short, you’ll learn how to stay afloat with Auto Layout. :]

auto layout

You’ll be creating an app called Wonderland, a simple Alice in Wonderland story app. Here’s what the app will look like when you’re finished:

auto layout

Using code to create all the views and constraints, you’ll lay out the app differently using Compact and Regular size classes.

Although the raywenderlich.com team advocates using storyboards whenever possible, sometimes it’s better to use code to create your views. For example, Wonderland contains an avatar profile view that you can use across several apps. It’s easier to reuse code rather than copy Interface Builder views across several apps.

In addition, if you learn how Auto Layout works in code, it’s easier to apply it in Interface Builder, which can become difficult to follow when you’re laying out various size class combinations.

Getting Started

Download the Wonderland starter app and open it up in Xcode.

Note: Use the iPhone 6s Plus simulator for testing unless told otherwise. The 6s Plus is horizontally Compact in portrait and horizontally Regular in landscape, so you can easily test both layouts.

You can see all the size classes and devices here.

Adaptive Layout Tutorial in iOS 9: Getting Started will teach you the basics of size classes and adaptive layout.

If you’re a raywenderlich.com subscriber you can watch a video to learn more about size classes here.

Run the app and you’ll see three colored views:

auto layout

  • avatarView – cyan: this view will show the chapter image, book title and social media icons.
    (I’ve called it avatarView because, even though in this app it may not look much like an avatar or profile view, it will have the standard profile view objects of image view, name and icons. You could use this view across multiple apps.)
  • chapterLabel – yellow: tells you what the current chapter is.
  • bookTextView – green: the text of the current chapter.

You can swipe the text view left or right to move to the next and previous chapters.

The three views are properly positioned using the view’s frame property.

But rotate the device (Cmd + left or right arrow), and the views don’t expand correctly to fill the landscape width:

auto layout

Open ViewController.swift, there’s only one method – viewDidLoad() – which calls methods to set up the three views.

The setup methods are defined in ViewControllerExtension.swift. These are separated out because you won’t be changing any of this code. You’ll only be working in ViewController.swift and AvatarView.swift.

What is Auto Layout?

Note: Have a brief look at our Auto Layout in Interface Builder tutorial. Even if you don’t plan to use Interface Builder yourself, the tutorial explains many useful concepts.

Auto Layout is a layout system based on constraints. You no longer think about screen objects in terms of their exact size. Only the relationship between the objects is relevant.

The downside of this is that the constraint system is extremely logical, and with one slip in logic your whole layout can come tumbling down.

auto layout

The advantages are considerable. In Wonderland you will set up relationships between views of varying sizes, and they will automatically grow and shrink as the device rotates because they are part of a layout system.

Working out Constraints

The best way to work out what constraints are required is to make a drawing of the required result. Forget the details; just look at the basic layout and decide on the relative positioning of views:

auto layout

For each one of these three views you have to provide at least four constraints: X position, Y position, Width and Height.

These are the constraints you’ll create:

  1. Each view is anchored to the leading edge of the main view’s margin guide, giving the X position constraint.
  2. bookTextView is anchored to the bottom of the main view; chapterLabel is anchored to the top of bookTextView and avatarView is anchored to the top of chapterLabel. This gives all views their Y position constraint.
  3. Each view is anchored to the trailing edge of the main view’s margin guide, giving the Width constraint for each – the width essentially stretches from the leading edge to the trailing edge.
  4. The Height constraint is the most difficult of the constraints to work out, as each view should stretch differently.

    The most important of these views is bookTextView, which is the text of the current chapter. You’ll set up this view to take up two thirds of the screen, and the other two views will take up the rest of the space.

    avatarView is the least important; this can grow and shrink depending on what space is available to it.

    chapterLabel should remain the same height no matter what, and is set by the font height of the text.

So now to translate this into code.

First, in ViewController create a new method called setupConstraints():

func setupConstraints() {
}

You’ll be using setupConstraints() to set up the constraints for all three views.

In viewDidLoad() remove the call to setupFrames() and replace it with the following:

setupConstraints()

Note: Constraints must be added after adding views to their superviews. All constraints need to be in the same hierarchy. If they aren’t, the app will immediately crash.

Constraint Anchors

Auto Layout Tutorial

iOS 9 introduced NSLayoutAnchor with anchor properties on UIView. You can now set up your views to be ‘anchored’ to other views.

There are three subclasses of NSLayoutAnchor:

  • NSLayoutXAxisAnchor
  • NSLayoutYAxisAnchor
  • NSLayoutDimension

When you set up a view’s anchor to be constrained to another view’s anchor, it must be of the same subclass. For example, the compiler will reject constraining a leadingAnchor, a subclass of NSLayoutXAxisAnchor, to a heightAnchor which is a subclass of NSLayoutYAxisAnchor.

This is another advantage of using anchors: you get extra constraint validity checking for free.

Note: Beware constraining leading / trailing anchors to left / right anchors – this will crash at runtime. Even though they are all instances of NSLayoutXAxisAnchor, Auto Layout does not let you mix leading with left anchors or trailing with right anchors.

Add the following code to setupConstraints():

// 1
bookTextView.translatesAutoresizingMaskIntoConstraints = false
// 2
bookTextView.leadingAnchor.constraintEqualToAnchor(
                view.leadingAnchor).active = true
bookTextView.trailingAnchor.constraintEqualToAnchor(
                view.trailingAnchor).active = true
bookTextView.bottomAnchor.constraintEqualToAnchor(
                view.bottomAnchor,
                constant: -20).active = true
// 3
bookTextView.heightAnchor.constraintEqualToAnchor(
                view.heightAnchor,
                multiplier: 0.65).active = true

Going through this step-by-step:

  1. You first set translatesAutoresizingMaskIntoConstraints to false. This tells the view that it’s using Auto Layout rather than frames. Interface Builder does this automatically, but if you are adding constraints in code, you need to set this property.
  2. You set up bookTextView‘s leading, trailing, and bottom anchors to anchor to the main view. The bottom anchor has a constant of -20 which will give a white space margin of 20 points at the bottom of the screen
  3. Using a multiplier, you set bookTextView to be always 65% of the height of the view controller’s view, no matter what size that view is.

By setting each constraint’s active property to true, these constraints are immediately active.

Note: When you set bookTextView‘s constraints, you used leading and trailing anchors rather than left and right anchors. Leading and trailing become relevant for right-to-left languages such as Arabic. In a right-to-left language, trailing becomes left and leading becomes right.
So when you localize Wonderland to Hebrew or Arabic, there will be no structural layout changes required!

Build and run the app in both portrait and landscape. bookTextView‘s frame adjusts automatically to match the view controller view’s frame.

auto layout

auto layout

You can try this out on the iPad simulators too; the view will always be 65% high.

View Layout Margins

All views have a layoutMarginsGuide property to which you can anchor, instead of anchoring to the view.

In most cases, rather than extending subviews all the way to the edge of the screen, it’s better to anchor subviews to the left and right view margin guides to allow standard white space around the edges.

You’ll now add avatarView to the top of the screen using the main view’s left and right layout margin guide anchors. This will leave white space on either side of avatarView.

Add the following code to the end of setupConstraints():

// 1
avatarView.translatesAutoresizingMaskIntoConstraints = false
// 2
avatarView.topAnchor.constraintEqualToAnchor(
                view.topAnchor).active = true
// 3
avatarView.leadingAnchor.constraintEqualToAnchor(
                view.layoutMarginsGuide.leadingAnchor).active = true
avatarView.trailingAnchor.constraintEqualToAnchor(
                view.layoutMarginsGuide.trailingAnchor).active = true
// 4
avatarView.heightAnchor.constraintEqualToConstant(200).active = true

Here’s the explanation of the code above:

  1. Here you set avatarView to use Auto Layout.
  2. You set avatarView‘s top constraint to the view’s top edge.
  3. You set the leading and trailing edges to constrain to the view’s margins instead of the edges of the view.
  4. avatarView‘s height is a constant 200. You’ll be changing this later in this Auto Layout tutorial.

Build and run the app; avatarView is the cyan view at the top of the screen:

auto layout

View Controller Layout Guides

As well as the view’s margin guides, view controllers have a top and bottom layout guide.

You can see that avatarView is underneath the status bar. If you had other translucent bars, such as a navigation or tab bar, the view controller’s view would also extend under these, and the content would be obscured by the bar.

When constraining subviews to a view controller’s view, you should always constrain to the view controller’s top guide’s bottom anchor and bottom guide’s top anchor, rather than the view’s top and bottom anchors. This will prevent the status bar from covering the subview.

Change avatarView‘s top anchor constraint in setupConstraints() to:

avatarView.topAnchor.constraintEqualToAnchor(
           topLayoutGuide.bottomAnchor).active = true

Here you constrain avatarView to the view controller’s top layout guide’s bottom anchor. The status bar, and any other translucent bars that may be added later, will no longer cover avatarView.

Similarly in setupConstraints(), change bookTextView‘s bottom anchor to:

bookTextView.bottomAnchor.constraintEqualToAnchor(
                 bottomLayoutGuide.topAnchor,
                 constant: -20).active = true

This will constrain bookTextView to the view controller’s bottom layout guide’s top anchor with a margin of 20 points. If you later add a tab bar to your app, then the text will not be covered by the bar.

Build and run the app; avatarView is no longer covered by the status bar:

auto layout

There’s no change to bookTextView because there are currently no tab bars on the screen.

Readable Content Guide

auto layout

The text in bookTextView currently goes from edge to edge and is very uncomfortable to read on an iPad’s wide screen.

Using readable content guides, which change depending on size class, you can make the text more readable by automatically adding more white space at the edges than layout margins currently provide.

On the iPhone 6s Plus in portrait, readable content guides are the same as the view’s margin guides, but in landscape there is more white space on either side of the text view. On the iPad in landscape, the white space is increased significantly.

The margin size depends on the system’s dynamic type. The larger the font, the wider the guide will be.

In setupConstraints(), change bookTextView‘s leading and trailing anchors to:

bookTextView.leadingAnchor.constraintEqualToAnchor(
             view.readableContentGuide.leadingAnchor).active = true
bookTextView.trailingAnchor.constraintEqualToAnchor(
             view.readableContentGuide.trailingAnchor).active = true

This changes the leading and trailing anchors to constrain to the readable content guide instead of the view’s edges.

Run the app on an iPad in landscape, and see how much more readable the text is when it’s centered in the screen:

auto layout

Note: You’ve used layout guides provided by Apple, but you can create your own layout guides and constrain views to these guides.

When you create a layout guide, you get most of the anchors available with views. So if you anchor several views to a layout guide and then reposition the guide, all the anchored views will move with the guide.

Layout guides are lighter in resources than UIViews and let you go even further than stack views with spatial relationships.

Intrinsic Content Size

Now it’s time to work on the chapter label.

At the end of setupConstraints() add the following:

chapterLabel.translatesAutoresizingMaskIntoConstraints = false
chapterLabel.centerXAnchor.constraintEqualToAnchor(
                view.centerXAnchor).active = true
chapterLabel.bottomAnchor.constraintEqualToAnchor(
                bookTextView.topAnchor).active = true

Here you set chapterLabel to use Auto Layout and constrained it to the center of the view. You also constrained chapterLabel‘s bottom to bookTextView‘s top.

Build and run the app; chapterLabel will be colored yellow:

auto layout

“But wait,” you protest. “I only set two constraints. You told me I had to set four.”

Yes, that is true. However, all views have an intrinsic content size. If that intrinsic content size is set, you don’t have to explicitly create layout constraints for Width and Height.

chapterLabel‘s intrinsic content size is set by the font and text used.

However, a standard UIView‘s intrinsic content width and height are set by default to UIViewNoIntrinsicMetric, which means that there is no size.

To demonstrate this, you’ll now change the constraints for avatarView. This is a subclass of UIView, so it has no default intrinsic content size. Just for fun, you’ll set avatarView to have an intrinsic content height of 100 instead of the current constant height of 200.

Remove the following constant constraint from setupConstraints():

avatarView.heightAnchor.constraintEqualToConstant(200).active = true

avatarView now has X Position, Y Position and Width constraints, but no Height constraint. If you were to run the app now, avatarView would not show on the screen at all, as it would have a zero height.

In AvatarView.swift, add the following method:

override func intrinsicContentSize() -> CGSize {
  return CGSize(width: UIViewNoIntrinsicMetric, height: 100)
}

This sets avatarView to have no intrinsic width, but to have an intrinsic height of 100.

The constraints now look like this:

auto layout

Build and run your app; you’ll see that the cyan-colored avatarView takes the height of 100 from its intrinsic content size:

auto layout

Note: If you ever need to change the intrinsic content size while the app is running, you can update it using invalidateIntrinsicContentSize().

In this case you really want chapterLabel to stay at its intrinsic height and avatarView to stretch so that it fills out the rest of the view, with a constant margin between them as in this diagram:

auto layout

First set the constant white space gap by adding the following to the end of setupConstraints() in ViewController.swift:

avatarView.bottomAnchor.constraintEqualToAnchor(
                chapterLabel.topAnchor,
                constant: -10).active = true

This will constrain avatarView‘s bottom anchor to be 10 pixels higher than the top of chapterLabel‘s top anchor.

Build and run the app:

auto layout

Uh oh. chapterLabel has stretched instead of avatarView!

You’ve set up constraints so that chapterLabel‘s top is anchored to avatarView‘s bottom and chapterLabel‘s bottom is anchored to the text view’s top. But when you don’t set an explicit constraint for Width and Height, the Auto Layout engine has to take intrinsic content size as a guide rather than a rule. In this situation it has given priority to avatarView‘s intrinsic size over chapterLabel‘s.

chapterLabel has consequently stretched vertically in a rather uncomfortable manner:

auto layout

There are two methods associated with intrinsic content size that give priorities to which views should stretch and compress.

setContentHuggingPriority(_:forAxis:) takes a priority and an axis to determine how much a view wants to stretch. A high priority means that a view wants to stay the same size. A low priority allows the view to stretch.

setContentCompressionResistancePriority(_:forAxis:) also takes a priority and an axis. This method determines how much a view wants to shrink. A high priority means that a view tries not to shrink and a low priority means that the view can squish.

Note: Priorities are values between 1 and 1000, where 1000 is the highest. The standard priorities are UILayoutPriorityRequired = 1000, UILayoutPriorityDefaultHigh = 750 and UILayoutPriorityDefaultLow = 250.

In this case you want chapterLabel to always have the correct height for the label and not stretch at all, so add the following to the bottom of setupConstraints():

chapterLabel.setContentHuggingPriority(
                  UILayoutPriorityRequired,
                  forAxis: .Vertical)
chapterLabel.setContentCompressionResistancePriority(
                  UILayoutPriorityRequired,
                  forAxis: .Vertical)

This sets chapterLabel‘s hugging priority and compression resistance as required for the vertical axis. The layout engine will therefore keep chapterLabel‘s intrinsic content height when it can.

Build and run the app again; you’ll see that avatarView stretches to fill the gap, which is exactly what you want:

auto layout

bookTextView didn’t shrink or stretch, because it has no intrinsic content size and all four constraints were explicitly set.

A Reusable Hierarchy in Code

Now you’ll work on avatarView. Just like a generic profile view, this view will have an image, title and social media icons. The views will adjust depending on whether the width is Compact or Regular.

This is how avatarView will look when completed:

auto layout

In AvatarView.swift all the subviews are set up and ready to go, so just add this code to the end of setup():

addSubview(imageView)
addSubview(titleLabel)
addSubview(socialMediaView)

Still in AvatarView, add a new method named setupConstraints():

func setupConstraints() {
  imageView.translatesAutoresizingMaskIntoConstraints = false
  titleLabel.translatesAutoresizingMaskIntoConstraints = false
  socialMediaView.translatesAutoresizingMaskIntoConstraints = false
}

Remember, you need to set translatesAutoresizingMaskIntoConstraints for every view you want to use with Auto Layout.

Call your new method at the end of willMoveToSuperview(_:) like so:

setupConstraints()

Build and run the app; the three subviews are there, sized to their intrinsic sizes, but not constrained to the correct positions:

auto layout

Note: The social media icons are courtesy of Vicki Wenderlich – you can purchase her art from Game Art Guppy.

Activate Arrays of Constraints

Setting each individual constraint’s active property as you have been doing so far is not as efficient as setting up all the constraints first and activating them all at once. So now you’ll set up the constraints for titleLabel, imageView and socialMediaView in this more efficient way.

You’ll add these constraints in code:

auto layout

Add the following code to the bottom of setupConstraints() in AvatarView.swift:

// 1
let labelBottom =
        titleLabel.bottomAnchor.constraintEqualToAnchor(bottomAnchor)
let labelCenterX = titleLabel.centerXAnchor.constraintEqualToAnchor(
      centerXAnchor)
 
// 2
let imageViewTop =
        imageView.topAnchor.constraintEqualToAnchor(topAnchor)
let imageViewBottom =
        imageView.bottomAnchor.constraintEqualToAnchor(
        titleLabel.topAnchor)
let imageViewCenterX =
    imageView.centerXAnchor.constraintEqualToAnchor(
      centerXAnchor)
 
// 3
let socialMediaTrailing =
    socialMediaView.trailingAnchor.constraintEqualToAnchor(trailingAnchor)
let socialMediaTop = socialMediaView.topAnchor.constraintEqualToAnchor(topAnchor)

Taking the above code step-by-step:

  1. You create two variables to hold titleLabel‘s constraints. The first will constrain titleLabel‘s bottom edge to avatarView‘s bottom and the second will center titleLabel in avatarView.
  2. Similarly, the next three variables hold imageView‘s constraints, with the top of imageView constrained to avatarView and the bottom of imageView to the top of titleLabel. imageView will be centered in avatarView.
  3. The last two variables hold constraints for socialMediaView to be right aligned and constrained to the top of avatarView.

For each of the views, you’ve created constraint variables but the constraints are not yet active.

To activate the constraints all at once, add the following to the end of setupConstraints():

NSLayoutConstraint.activateConstraints([
            imageViewTop, imageViewBottom, imageViewCenterX,
            labelBottom, labelCenterX,
            socialMediaTrailing, socialMediaTop])

The constraints are now activated in the array order.

As both imageView and titleLabel have intrinsic sizes, you’ll need to set imageView‘s compression resistance to ensure that imageView resizes in preference to titleLabel.

Add the code below to the end of setupConstraints():

imageView.setContentCompressionResistancePriority(
            UILayoutPriorityDefaultLow,
            forAxis: .Vertical)
imageView.setContentCompressionResistancePriority(
            UILayoutPriorityDefaultLow,
            forAxis: .Horizontal)

Here you set imageView‘s compression resistance priority to low for the vertical and horizontal axes.

Finally, change socialMediaView‘s axis to vertical like so:

socialMediaView.axis = .Vertical

Build and run on the iPhone 6s Plus and check out the app in portrait:

auto layout

This layout is looking pretty good. imageView and titleLabel are centered, and socialMediaView is right aligned and vertical.

Arrange Layouts by Size Class

You’ve now learned all the basics of easy Auto Layout. In this section you’ll put everything together and complete your reusable avatar view to be laid out entirely differently in different size classes:

auto layout

If the size class is Compact, you want imageView and titleLabel to be centered, and the social media icons should be right-aligned but laid out vertically, like this:

auto layout

If the size class is Regular, imageView and titleLabel should be left-aligned and the social media icons should still be right-aligned but laid out horizontally:

auto layout

Constraint Activation and Deactivation

Many of the constraints will need to be activated and deactivated, so you’ll now set up arrays of constraints, but only activate the array appropriate for the device size class.

To do this, you’ll first remove the constraints that will change for each size class, leaving only the constraints that will not change.

Still in AvatarView.swift, in setupConstraints() remove the following code:

let labelCenterX = titleLabel.centerXAnchor.constraintEqualToAnchor(
      centerXAnchor)

and

let imageViewCenterX =
    imageView.centerXAnchor.constraintEqualToAnchor(
      centerXAnchor)

and

let socialMediaTop = socialMediaView.topAnchor.constraintEqualToAnchor(topAnchor)

The constraints that remain are the top and bottom constraints for imageView and titleLabel and a trailing anchor so that socialMediaView will always be right-aligned.

Change the activation array to contain the constraints that you’ve set so far. Replace:

NSLayoutConstraint.activateConstraints([
            imageViewTop, imageViewBottom, imageViewCenterX,
            labelBottom, labelCenterX,
            socialMediaTrailing, socialMediaTop])

…with the following:

NSLayoutConstraint.activateConstraints([
            imageViewTop, imageViewBottom,
            labelBottom,
            socialMediaTrailing])

The constraints you’ve set up here for imageView, titleLabel and socialMediaView are the same for both Compact and Regular size classes. As the constraints won’t change, it’s OK to activate the constraints here.

In AvatarView, create two array properties to hold the constraints for the different size classes:

private var regularConstraints = [NSLayoutConstraint]()
private var compactConstraints = [NSLayoutConstraint]()

Add the code below to the end of setupConstraints() in AvatarView:

compactConstraints.append(
      imageView.centerXAnchor.constraintEqualToAnchor(centerXAnchor))
compactConstraints.append(
     titleLabel.centerXAnchor.constraintEqualToAnchor(centerXAnchor))
compactConstraints.append(
        socialMediaView.topAnchor.constraintEqualToAnchor(topAnchor))

Here you again set up the constraints that you removed, but these are now in an array that can be activated when the size class is Compact.

Add the following code to the end of setupConstraints():

regularConstraints.append(
      imageView.leadingAnchor.constraintEqualToAnchor(leadingAnchor))
regularConstraints.append(
      titleLabel.leadingAnchor.constraintEqualToAnchor(
          imageView.leadingAnchor))
regularConstraints.append(
      socialMediaView.bottomAnchor.constraintEqualToAnchor(bottomAnchor))

You’ve now set up, but not yet activated, the constraints that will be used when the device changes to the Regular size class.

Now for the activation of the constraint arrays.

The place to capture trait collection changes is in traitCollectionDidChange(_:), so you’ll override this method to activate and deactivate the constraints.

At the end of AvatarView, add the following method:

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
  super.traitCollectionDidChange(previousTraitCollection)
 
  // 1
  if traitCollection.horizontalSizeClass == .Regular {
    // 2
    NSLayoutConstraint.deactivateConstraints(compactConstraints)
    NSLayoutConstraint.activateConstraints(regularConstraints)
    // 3
    socialMediaView.axis = .Horizontal
  } else {
    // 4
    NSLayoutConstraint.deactivateConstraints(regularConstraints)
    NSLayoutConstraint.activateConstraints(compactConstraints)
    socialMediaView.axis = .Vertical
  }
}

Here you activate and deactivate the specific arrays for the specific size class.

Going through each numbered comment in turn:

  1. You set up a conditional that checks the size class.
  2. If the size class is Regular, you deactivate the constraints in the array for the Compact size class and activate the constraints for the Regular size class.
  3. You change the axis of socialMediaView to be horizontal for the Regular size.
  4. Similarly, you deactivate the Regular size class array and activate the Compact size class array and change the socialMediaView to be vertical for the Compact size.

Build and run on the iPhone 6s Plus, and rotate between portrait and landscape to see the final view positions:

auto layout

auto layout

Unfortunately, due to the image’s intrinsic content size, the image does not appear to be left-aligned in landscape. However, the image view has a magenta background, so you can see that it really is left-aligned. You’ll sort that out shortly.

The Constraint Update Cycle

auto layout

This diagram shows how views are drawn. There are three main passes with methods that you can override to update views or constraints once the system has calculated the layout:

  • All the constraints are calculated in updateConstraints(). This is where all priorities, compression resistance, hugging and intrinsic content size all come together in one complex algorithm. You can override this method to change constraints.
  • Views are then laid out in layoutSubviews(). If you need to access the correct view frame, you can override this.
  • Finally the view is drawn with drawRect(_:). You can override this method to draw the view’s content with Core Graphics or UIKit.

When the size class changes due to multitasking or device rotation, view layout updates are automatic, but you can trigger each part of the layout with the setNeeds...() methods listed on the left of the diagram.

Changing the layout of imageView is a good example of why you might need to recalculate the layout constraints.

Updating constraints

To fix the horizontal size of imageView, you’ll need to add an aspect ratio constraint. The height of imageView is calculated by the constraints you’ve already set up, and the width of the image view should be a percentage of that height.

To complicate matters, the constraint will have to be updated every time the user goes to a new chapter when the image is changed — the aspect ratio will be different for every image.

updateConstraints() executes whenever the constraint engine recalculates the layout, so this is a great place to put the code.

Create a new property in AvatarView to hold the aspect ratio constraint:

private var aspectRatioConstraint:NSLayoutConstraint?

Add the following method to AvatarView:

override func updateConstraints() {
  super.updateConstraints()
  // 1
  var aspectRatio: CGFloat = 1
  if let image = image {
    aspectRatio = image.size.width / image.size.height
  }
  // 2
  aspectRatioConstraint?.active = false
  aspectRatioConstraint =
        imageView.widthAnchor.constraintEqualToAnchor(
            imageView.heightAnchor,
            multiplier: aspectRatio)
  aspectRatioConstraint?.active = true
}

Taking this step-by-step:

  1. You calculate the correct aspect ratio for the image.
  2. Although it looks like you are changing the constraint here, you are actually creating a brand new constraint. You need to deactivate the old one so that you don’t keep adding new constraints to imageView. If you were wondering why you created a property to hold the aspect ratio constraint, it was simply so that you would have a handle to the constraint for this deactivation.

Build and run the app; notice that the image view is properly sized as you can’t see any magenta showing from behind the image:

auto layout

However, you’re not finished yet! Swipe to the left to load Chapter 2. Chapter 2’s image has a completely different aspect ratio, so the dreaded magenta bands appear:

auto layout

Whenever the image changes, you need a way of calling updateConstraints(). However, as noted in the diagram above, this is a method used in the Auto Layout engine calculations – which you should never call directly.

Instead, you need to call setNeedsUpdateConstraints(). This will mark the constraint layout as ‘dirty’ and the engine will recalculate the constraints in the next run loop by calling updateConstraints() for you.

Change the image property declaration at the top of AvatarView to the following:

var image: UIImage? {
  didSet {
    imageView.image = image
    setNeedsUpdateConstraints()
  }
}

As well as updating imageView‘s image, this now calls setNeedsUpdateConstraints() which means that whenever the image property is set, all constraints will be recalculated and updated.

Build and run, swipe left to Chapter 2 and your aspect ratio constraint should work perfectly:

auto layout

Note: If you hadn’t set imageView‘s horizontal compression resistance to ‘low’ earlier, the image would not have shrunk properly in the horizontal axis.

Laying Out Views Manually

Occasionally you’ll want to access a view’s frame. This can only safely be done in layoutSubviews() after all the views have been laid out by the Auto Layout engine.

If you run Wonderland on a smaller device such as the iPhone 4s or 5s, there are two problems. Firstly imageView in landscape is really tiny, and secondly socialMediaView is too large and draws over text.

auto layout

To fix this, you’ll check the size of imageView‘s frame and if it’s below a certain threshold, you’ll hide imageView. You’ll also check that socialMediaView fits within avatarView‘s bounds and if not hide socialMediaView.

Override layoutSubviews() in AvatarView:

override func layoutSubviews() {
  super.layoutSubviews()
  if bounds.height < socialMediaView.bounds.height {
    socialMediaView.alpha = 0
  } else {
    socialMediaView.alpha = 1
  }
  if imageView.bounds.height < 30 {
    imageView.alpha = 0
  } else {
    imageView.alpha = 1
  }
}

Here you set socialMediaView to be transparent if avatarView‘s height is less than socialMediaView‘s height. You also set imageView to be transparent if its height is less than 30 points. The image is too small to see at this size.

Build and run, and imageView is hidden if it’s too small and socialMediaView is hidden if it’s too big. This is an iPhone 4s:

auto layout

Cleaning Up

Congratulations! You’ve now finished Wonderland, so you can remove all the background colors.

In ViewController.swift, remove the following line from viewDidLoad():

colorViews()

In AvatarView.swift, remove the following lines from setup():

imageView.backgroundColor = UIColor.magentaColor()
titleLabel.backgroundColor = UIColor.orangeColor()

Make sure you run the app on various iPhone and iPad simulators in both portrait and landscape to see the resulting effect:

auto layout

Note: The best transformation happens when you run in landscape on the iPad Air 2 simulator. This allows for multitasking, so if you pull in another application by swiping at the right edge, your size class changes instantly from Regular to Compact. Neat!

Where to Go From Here?

You can download the final project here.

The best resource for understanding Auto Layout is Apple’s WWDC 2015 video Mysteries of Auto Layout 2.

The app demonstrated in that WWDC video is AstroLayout. Although this is in Objective-C, it is well documented. It describes layout guides and constraint animation with keyframes.

There’s a whole guide to Auto Layout here.

Finally, there’s the excellent Ray Wenderlich Auto Layout Video Series.

We hope you enjoyed this Auto Layout tutorial, and if you have any questions or comments, please join the forum discussion below!

The post Easier Auto Layout: Coding Constraints in iOS 9 appeared first on Ray Wenderlich.

Video Tutorial: Beginning Core Graphics Part 5: PaintCode

Video Tutorial: Beginning Core Graphics Part 6: Conclusion

Open Call For Applications: Apple Game Frameworks Authors and Tech Editors

$
0
0

OpenCall-AGF-feature

Do you like making games with any of Apple’s Game Frameworks, like Sprite Kit, Scene Kit, GameplayKit or Metal?

Have you read 2D iOS & tvOS Games by Tutorials or 3D iOS Games by Tutorials?

Do you think zombies are wildly fantastic?

If you answered yes to any of these questions, then you may have the makings of either an author or tech editor extraordinaire! But not just any author or tech editor — a Ray Wenderlich Apple Game Frameworks author or tech editor.

That’s right! We’re looking for great new authors and tech editors to join our team. Want to know more? Keep reading to find out what’s involved, and how to apply!

Note: This is not a full time job; these are part-time informal positions you can do in the evenings/weekends.

Why Join Our Team?

Here are the top 5 reasons to join the Apple Game Frameworks Tutorial Team:

  1. Learning. You’ll always be learning something new — and will have fun doing it! You’ll become a better developer, writer and person. The best part… you’ll make a lot of new friends along the way.
  2. Money! Get paid to learn! We offer the highest rates in the industry.
  3. Special Opportunities. Members of the Tutorial Team get access to special opportunities such as contributing to our books and products, speaking at our conference, being a guest on our podcast, working on team projects and much more.
  4. You’ll Make a Difference. We get emails every day about how our tutorials help our readers make their first app, get their dream job or accomplish a lifelong dream of making their own game. This means a lot to us, and makes all the hard work worth it!
  5. Free Stuff! And as a final bonus, by joining the Tutorial Team you’ll get a lot of free stuff! You’ll get a free copy of all of the products we sell on the site — over $1,000 in value!

Aww Yeah!

Requirements and How to Apply

Here are the requirements:

  • You must be an experienced SpriteKit, SceneKit, or Metal developer.
  • You should be a great writer with fluent English writing skills.
  • You should be comfortable learning brand new topics that you’ve never done before, which are either not documented or poorly documented.
  • You should have a strong work ethic — this will be a significant time commitment and is not easy.

To apply, send our Apple Game Frameworks Team Lead, Tammy Coron, an email (that’s me!). Be sure to include the following information:

  • Why do you want to be an Apple Game Frameworks author or tech editor?
  • Please tell me a little bit about yourself and your experience.
  • What is the best game you’ve made or worked on using Apple Game Frameworks, and why are you proud of the work you did on this game? [Please include link]
  • Please link to any examples of technical writing you’ve done in the past.
  • Please include links to: your GitHub account, your StackOverflow account and your Twitter account.

If you’re applying to be an author, you’ll be required to write a sample tutorial to gauge your writing skills. If you’re applying to be a tech editor, you’ll be given a tech editor tryout which will gauge your editing skills.

If you pass the tryout, you’re in!

Now’s The Time

Don’t sit on the sidelines waiting for the zombies to bite. Tryout for the team. Use your brain and share your knowledge!

Now what are you waiting for? Send me that email because the Apple Game Frameworks Team and I look forward to creating some great tutorials with you! :]

The post Open Call For Applications: Apple Game Frameworks Authors and Tech Editors appeared first on Ray Wenderlich.


Video Tutorial: Intermediate Core Graphics: Series Introduction

Video Tutorial: Intermediate Core Graphics Part 1: Gradients

How To Make a Game Like Space Invaders with Sprite Kit and Swift Tutorial: Part 1

$
0
0

SpaceInvaders-feature

Update 05/10/2016: Updated for Xcode 7.3 by Ryan Ackermann. Original tutorial by Joel Shapiro and previously updated by Riccardo d’Antoni.

Space Invaders is one of the most important video games ever developed. Created by Tomohiro Nishikado and released in 1978 by Taito Corporation, it earned billions of dollars in revenue. It became a cultural icon, inspiring legions of non-geeks to take up video games as a hobby.

In this tutorial, you’ll build an iOS version of Space Invaders, using Swift and Sprite Kit, Apple’s 2D game framework.

This tutorial assumes you are familiar with the basics of Swift and Sprite Kit. If you are completely new to Sprite Kit, you should go through our Sprite Kit tutorial for beginners first.

Also, you will need Xcode 7.3 or later, an iPhone or iPod Touch running iOS 9 and an Apple developer account in order to get the most out of this tutorial. That is because you will be moving the ship in this game using the accelerometer, which is not present on the iOS simulator. If you don’t have an iOS 9 device or developer account, you can still complete the tutorial — you just won’t be able to move your ship.

Without further ado, let’s get ready to blast some aliens!

An original Space Invaders arcade cabinet

An original Space Invaders arcade cabinet

Getting Started

Apple provides an template named Game which is pretty useful if you want to create your next smash hit from scratch. However, in order to get you started quickly, download the starter project for this tutorial. It’s based on the Sprite Kit Game template and already has some of the more tedious work done for you.

Once you’ve downloaded and unzipped the project, open the project in Xcode and build and run. After the splash screen intro, you should see the following screen appear on your device or your simulator:

space_invaders_first_run

Creepy – the invaders are watching you! However, if you see the screen above, this means you’re ready to get started.

Adding Colorful Invaders

All right, time to make some invaders! In this game, you’re going to create three types of invaders, so open GameScene.swift and add this enumeration inside the GameScene class, right after the line var contentCreated = false:

enum InvaderType {
  case A
  case B
  case C
 
  static var size: CGSize {
    return CGSize(width: 24, height: 16)
  }
 
  static var name: String {
    return "invader"
  }
}

Here you create an enumeration with three different cases, and a few helper properties to return the size of the invader sprite, and a description.

Next, add this new method directly after createContent():

func makeInvaderOfType(invaderType: InvaderType) -> SKNode {
  // 1
  var invaderColor: SKColor
 
  switch(invaderType) {
  case .A:
    invaderColor = SKColor.redColor()
  case .B:
    invaderColor = SKColor.greenColor()
  case .C:
    invaderColor = SKColor.blueColor()
  }
 
  // 2
  let invader = SKSpriteNode(color: invaderColor, size: InvaderType.size)
  invader.name = InvaderType.name
 
  return invader
}

You take the following actions in the above code:

  1. Use the invaderType parameter to determine the color of the invader.
  2. Call the handy convenience initializer SKSpriteNode(color:size:) to initialize a sprite that renders as a rectangle of the given color invaderColor with the enumeration’s size InvaderType.size.

Okay, so a colored block is not the most menacing enemy imaginable. It may be tempting to design invader sprite images and dream about all the cool ways you can animate them, but the best approach is to focus on the game logic first, and worry about aesthetics later.

Adding makeInvaderOfType() isn’t quite enough to display the invaders on the screen. You’ll need something to invoke this method and place the newly created sprites in the scene.

First, you’ll need a few constants. Add the following constants inside GameScene, right after the declaration of InvaderType:

let kInvaderGridSpacing = CGSize(width: 12, height: 12)
let kInvaderRowCount = 6
let kInvaderColCount = 6

These are some constants to represent how you’ll be laying out the invaders in this game – basically a 6×6 grid, with 12×12 point spacing in-between each invader.

Next add the following method directly after makeInvaderOfType():

func setupInvaders() {
  // 1
  let baseOrigin = CGPoint(x: size.width / 3, y: size.height / 2)
 
  for row in 0..<kInvaderRowCount {
    // 2
    var invaderType: InvaderType
 
    if row % 3 == 0 {
      invaderType = .A
    } else if row % 3 == 1 {
      invaderType = .B
    } else {
      invaderType = .C
    }
 
    // 3
    let invaderPositionY = CGFloat(row) * (InvaderType.size.height * 2) + baseOrigin.y
 
    var invaderPosition = CGPoint(x: baseOrigin.x, y: invaderPositionY)
 
    // 4
    for _ in 1..<kInvaderRowCount {
      // 5
      let invader = makeInvaderOfType(invaderType)
      invader.position = invaderPosition
 
      addChild(invader)
 
      invaderPosition = CGPoint(
        x: invaderPosition.x + InvaderType.size.width + kInvaderGridSpacing.width,
        y: invaderPositionY
      )
    }
  }
}

The above method lays out invaders in a grid of rows and columns. Each row contains only a single type of invader. The logic looks complicated, but if you break it down, it makes perfect sense:

  1. Declare and set the baseOrigin constant (representing the origin of where to start spawning areas – 1/3 from the right of the screen, and 1/2 from the bottom of the screen) and loop over the rows.
  2. Choose a single InvaderType for all invaders in this row based on the row number.
  3. Do some math to figure out where the first invader in this row should be positioned.
  4. Loop over the columns.
  5. Create an invader for the current row and column and add it to the scene.
  6. Update the invaderPosition so that it’s correct for the next invader.

Now, you just need to display the invaders on the screen. Replace the temporary invader setup code in createContent() with setupInvaders() just above the background color:

setupInvaders()

Build and run your app; you should see a bunch of invaders on the screen, as shown below:

space_invaders_added_color

The rectangular alien overlords are here! :]

Create Your Valiant Ship

With those evil invaders on screen, your mighty ship can’t be far behind. Just as you did for the invaders, you first need to define a few constants.

Add the following code immediately below the kInvaderColCount line:

let kShipSize = CGSize(width: 30, height: 16)
let kShipName = "ship"

kShipSize stores the size of the ship, and kShipName stores the name you will set on the sprite node, so you can easily look it up later.

Next, add the following two methods just after setupInvaders():

func setupShip() {
  // 1
  let ship = makeShip()
 
  // 2
  ship.position = CGPoint(x: size.width / 2.0, y: kShipSize.height / 2.0)
  addChild(ship)
}
 
func makeShip() -> SKNode {
  let ship = SKSpriteNode(color: SKColor.greenColor(), size: kShipSize)
  ship.name = kShipName
  return ship
}

Here’s the interesting bits of logic in the two methods above:

  1. Create a ship using makeShip(). You can easily reuse makeShip() later if you need to create another ship (e.g. if the current ship gets destroyed by an invader and the player has “lives” left).
  2. Place the ship on the screen. In Sprite Kit, the origin is at the lower left corner of the screen. The anchorPoint is based on a unit square with (0, 0) at the lower left of the sprite’s area and (1, 1) at its top right. Since SKSpriteNode has a default anchorPoint of (0.5, 0.5), i.e., its center, the ship’s position is the position of its center. Positioning the ship at kShipSize.height / 2.0 means that half of the ship’s height will protrude below its position and half above. If you check the math, you’ll see that the ship’s bottom aligns exactly with the bottom of the scene.

To display your ship on the screen, add the following line below setupInvaders() in createContent():

setupShip()

Build and run your app; and you should see your ship arrive on the scene, as below:

space_invaders_added_player

Fear not, citizens of Earth! Your trusty spaceship is here to save the day!

Adding the Heads Up Display (HUD)

It wouldn’t be much fun to play Space Invaders if you didn’t keep score, would it? You’re going to add a heads-up display (or HUD) to your game. As a star pilot defending Earth, your performance is being monitored by your commanding officers. They’re interested in both your “kills” (score) and “battle readiness” (health).

Add the following constants at the top of GameScene.swift, just below kShipName:

let kScoreHudName = "scoreHud"
let kHealthHudName = "healthHud"

Now, add your HUD by inserting the following method right after makeShip():

func setupHud() {
  // 1
  let scoreLabel = SKLabelNode(fontNamed: "Courier")
  scoreLabel.name = kScoreHudName
  scoreLabel.fontSize = 25
 
  // 2
  scoreLabel.fontColor = SKColor.greenColor()
  scoreLabel.text = String(format: "Score: %04u", 0)
 
  // 3
  scoreLabel.position = CGPoint(
    x: frame.size.width / 2,
    y: size.height - (40 + scoreLabel.frame.size.height/2)
  )
  addChild(scoreLabel)
 
  // 4
  let healthLabel = SKLabelNode(fontNamed: "Courier")
  healthLabel.name = kHealthHudName
  healthLabel.fontSize = 25
 
  // 5
  healthLabel.fontColor = SKColor.redColor()
  healthLabel.text = String(format: "Health: %.1f%%", 100.0)
 
  // 6
  healthLabel.position = CGPoint(
    x: frame.size.width / 2,
    y: size.height - (80 + healthLabel.frame.size.height/2)
  )
  addChild(healthLabel)
}

This is boilerplate code for creating and adding text labels to a scene. The relevant bits are as follows:

  1. Give the score label a name so you can find it later when you need to update the displayed score.
  2. Color the score label green.
  3. Position the score label.
  4. Give the health label a name so you can reference it later when you need to update the displayed health.
  5. Color the health label red; the red and green indicators are common colors for these indicators in games, and they’re easy to differentiate in the middle of furious gameplay.
  6. Position the health below the score label.

Add the following line below setupShip() in createContent() to call the setup method for your HUD:

setupHud()

Build and run your app; you should see the HUD in all of its red and green glory on your screen as shown below:

space_invaders_hud

Invaders? Check. Ship? Check. HUD? Check. Now all you need is a little dynamic action to tie it all together!

Adding Motion to the Invaders

To render your game onto the screen, Sprite Kit uses a game loop which searches endlessly for state changes that require on-screen elements to be updated. The game loop does several things, but you’ll be interested in the mechanisms that update your scene. You do this by overriding the update() method, which you’ll find as a stub in your GameScene.swift file.

When your game is running smoothly and renders 60 frames-per-second (iOS devices are hardware-locked to a max of 60 fps), update() will be called 60 times per second. This is where you modify the state of your scene, such as altering scores, removing dead invader sprites, or moving your ship around…

You’ll use update() to make your invaders move across and down the screen. Each time Sprite Kit invokes update(), it’s asking you “Did your scene change?”, “Did your scene change?”… It’s your job to answer that question — and you’ll write some code to do just that.

Insert the following code at the top of GameScene.swift, just above the definition of the InvaderType enum:

enum InvaderMovementDirection {
  case Right
  case Left
  case DownThenRight
  case DownThenLeft
  case None
}

Invaders move in a fixed pattern: right, right, down, left, left, down, right, right, … so you’ll use the InvaderMovementDirection type to track the invaders’ progress through this pattern. For example, InvaderMovementDirection.Right means the invaders are in the right, right portion of their pattern.

Next, insert the following properties just below the existing property for contentCreated:

// 1
var invaderMovementDirection: InvaderMovementDirection = .Right
// 2
var timeOfLastMove: CFTimeInterval = 0.0
// 3
let timePerMove: CFTimeInterval = 1.0

This setup code initializes invader movement as follows:

  1. Invaders begin by moving to the right.
  2. Invaders haven’t moved yet, so set the time to zero.
  3. Invaders take 1 second for each move. Each step left, right or down takes 1 second.

Now, you’re ready to make the invaders move. Add the following code just below // Scene Update:

func moveInvadersForUpdate(currentTime: CFTimeInterval) {
  // 1
  if (currentTime - timeOfLastMove < timePerMove) {
    return
  }
 
  // 2
  enumerateChildNodesWithName(InvaderType.name) {
    node, stop in
 
    switch self.invaderMovementDirection {
    case .Right:
      node.position = CGPointMake(node.position.x + 10, node.position.y)
    case .Left:
      node.position = CGPointMake(node.position.x - 10, node.position.y)
    case .DownThenLeft, .DownThenRight:
      node.position = CGPointMake(node.position.x, node.position.y - 10)
    case .None:
      break
    }
 
    // 3
    self.timeOfLastMove = currentTime
  }
}

Here’s a breakdown of the code above, comment by comment:

  1. If it’s not yet time to move, then exit the method. moveInvadersForUpdate() is invoked 60 times per second, but you don’t want the invaders to move that often since the movement would be too fast for a normal person to see.
  2. Recall that your scene holds all of the invaders as child nodes; you added them to the scene using addChild() in setupInvaders() identifying each invader by its name property. Invoking enumerateChildNodesWithName() only loops over the invaders because they’re named kInvaderName; this makes the loop skip your ship and the HUDs. The guts of the block moves the invaders 10 pixels either right, left or down depending on the value of invaderMovementDirection.
  3. Record that you just moved the invaders, so that the next time this method is invoked (1/60th of a second from now), the invaders won’t move again till the set time period of one second has elapsed.

To make your invaders move, add the following to update():

moveInvadersForUpdate(currentTime)

Build and run your app; you should see your invaders slowly walk their way to the right:

space_invaders_movement

Hmmm, what happened? Why did the invaders disappear? Maybe the invaders aren’t as menacing as you thought!

The invaders don’t yet know that they need to move down and change their direction once they hit the side of the playing field. Guess you’ll need to help those invaders find their way!

Controlling the Invaders’ Direction

Adding the following code just after // Invader Movement Helpers:

func determineInvaderMovementDirection() {
  // 1
  var proposedMovementDirection: InvaderMovementDirection = invaderMovementDirection
 
  // 2
  enumerateChildNodesWithName(InvaderType.name) {
    node, stop in
 
    switch self.invaderMovementDirection {
    case .Right:
      //3
      if (CGRectGetMaxX(node.frame) >= node.scene!.size.width - 1.0) {
        proposedMovementDirection = .DownThenLeft
 
        stop.memory = true
      }
    case .Left:
      //4
      if (CGRectGetMinX(node.frame) <= 1.0) {
        proposedMovementDirection = .DownThenRight
 
        stop.memory = true
      }
 
    case .DownThenLeft:
      proposedMovementDirection = .Left
 
      stop.memory = true
 
    case .DownThenRight:
      proposedMovementDirection = .Right
 
      stop.memory = true
 
    default:
      break
    }
 
  }
 
  //7
  if (proposedMovementDirection != invaderMovementDirection) {
    invaderMovementDirection = proposedMovementDirection
  }
}

Here’s what’s going on in the above code:

  1. Here you keep a reference to the current invaderMovementDirection so that you can modify it in //2.
  2. Loop over all the invaders in the scene and invoke the block with the invader as an argument.
  3. If the invader’s right edge is within 1 point of the right edge of the scene, it’s about to move offscreen. Set proposedMovementDirection so that the invaders move down then left. You compare the invader’s frame (the frame that contains its content in the scene’s coordinate system) with the scene width. Since the scene has an anchorPoint of (0, 0) by default, and is scaled to fill its parent view, this comparison ensures you’re testing against the view’s edges.
  4. If the invader’s left edge is within 1 point of the left edge of the scene, it’s about to move offscreen. Set proposedMovementDirection so that invaders move down then right.
  5. If invaders are moving down then left, they’ve already moved down at this point, so they should now move left. How this works will become more obvious when you integrate determineInvaderMovementDirection with moveInvadersForUpdate().
  6. If the invaders are moving down then right, they’ve already moved down at this point, so they should now move right.
  7. If the proposed invader movement direction is different than the current invader movement direction, update the current direction to the proposed direction.

Add the following code within moveInvadersForUpdate(), immediately after the conditional check of timeOfLastMove:

determineInvaderMovementDirection()

Why is it important that you add the invocation of determineInvaderMovementDirection() only after the check on timeOfLastMove? That’s because you want the invader movement direction to change only when the invaders are actually moving. Invaders only move when the check on timeOfLastMove passes — i.e., the conditional expression is true.

What would happen if you added the new line of code above as the very first line of code in moveInvadersForUpdate(currentTime: CFTimeInterval)? If you did that, then there would be two bugs:

  • You’d be trying to update the movement direction way too often — 60 times per second — when you know it can only change at most once per second.
  • The invaders would never move down, as the state transition from DownThenLeft to Left would occur without an invader movement in between. The next invocation of moveInvadersForUpdate() that passed the check on timeOfLastMove would be executed with Left and would keep moving the invaders left, skipping the down move. A similar bug would exist for DownThenRight and Right.

Build and run your app; you’ll see the invaders moving as expected across and down the screen:

space_invaders_invader_direction

Note: You might have noticed that the invaders’ movement is jerky. That’s a consequence of your code only moving invaders once per second — and moving them a decent distance at that. But the movement in the original game was jerky, so keeping this feature helps your game seem more authentic.

Controlling Ship Movements with Device Motion

You might be familiar with UIAccelerometer, which has been available since iOS 2.0 for detecting device tilt. However, UIAccelerometer was deprecated in iOS 5.0, so iOS 9 apps should use CMMotionManager, which is part of Apple’s CoreMotion framework.

The CoreMotion library has already been added to the starter project, so there’s no need for you to add it.

Your code can retrieve accelerometer data from CMMotionManager in two different ways:

  1. Pushing accelerometer data to your code: In this scenario, you provide CMMotionManager with a block that it calls regularly with accelerometer data. This doesn’t fit well with your scene’s update() method that ticks at regular intervals of 1/60th of a second. You only want to sample accelerometer data during those ticks — and those ticks likely won’t line up with the moment that CMMotionManager decides to push data to your code.
  2. Pulling accelerometer data from your code: In this scenario, you call CMMotionManager and ask it for data when you need it. Placing these calls inside your scene’s update() method aligns nicely with the ticks of your system. You’ll be sampling accelerometer data 60 times per second, so there’s no need to worry about lag.

Your app should only use a single instance of CMMotionManager to ensure you get the most reliable data. To that effect, declare and initialize the following property at the top of GameScene:

let motionManager: CMMotionManager = CMMotionManager()

Now, add the following code to didMoveToView(), right after the contentCreated = true line:

motionManager.startAccelerometerUpdates()

This new code kicks off the production of accelerometer data. At this point, you can use the motion manager and its accelerometer data to control your ship’s movement.

Add the following method just below moveInvadersForUpdate():

func processUserMotionForUpdate(currentTime: CFTimeInterval) {
  // 1
  if let ship = childNodeWithName(kShipName) as? SKSpriteNode {
    // 2
    if let data = motionManager.accelerometerData {
      // 3
      if fabs(data.acceleration.x) > 0.2 {
        // 4 How do you move the ship?
        print("Acceleration: \(data.acceleration.x)")
      }
    }
  }
}

Dissecting this method, you’ll find the following:

  1. Get the ship from the scene so you can move it.
  2. Get the accelerometer data from the motion manager. It is an Optional, that is a variable that can hold either a value or no value. The if let data statement allows to check if there is a value in accelerometerData, if is the case assign it to the constant data in order to use it safely within the if’s scope.
  3. If your device is oriented with the screen facing up and the home button at the bottom, then tilting the device to the right produces data.acceleration.x > 0, whereas tilting it to the left produces data.acceleration.x < 0. The check against 0.2 means that the device will be considered perfectly flat/no thrust (technically data.acceleration.x == 0) as long as it's close enough to zero (data.acceleration.x in the range [-0.2, 0.2]). There's nothing special about 0.2, it just seemed to work well for me. Little tricks like this will make your control system more reliable and less frustrating for users.
  4. Hmmm, how do you actually use data.acceleration.x to move the ship? You want small values to move the ship a little and large values to move the ship a lot. For now, you just print out the acceleration value.

Finally, add the following line to the top of update():

processUserMotionForUpdate(currentTime)

Your new processUserMotionForUpdate now gets called 60 times per second as the scene updates.

Build and run - but this time, be sure that you run on a physical device like an iPhone. You won't be able to test the tilt code unless you are running the game on an actual device.

As you tilt your device, the ship won't move - however you will see some print statements in your console log like this:

Acceleration: 0.280059814453125
Acceleration: 0.255386352539062
Acceleration: 0.227584838867188
Acceleration: -0.201553344726562
Acceleration: -0.2618408203125
Acceleration: -0.280426025390625
Acceleration: -0.28662109375

Here you can see the acceleration changing as you tilt the device back and forth. Next, let's use this value to make the ship move - through the power of Sprite Kit physics!

Translating Motion Controls into Movement via Physics

Sprite Kit has a powerful built-in physics system based on Box 2D that can simulate a wide range of physics like forces, translation, rotation, collisions, and contact detection. Each SKNode, and thus each SKScene and SKSpriteNode, has an SKPhysicsBody attached to it. This SKPhysicsBody represents the node in the physics simulation.

Add the following code right before the final return ship line in makeShip():

// 1
ship.physicsBody = SKPhysicsBody(rectangleOfSize: ship.frame.size)
 
// 2
ship.physicsBody!.dynamic = true
 
// 3
ship.physicsBody!.affectedByGravity = false
 
// 4
ship.physicsBody!.mass = 0.02

Taking each comment in turn, you'll see the following:

  1. Create a rectangular physics body the same size as the ship.
  2. Make the shape dynamic; this makes it subject to things such as collisions and other outside forces.
  3. You don't want the ship to drop off the bottom of the screen, so you indicate that it's not affected by gravity.
  4. Give the ship an arbitrary mass so that its movement feels natural.

Now replace the println statement in processUserMotionForUpdate (right after comment // 4) with the following:

ship.physicsBody!.applyForce(CGVectorMake(40.0 * CGFloat(data.acceleration.x), 0))

The new code applies a force to the ship's physics body in the same direction as data.acceleration.x. The number 40.0 is an arbitrary value to make the ship's motion feel natural.

Build and run your game and try tilting your device left or right; Your ship will fly off the side of the screen, lost in the deep, dark reaches of space. If you tilt hard and long enough in the opposite direction, you might get your ship to come flying back the other way. But at present, the controls are way too flaky and sensitive. You'll never kill any invaders like this!

An easy and reliable way to prevent things from escaping the bounds of your screen during a physics simulation is to build what's called an edge loop around the boundary of your screen. An edge loop is a physics body that has no volume or mass but can still collide with your ship. Think of it as an infinitely-thin wall around your scene.

Since your GameScene is a kind of SKNode, you can give it its own physics body to create the edge loop.

Add the following code to createContent() right before the setupInvaders() line:

physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)

The new code adds the physics body to your scene.

Build and run your game once more and try tilting your device to move your ship, as below:

space_invaders_player_movement

What do you see? If you tilt your device far enough to one side, your ship will collide with the edge of the screen. It no longer flies off the edge of the screen. Problem solved!

Depending on the ship's momentum,you may also see the ship bouncing off the edge of the screen, instead of just stopping there. This is an added bonus that comes for free from Sprite Kit's physics engine — it's a property called restitution. Not only does it look cool, but it is what's known as an affordance since bouncing the ship back towards the center of the screen clearly communicates to the user that the edge of the screen is a boundary that cannot be crossed.

Where to Go From Here?

Here is the example project for the game up to this point.

So far, you've created invaders, your ship, and a Heads Up Display (HUD) and drawn them on-screen. You've also coded logic to make the invaders move automatically and to make your ship move as you tilt your device.

In part two of this tutorial, you'll add firing actions to your ship as well as the invaders, along with some collision detection so you'll know when you've hit the invaders — and vice versa! You'll also polish your game by adding both sound effects as well as realistic images to replace the colored rectangles that currently serve as placeholders for invaders and your ship.

In the meantime, if you have any questions or comments, please feel free to join in the discussions below!

The post How To Make a Game Like Space Invaders with Sprite Kit and Swift Tutorial: Part 1 appeared first on Ray Wenderlich.

How To Make a Game Like Space Invaders with Sprite Kit and Swift Tutorial: Part 2

$
0
0

SpaceInvaders-feature

Update 05/10/2016: Updated for Xcode 7.3 by Ryan Ackermann. Original tutorial by Joel Shapiro and previously updated by Riccardo d’Antoni.

Welcome back to our 2-part Sprite Kit tutorial that teaches you how to make a game like Space Invaders!

In the first part, you created the foundation of the game. So far, you’ve added the invaders, your ship, and a Heads Up Display (HUD) to your game. You also coded the logic to make the invaders move automatically and to make your ship move as you tilted your device.

In this second and final part, you’ll add the ability for your ship and the aliens to fire on each other and blow each other up! You’ll also polish your game by adding sound effects and realistic images to replace the colored rectangles that currently serve as place holders for the invaders and your ship.

This tutorial picks up where the first part left off. If you don’t have the project already, you can download the example project where you left things off.

All right, it’s time to blow up some invaders!

Making Your Ship Fire its Laser Cannon

You will be detecting taps in the scene’s touchesEnded() method. The question is what should you do inside that method?

Taps can happen at any point during the gameplay. Contrast that with the way your scene changes: — at discrete intervals from within the update() method. So how can you save up taps detected at any time in touchesEnded() and process them later in update() when it’s invoked by the Sprite Kit game loop?

The answer is a queue! You’re going to use a simple Array to store your taps in a FIFO (First In First Out) queue.

Add the following property at the top of GameScene.swift in order to initializes the tap queue to an empty array:

var tapQueue = [Int]()

Next find the // User Tap Helpers comment and add the following method inside:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
  if let touch = touches.first {
    if (touch.tapCount == 1) {
      tapQueue.append(1)
    }
  }
}

The touchesEnded() method itself is fairly simple. It just adds an entry to the queue. You don’t need a custom class to store the tap in the queue since all you need to know is that a tap occurred. Therefore, you use the integer 1 as a mnemonic for single tap.

Since you know that the invaders will also eventually fire bullets at your ship, add the following enum to the top of the class:

enum BulletType {
  case ShipFired
  case InvaderFired
}

You’re going to use BulletType to share the same bullet code for both invaders and your ship. It appears that you and the invaders shop at the same ammunition stores! :]

Next, add the following properties:

let kShipFiredBulletName = "shipFiredBullet"
let kInvaderFiredBulletName = "invaderFiredBullet"
let kBulletSize = CGSize(width:4, height: 8)

Now, add the following method at the end of the “Scene Setup and Content Creation” section:

func makeBulletOfType(bulletType: BulletType) -> SKNode {
  var bullet: SKNode
 
  switch bulletType {
  case .ShipFired:
    bullet = SKSpriteNode(color: SKColor.greenColor(), size: kBulletSize)
    bullet.name = kShipFiredBulletName
  case .InvaderFired:
    bullet = SKSpriteNode(color: SKColor.magentaColor(), size: kBulletSize)
    bullet.name = kInvaderFiredBulletName
    break
  }
 
  return bullet
}

This method is relatively straightforward: it simply creates a rectangular colored sprite to represent a bullet and sets the name of the bullet so you can find it later in your scene.

Now, add the following methods inside the “Bullet Helpers” section:

func fireBullet(bullet: SKNode, toDestination destination: CGPoint, withDuration duration: CFTimeInterval, andSoundFileName soundName: String) {
  // 1
  let bulletAction = SKAction.sequence([
    SKAction.moveTo(destination, duration: duration),
    SKAction.waitForDuration(3.0 / 60.0), SKAction.removeFromParent()
  ])
 
  // 2
  let soundAction = SKAction.playSoundFileNamed(soundName, waitForCompletion: true)
 
  // 3
  bullet.runAction(SKAction.group([bulletAction, soundAction]))
 
  // 4
  addChild(bullet)
}
 
func fireShipBullets() {
  let existingBullet = childNodeWithName(kShipFiredBulletName)
 
  // 1
  if existingBullet == nil {
    if let ship = childNodeWithName(kShipName) {
      let bullet = makeBulletOfType(.ShipFired)
        // 2
        bullet.position = CGPoint(
          x: ship.position.x,
          y: ship.position.y + ship.frame.size.height - bullet.frame.size.height / 2
      )
      // 3
      let bulletDestination = CGPoint(
        x: ship.position.x,
        y: frame.size.height + bullet.frame.size.height / 2
      )
      // 4
      fireBullet(bullet, toDestination: bulletDestination, withDuration: 1.0, andSoundFileName: "ShipBullet.wav")
    }
  }
}

Going through the code in fireBullet() step-by-step, you do the following:

  1. Create an SKAction that moves the bullet to the desired destination and then removes it from the scene. This sequence executes the individual actions consecutively — the next action only takes place after the previous action has completed. Hence the bullet is removed from the scene only after it has been moved.
  2. Play the desired sound to signal that the bullet was fired. All sounds are included in the starter project and iOS knows how to find and load them.
  3. Move the bullet and play the sound at the same time by putting them in the same group. A group runs its actions in parallel, not sequentially.
  4. Fire the bullet by adding it to the scene. This makes it appear onscreen and starts the actions.

Here’s what you do in fireShipBullets():

  1. Only fire a bullet if there isn’t one currently on-screen. It’s a laser cannon, not a laser machine gun — it takes time to reload!
  2. Set the bullet’s position so that it comes out of the top of the ship.
  3. Set the bullet’s destination to be just off the top of the screen. Since the x coordinate is the same as that of the bullet’s position, the bullet will fly straight up.
  4. Fire the bullet!

Your laser cannon is almost ready to fire!

Add the following to the “Scene Update Helpers” section:

func processUserTapsForUpdate(currentTime: CFTimeInterval) {
  // 1
  for tapCount in tapQueue {
    if tapCount == 1 {
      // 2
      fireShipBullets()
    }
    // 3
    tapQueue.removeAtIndex(0)
  }
}

Let’s review the above code:

  1. Loop over your tapQueue.
  2. If the queue entry is a single-tap, handle it. As the developer, you clearly know that you only handle single taps for now, but it’s best to be defensive against the possibility of double-taps (or other actions) later.
  3. Remove the tap from the queue.

Note: processUserTapsForUpdate() completely consumes the queue of taps at each invocation. Combined with the fact that fireShipBullets() will not fire another bullet if one is already onscreen, this emptying of the queue means that extra or rapid-fire taps will be ignored. Only the first tap needed to fire a bullet will matter.

Finally, add the following code as the first line in update():

processUserTapsForUpdate(currentTime)

This invokes processUserTapsForUpdate() during the update loop and processes any user taps.

Build your game, run, and fire away!

space_invaders_first_shot

Making Invaders Attack

Awesome, your ship can finally fire on those evil invaders! You’ll have them on the run soon enough.

But you’ve probably noticed that your bullets pass straight through invaders instead of blowing them up. That’s because your bullets aren’t yet smart enough to detect when they’ve hit an invader. You’re going to fix that in a moment.

First, you’ll make the invaders return fire by adding the code below to the // Scene Update section:

func fireInvaderBulletsForUpdate(currentTime: CFTimeInterval) {
  let existingBullet = childNodeWithName(kInvaderFiredBulletName)
 
  // 1
  if existingBullet == nil {
    var allInvaders = Array<SKNode>()
 
    // 2
    enumerateChildNodesWithName(InvaderType.name) {
      node, stop in
 
      allInvaders.append(node)
    }
 
    if allInvaders.count > 0 {
      // 3
      let allInvadersIndex = Int(arc4random_uniform(UInt32(allInvaders.count)))
 
      let invader = allInvaders[allInvadersIndex]
 
      // 4
      let bullet = makeBulletOfType(.InvaderFired)
      bullet.position = CGPoint(
        x: invader.position.x,
        y: invader.position.y - invader.frame.size.height / 2 + bullet.frame.size.height / 2
      )
 
      // 5
      let bulletDestination = CGPoint(x: invader.position.x, y: -(bullet.frame.size.height / 2))
 
      // 6
      fireBullet(bullet, toDestination: bulletDestination, withDuration: 2.0, andSoundFileName: "InvaderBullet.wav")
    }
  }
}

The central logic for the above method is as follows:

  1. Only fire a bullet if one’s not already on-screen.
  2. Collect all the invaders currently on-screen.
  3. Select an invader at random.
  4. Create a bullet and fire it from just below the selected invader.
  5. The bullet should travel straight down and move just off the bottom of the screen.
  6. Fire off the invader’s bullet.

Add the following line to the end of update():

fireInvaderBulletsForUpdate(currentTime)

This invocation of fireInvaderBulletsForUpdate() starts the invaders firing back at you.

Build, run, and you should see the invaders firing their purple bullets at your ship, as shown in the screenshot below:

space_invaders_firing_back

As a matter of game design, notice that the invaders’ bullets are purple while your ship’s bullets are green. This strong color contrast makes it easy to see the difference between bullets in the heat of battle. Also, you should hear a different sound when your ship fires versus when an invader fires.

Detecting When Bullets Hit Their Target

With all those bullets flying around on the screen it’s amazing that nothing blows up! That’s because your game has no hit detection. It needs to detect when your ship’s bullets hit an invader — and when an invader’s bullet hits your ship.

Since you’re already using physics bodies, Sprite Kit’s physics engine can detect when one body hits another. For this, you’ll use contact detection — not collision detection. You’re not using physics to move bullets or invaders, so you’re not interested in the physical collisions between them. Contact detection merely detects when one physics body overlaps another in space; it doesn’t otherwise move or affect the bodies in contact.

This is both a speed optimization and a correctness constraint, as some types of contact may not be desired. Controlling which physics bodies are checked for contact begins by defining category bitmasks.

Add the following new properties to GameScene:

let kInvaderCategory: UInt32 = 0x1 << 0
let kShipFiredBulletCategory: UInt32 = 0x1 << 1
let kShipCategory: UInt32 = 0x1 << 2
let kSceneEdgeCategory: UInt32 = 0x1 << 3
let kInvaderFiredBulletCategory: UInt32 = 0x1 << 4

These strange-looking constants are bitmasks. A bitmask is basically a way of stuffing multiple on/off variables into a single 32-bit unsigned integer. A bitmask can have 32 distinct values when stored as a UInt32. Each of these five categories defines a type of physics body. Notice how the number to the right of the << operator is different in each case; that guarantees each bitmask is unique and distinguishable from the others.

Add the following code to createContent() right after the line that creates the physics body:

physicsBody!.categoryBitMask = kSceneEdgeCategory

This new code sets the category for the physics body of your scene.

Add the following code to makeShip() right before the return ship line to set up the categories for your ship:

// 1
ship.physicsBody!.categoryBitMask = kShipCategory
// 2
ship.physicsBody!.contactTestBitMask = 0x0
// 3
ship.physicsBody!.collisionBitMask = kSceneEdgeCategory

Here's the breakdown of the above code:

  1. Set the ship's category.
  2. Don't detect contact between the ship and other physics bodies.
  3. Do detect collisions between the ship and the scene's outer edges.

Since you'll be adding physics bodies to invaders next, setting your ship's collisionBitMask precisely ensures that your ship will only collide with the sides of the scene and won't also collide with invaders.

While you're at it, you should set the category for the invaders since this will help detect collisions between your ship's bullets and the invaders.

Add the following to the end of makeInvaderOfType() right before the return invader line:

invader.physicsBody = SKPhysicsBody(rectangleOfSize: invader.frame.size)
invader.physicsBody!.dynamic = false
invader.physicsBody!.categoryBitMask = kInvaderCategory
invader.physicsBody!.contactTestBitMask = 0x0
invader.physicsBody!.collisionBitMask = 0x0

This code gives your invader a physics body and identifies it as an invader using kInvaderCategory. It also indicates that you don't want invaders to contact or collide with other entities.

Your next step is to categorize bullets and set their contact and collision masks.

Add the following inside the case .ShipFired clause of makeBulletOfType():

bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody!.dynamic = true
bullet.physicsBody!.affectedByGravity = false
bullet.physicsBody!.categoryBitMask = kShipFiredBulletCategory
bullet.physicsBody!.contactTestBitMask = kInvaderCategory
bullet.physicsBody!.collisionBitMask = 0x0

The above code identifies ship-fired bullets as such and tells Sprite Kit to check for contact between ship-fired bullets and invaders, but that collisions should be ignored.

That takes care of the ship's bullets — now on to the invaders' bullets!

Add the following inside the case .InvaderFired clause of makeBulletOfType():

bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody!.dynamic = true
bullet.physicsBody!.affectedByGravity = false
bullet.physicsBody!.categoryBitMask = kInvaderFiredBulletCategory
bullet.physicsBody!.contactTestBitMask = kShipCategory
bullet.physicsBody!.collisionBitMask = 0x0

This code is similar to the previous block: it identifies invader-fired bullets as such and tells Sprite Kit to check for contact between invader-fired bullets and your ship, and again, ignores the collision aspect.

Note: In order for contact detection to work, the ship-fired bullets must be defined as dynamic by setting bullet.physicsBody.dynamic = true. If not, Sprite Kit won't check for contact between these bullets and the static invaders as their definition is invader.physicsBody.dynamic = false.

Invaders are static because they aren't moved by the physics engine. Sprite Kit won't check for contact between two static bodies, so if you need to check for contact between two categories of physics bodies, at least one of the categories must have a dynamic physics body.

You may be wondering why the contactTestBitMask values are not symmetrical. For example, why are you setting an invader's contactTestBitMastk = 0x0 but a ship-fired bullet's contactTestBitMask = kInvaderCategory?

The reason is that when Sprite Kit checks for contact between any two physics bodies A and B, only one of the bodies needs to declare that it should test for contact with the other, not both. As long as either A declares that it can contact with B, or B declares that it can contact with A, contact will be detected. It's not necessary for both bodies to declare that they should test for contact with the other.

Setting the contactTestBitMask on only one type of body like you've done seems more manageable. You might prefer to set contactTestBitMask values on both types of bodies, and that's fine, as long as you're consistent in choosing one approach or the other.

With these changes, your game's physics engine will detect contact between ship-fired bullets and the invaders, and between invader-fired bullets and your ship. But how does the physics engine inform your game of these contacts?

The answer is to use SKPhysicsContactDelegate.

Implementing the Physics Contact Delegate Methods

Still in GameScene.swift, modify the class line to look like the following:

class GameScene: SKScene, SKPhysicsContactDelegate {

This declares your scene as a delegate for the physics engine. The didBeginContact() method of SKPhysicsContactDelegate executes each time two physics bodies make contact, based on how you set your physics bodies' categoryBitMask and contactTestBitMask. You'll implement didBeginContact in just a moment.

Much like taps, contact can happen at any time. Consequently, didBeginContact can execute at any time. But in keeping with your discrete time ticks, you should only process contact during those ticks when update is called. So, just like taps, you'll create a queue to store contacts until they can be processed via update.

Add the following new property at the top of the class:

var contactQueue = [SKPhysicsContact]()

Now add the following code to the end of didMoveToView():

physicsWorld.contactDelegate = self

This just initializes an empty contact queue and sets the scene as the contact delegate of the physics engine.

Next, add this method below touchesEnded() in the "Physics Contact Helpers" section:

func didBeginContact(contact: SKPhysicsContact) {
  contactQueue.append(contact)
}

This method simply records the contact in your contact queue to handle later when update() executes.

Below didBeginContact(), add the following method:

func handleContact(contact: SKPhysicsContact) {
  //1
  // Ensure you haven't already handled this contact and removed its nodes
  if contact.bodyA.node?.parent == nil || contact.bodyB.node?.parent == nil {
    return
  }
 
  let nodeNames = [contact.bodyA.node!.name!, contact.bodyB.node!.name!]
 
  // 2
  if nodeNames.contains(kShipName) && nodeNames.contains(kInvaderFiredBulletName) {
 
    // 3
    // Invader bullet hit a ship
    self.runAction(SKAction.playSoundFileNamed("ShipHit.wav", waitForCompletion: false))
 
    contact.bodyA.node!.removeFromParent()
    contact.bodyB.node!.removeFromParent()
 
 
  } else if nodeNames.contains(InvaderType.name) && nodeNames.contains(kShipFiredBulletName) {
 
    // 4
    // Ship bullet hit an invader
    self.runAction(SKAction.playSoundFileNamed("InvaderHit.wav", waitForCompletion: false))
    contact.bodyA.node!.removeFromParent()
    contact.bodyB.node!.removeFromParent()
  }
}

This code is relatively straightforward, and explained below:

  1. Don't allow the same contact twice.
  2. Check to see if an invader bullet hits your ship.
  3. If an invader bullet hits your ship, remove your ship and the bullet from the scene and play a sound.
  4. If a ship bullet hits an invader, remove the invader and the bullet from the scene and play a different sound.

Add the following method to the // Scene Update section:

func processContactsForUpdate(currentTime: CFTimeInterval) {
  for contact in contactQueue {
    handleContact(contact)
 
    if let index = contactQueue.indexOf(contact) {
      contactQueue.removeAtIndex(index)
    }
  }
}

The above code just drains the contact queue, calling handleContact for each contact in the queue and then remove the contact with the newly added method in the Array extension.

Add the following line to the very top of update() to call your queue handler:

processContactsForUpdate(currentTime)

Build and run you app, and start firing at those invaders!

space_invaders_fighting_back

Now, when your ship’s bullet hits an invader, the invader disappears from the scene and an explosion sound plays. In contrast, when an invader’s bullet hits your ship, the code removes your ship from the scene and a different explosion sound plays.

Depending on your playing skill (or lack thereof!), you may have to run a few times to see both invaders and your ship get destroyed.

Updating Your Heads Up Display (HUD)

Your game looks good, but it’s lacking a certain something. There’s not much dramatic tension to your game. What’s the advantage of hitting an invader with your bullet if you don’t get credit? What’s the downside to being hit by an invader’s bullet if there’s no penalty?

You’ll rectify this by awarding score points for hitting invaders with your ship’s bullets, and by reducing your ship’s health when it gets hit by an invader’s bullet.

Add the following properties to the top of the class:

var score: Int = 0
var shipHealth: Float = 1.0

Your ship’s health starts at 100% but you will store it as a number ranging from 0 to 1. The above sets your ship’s initial health.

Now, replace the following line in setupHud():

healthLabel.text = String(format: "Health: %.1f%%", 100.0)

With this:

healthLabel.text = String(format: "Health: %.1f%%", shipHealth * 100.0)

The new line sets the initial HUD text based on your ship’s actual health value instead of a static value of 100.

Next, add the following two methods below setupHud():

func adjustScoreBy(points: Int) {
  score += points
 
  if let score = childNodeWithName(kScoreHudName) as? SKLabelNode {
    score.text = String(format: "Score: %04u", self.score)
  }
}
 
func adjustShipHealthBy(healthAdjustment: Float) {
  // 1
  shipHealth = max(shipHealth + healthAdjustment, 0)
 
  if let health = childNodeWithName(kHealthHudName) as? SKLabelNode {
    health.text = String(format: "Health: %.1f%%", self.shipHealth * 100)
  }
}

These methods are fairly straightforward: update the score and the score label, and update the ship’s health and the health label. //1 merely ensures that the ship’s health doesn’t go negative.

The final step is to call these methods at the right time during gameplay. Replace handleContact() with the following updated version:

func handleContact(contact: SKPhysicsContact) {
  // Ensure you haven't already handled this contact and removed its nodes
  if contact.bodyA.node?.parent == nil || contact.bodyB.node?.parent == nil {
    return
  }
 
  let nodeNames = [contact.bodyA.node!.name!, contact.bodyB.node!.name!]
 
  if nodeNames.contains(kShipName) && nodeNames.contains(kInvaderFiredBulletName) {
    // Invader bullet hit a ship
    runAction(SKAction.playSoundFileNamed("ShipHit.wav", waitForCompletion: false))
 
    // 1
    adjustShipHealthBy(-0.334)
 
    if shipHealth <= 0.0 {
      // 2
      contact.bodyA.node!.removeFromParent()
      contact.bodyB.node!.removeFromParent()
    } else {
      // 3
      if let ship = self.childNodeWithName(kShipName) {
        ship.alpha = CGFloat(shipHealth)
 
        if contact.bodyA.node == ship {
          contact.bodyB.node!.removeFromParent()
 
        } else {
          contact.bodyA.node!.removeFromParent()
        }
      }
    }
 
  } else if nodeNames.contains(InvaderType.name) && nodeNames.contains(kShipFiredBulletName) {
    // Ship bullet hit an invader
    runAction(SKAction.playSoundFileNamed("InvaderHit.wav", waitForCompletion: false))
    contact.bodyA.node!.removeFromParent()
    contact.bodyB.node!.removeFromParent()
 
    // 4
    adjustScoreBy(100)
  }
}

Here’s what’s changed in the method:

  1. Adjust the ship’s health when it gets hit by an invader’s bullet.
  2. If the ship’s health is zero, remove the ship and the invader’s bullet from the scene.
  3. If the ship’s health is greater than zero, only remove the invader’s bullet from the scene. Dim the ship’s sprite slightly to indicate damage.
  4. When an invader is hit, add 100 points to the score.

The above also explains why you store the ship’s health as a value between 0 and 1, even though your health starts at 100. Since alpha values range from 0 to 1, you can use the ship’s health value as the alpha value for for your ship to indicate progressive damage. That’s pretty handy!

Build and run your game again; you should see the score change when your bullets hit an invader; as well, you should see your ship’s health change when your ship is hit, as below:

space_invaders_healthy

Polishing Your Invader and Ship Images

You’ve been incredibly patient working with these less-than-menacing red, green, blue and magenta rectangles. Keeping the visuals simple has worked well because it allowed you to focus ruthlessly on getting your game logic correct.

Now you’ll add some actual image sprites to make your game much more realistic — and more fun to play!

Replace makeInvaderOfType() with the following two methods:

func loadInvaderTexturesOfType(invaderType: InvaderType) -> [SKTexture] {
 
  var prefix: String
 
  switch(invaderType) {
  case .A:
    prefix = "InvaderA"
  case .B:
    prefix = "InvaderB"
  case .C:
    prefix = "InvaderC"
  }
 
  // 1
  return [SKTexture(imageNamed: String(format: "%@_00.png", prefix)),
    SKTexture(imageNamed: String(format: "%@_01.png", prefix))]
}
 
func makeInvaderOfType(invaderType: InvaderType) -> SKNode {
 
  let invaderTextures = loadInvaderTexturesOfType(invaderType)
 
  // 2
  let invader = SKSpriteNode(texture: invaderTextures[0])
  invader.name = InvaderType.name
 
  // 3
  invader.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(invaderTextures, timePerFrame: timePerMove)))
 
  // invaders' bitmasks setup
  invader.physicsBody = SKPhysicsBody(rectangleOfSize: invader.frame.size)
  invader.physicsBody!.dynamic = false
  invader.physicsBody!.categoryBitMask = kInvaderCategory
  invader.physicsBody!.contactTestBitMask = 0x0
  invader.physicsBody!.collisionBitMask = 0x0
 
  return invader
}

Here’s what the new code does:

  1. Loads a pair of sprite images — InvaderA_00.png and InvaderA_01.png — for each invader type and creates SKTexture objects from them.
  2. Uses the first such texture as the sprite’s base image.
  3. Animates these two images in a continuous animation loop.

All of the images were included in the starter project and iOS knows how to find and load them, so there’s nothing left to do here.

Build and run your app; you should see something similar to the screenshot below:

space_invaders_pretty_enemies

Looks pretty cool doesn’t it? Next, you’ll replace your blocky green ship with a much more retro and stylish looking version.

Replace this piece of code inside makeShip():

let ship = SKSpriteNode(color: SKColor.greenColor(), size: kShipSize)

With the following:

let ship = SKSpriteNode(imageNamed: "Ship.png")

Your ship sprite is now constructed from an image.

Build and run your game; you should see your official-looking ship appear as below:

space_invaders_pretty_player

Play your game for a while — what do you notice? Although you can blast happily away at the invaders, there’s no clear victory or defeat. It’s not much of a space war, is it?

Implementing the End Game

Think about how your game should end. What are the conditions that will lead to a game being over?

  • Your ship’s health drops to zero.
  • You destroy all the invaders.
  • The invaders get too close to Earth.

You’ll now add checks for each of the above conditions.

First, add the following new properties to the top of the class:

let kMinInvaderBottomHeight: Float = 32.0
var gameEnding: Bool = false

The above defines the height at which the invaders are considered to have invaded Earth, and a flag that indicates whether the game is over or not.

Now, add the following two methods below handleContact():

func isGameOver() -> Bool {
  // 1
  let invader = childNodeWithName(InvaderType.name)
 
  // 2
  var invaderTooLow = false
 
  enumerateChildNodesWithName(InvaderType.name) {
    node, stop in
 
    if (Float(CGRectGetMinY(node.frame)) <= self.kMinInvaderBottomHeight)   {
      invaderTooLow = true
      stop.memory = true
    }
  }
 
  // 3
  let ship = childNodeWithName(kShipName)
 
  // 4
  return invader == nil || invaderTooLow || ship == nil
}
 
func endGame() {
  // 1
  if !gameEnding {
 
    gameEnding = true
 
    // 2
    motionManager.stopAccelerometerUpdates()
 
    // 3
    let gameOverScene: GameOverScene = GameOverScene(size: size)
 
    view?.presentScene(gameOverScene, transition: SKTransition.doorsOpenHorizontalWithDuration(1.0))
  }
}

Here’s what’s happening in the first method, which checks to see if the game is over:

  1. Get a random invader in the scene (if one exists) – you’ll use this later.
  2. Iterate through the invaders to check if any invaders are too low.
  3. Get a pointer to your ship: if the ship’s health drops to zero, then the player is considered dead and the player ship will be removed from the scene. In this case, you’d get a nil value indicating that there is no player ship.
  4. Return whether your game is over or not. If there are no more invaders, or an invader is too low, or your ship is destroyed, then the game is over.

The second method actually ends the game and displays the game over scene. Here’s what the code does:

  1. End your game only once. Otherwise, you’ll try to display the game over scene multiple times and this would be a definite bug.
  2. Stop accelerometer updates.
  3. Show the GameOverScene. You can inspect GameOverScene.swift for the details, but it’s a basic scene with a simple “Game Over” message. The scene will start another game if you tap on it.

Add the following line as the first line of code in update():

if isGameOver() {
  endGame()
}

The above checks to see if the game is over every time the scene updates. If the game is over, then it displays the game over scene.

Build and run; blast away at the invaders until your game ends. Hopefully, you’ll destroy all of the invaders before they destroy you! Once your game ends, you should see a screen similar to the following:

space_invaders_game_over

Tap the game over scene and you should be able to play again!

One Last Thing: Polish and Fidelity

If it’s not fun to play with colored squares, it’s not going to be fun to play with fancy art work, either! Nail down your gameplay and game logic first, then build out with fancy art assets and cool sound effects.

That being said, it’s essential that you polish your game before releasing it to the App Store. The App Store is a crowded market and spit and polish will distinguish your app from the competition. Try to add little animations, storylines and a dash of cute factor that will delight your users. Also, consider being true to the game if you’re remaking a classic.

If you’re a fan of Space Invaders, you’ll know that your remake is missing one important element. In the original game, the invaders march faster the closer they get to the bottom of the screen.

You’ll update your game to incorporate this game mechanic as well to please the retro gaming purists out there.

Convert the instance constant let timePerMove: CFTimeInterval = 1.0 to variable var:

var timePerMove: CFTimeInterval = 1.0

Then add the following method below moveInvadersForUpdate():

func adjustInvaderMovementToTimePerMove(newTimerPerMove: CFTimeInterval) {
  // 1
  if newTimerPerMove <= 0 {
    return
  }
 
  // 2
  let ratio: CGFloat = CGFloat(timePerMove / newTimerPerMove)
  timePerMove = newTimerPerMove
 
  // 3
  enumerateChildNodesWithName(InvaderType.name) {
    node, stop in
    node.speed = node.speed * ratio
  }
}

Let’s examine this code:

  1. Ignore bogus values — a value less than or equal to zero would mean infinitely fast or reverse movement, which doesn’t make sense.
  2. Set the scene’s timePerMove to the given value. This will speed up the movement of invaders within moveInvadersForUpdate. Record the ratio of the change so you can adjust the node’s speed accordingly.
  3. Speed up the animation of invaders so that the animation cycles through its two frames more quickly. The ratio ensures that if the new time per move is 1/3 the old time per move, the new animation speed is 3 times the old animation speed. Setting the node’s speed ensures that all of the node’s actions run more quickly, including the action that animates between sprite frames.

Now, you need something to invoke this new method.

Modify determineInvaderMovementDirection() as indicated by comments below:

case .Right:
  //3
  if (CGRectGetMaxX(node.frame) >= node.scene!.size.width - 1.0) {
    proposedMovementDirection = .DownThenLeft
 
    // Add the following line
    self.adjustInvaderMovementToTimePerMove(self.timePerMove * 0.8)
 
    stop.memory = true
  }
case .Left:
  //4
  if (CGRectGetMinX(node.frame) <= 1.0) {
    proposedMovementDirection = .DownThenRight
 
    // Add the following line
    self.adjustInvaderMovementToTimePerMove(self.timePerMove * 0.8)
 
    stop.memory = true
  }

The new code simply reduces the time per move by 20% each time the invaders move down. This increases their speed by 25% (4/5 the move time means 5/4 the move speed).

Build and run your game, and watch the movement of the invaders; you should notice that those invaders move faster and faster as they get closer to the bottom of the screen:

space_invaders_end

This was a quick and easy code change that made your game that much more challenging and fun to play. If you’re going to save the Earth from invading hordes, you might as well do it right! Spending time on seemingly minor tweaks like this is what makes the difference between a good game and a GREAT game.

Where to Go From Here?

Here is the final project from this Sprite Kit tutorial.

I encourage you to experiment with your SKInvaders game. Play with it, tweak it and see what you can do! Breaking your code, fixing it, then finally seeing an awesome new feature come to life is one of the many thrills of game development.

If you’d like to learn more, you should check out our book 2D iOS Games by Tutorials. The book teaches you everything you need to know to make 2D iOS games, by making a series of mini-games like this one, from an action game to a puzzle game to a tower defense game.

Enjoy playing your new game; I look forward to hearing from you with comments below or questions in the forums!

The post How To Make a Game Like Space Invaders with Sprite Kit and Swift Tutorial: Part 2 appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Core Graphics Part 2: Transforms

How To Create a Breakout Game with Sprite Kit and Swift: Part 1

$
0
0

breakout

Update 05/11/2016: Updated for Xcode 7.3 by Michael Briscoe. Original post by Tutorial Team member Barbara Reichart.

Sprite Kit is Apple’s game development framework for iOS and OS X. Not only does it come with some great graphics capabilities, but it also includes an easy to use physics engine. Best of all, you do all the work using the tools you are familiar with: Swift, Xcode and Interface Builder!

There’s a lot you can do with Sprite Kit, and a great way to start learning about how it works is to create a simple game.

In this 2-part tutorial series, you are going to learn how to create a Breakout game using Sprite Kit, complete with collision detection, ball bouncing using physics effects, dragging the paddle via touches, and game states.

If you are new to Sprite Kit, you should go through the Sprite Kit Swift Tutorial for Beginners before proceeding with this tutorial.

Getting Started

Be sure to download the starter project for this tutorial. This project was created using the standard Xcode game template. The assets and state classes, have already been imported to save a bit of time. You’ll learn more about game states as you go along.

Go ahead and take a moment to familiarize yourself with the project. Build and run, and you’ll see a gray screen in landscape mode.

MostlyGray

Introducing the Sprite Kit Visual Editor

Let’s start by configuring the scene file. To do that, open the GameScene.sks file. This is a visual editor already linked to your Sprite Kit Scene and every element dropped in there will be accessible in your game and from GameScene.swift.

First, you will have to resize the scene so it fits your targeted screen for this tutorial: an iPhone 6 screen. You can do that in the Scene section of the Attributes inspector on the top right corner of the Xcode window. If you don’t see the Attributes inspector, you can access it via View\Utilities\Show Attributes Inspector. Set the scene’s size to 568×320 as shown in the screenshot below.

Set the scene size

Note: If your assets library contains art for multiple scale factors, (i.e. 1x, 2x, 3x), be sure to configure the scene size for the 1x artwork. Sprite Kit will automagically use the correct artwork for the currently running device.

Now to the game’s background. As shown in the screenshot below, drag a Color Sprite from the Object Library panel on the bottom right corner of the Xcode window. If you don’t see the Object Library panel, select View\Utilities\Show Object Library from the menubar.

Add background sprite

Using the Attributes inspector, change the Position to 284,160 and set it’s Texture to be bg.

You can now build and run to see your game display it’s background.

Background

Once you have a nice clean landscape scene with a background, it is time to add the ball! Still in GameScene.sks, drag a new Color Sprite into the scene. Then, set it’s Name to ball, it’s Texture to ball, and it’s Position to 284,220. Also set it’s Z Position to 2 to ensure that the ball appears over the background.

Build and run and you’ll see your ball appear on the screen:

Static Ball

However, it doesn’t move yet. That is because you need to add some physics to it.

Physics

In Sprite Kit you work in two environments: the graphical world that you see on the screen and the physics world, which determines how objects move and interact.

The first thing you need to do when using Sprite Kit physics is to change the world according to the needs of your game. The world object is the main object in Sprite Kit that manages all of the objects and the physics simulation. It also sets up the gravity that works on physics bodies added to it. The default gravity is -9.81 thus similar to that of the earth. So, as soon as you add a body it would “fall down”.

Once you have configured the world object, you can add things to it that interact according to the principles of physics. For this the most usual way is to create a sprite (graphics) and set its physics body. The properties of the body and the world determine how it moves.

Bodies can be dynamic objects (balls, ninja stars, birds, …) that move and are influenced by physical forces, or they can be static objects (platforms, walls, …) that are not influenced by those forces. When creating a body you can set a ton of different properties like shape, density, friction and many more. Those properties heavily influence how the body behaves within the world.

When defining a body, you might wonder about the units of their size and density. Internally Sprite Kit uses the metric system (SI units). However within your game you usually do not need to worry about actual forces and mass, as long as you use consistent values.

Once you’ve added all of the bodies to your world, Sprite Kit can take over and do the simulation.

To set up your first physics body, select the ball node you just added and scroll down the Attributes inspector until you reach the Physics Definition section. Select Body Type > Bounding Circle and set the newly appeared properties to the following:

  1. Uncheck Allows Rotation
  2. Set the Friction to 0
  3. Set the Restitution to 1
  4. Set the linear Damping to 0
  5. Set the Angular Damping to 0
Adding physics to the ball

Adding physics to the ball

Here you’ve created a volume-based physics body with the form of a circle that has exactly the same size as the ball sprite. This physics body is affected by forces or impulses, and collisions with other bodies.

As for it’s properties:

  1. Allows Rotation does exactly what the name implies. It either allows rotation of the body or not. Here you do not want the ball to rotate.
  2. Friction is also quite clear – it simply removes all friction.
  3. Restitution refers to the bounciness of an object. You set the restitution to 1, meaning that when the ball collides with an object the collision will be perfectly elastic. In plain English, this means that the ball will bounce back with equal force to the impact.
  4. Linear Damping simulates fluid or air friction by reducing the body’s linear velocity. In the Breakout game the ball should not be slowed down when moving. So, you set the damping to 0.
  5. Angular Damping is the same as Linear Damping but for the angular velocity. Setting this is optional as you don’t allow rotation for the ball.
Note: Usually, it’s best to have the physics body be fairly similar to what the player sees. For the ball it’s very easy to have a perfect match. However, with more complex shapes you’ll need to be careful since very complex bodies can exact a high toll on performance. Since iOS 8 and Xcode 6, Sprite Kit supports alpha masks body types, that automatically take the shape of a sprite as the shape of its physics body, but be careful as it can degrade performance.

Build and run. If you’re quick enough you should see the ball just fall through the scene and disappear at the bottom of the screen.

Ball Falling

Two reasons for this: first, the default gravity of a scene simulates that of the earth – 0 along the x-axis and -9.8 along the y-axis. Second, your scene’s physics world has no boundaries that would act as a cage enclosing the ball. Let’s start with that!

Caging the ball

Cage the ball!

No escape for the ball.

Open GameScene.swift and add the following line of code to the end of didMoveToView(_:) to create an invisible barrier around the screen:

// 1
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
// 2
borderBody.friction = 0
// 3
self.physicsBody = borderBody

Let’s review this line by line:

  1. You create an edge-based body. In contrast to the volume-based body you added to the ball, an edge-based body does not have mass or volume, and is unaffected by forces or impulses.
  2. Set the friction to 0 so that the ball will not be slowed down when colliding with the border barrier. Instead, you want to have a perfect reflection, where the ball leaves along the same angle that it hit the barrier.
  3. You can set a physics body for every node. Here, you attach it to the scene. Note: The coordinates of the SKPhysicsBody are relative to the position of the node.

Running your project, you should now see your ball fall as before but it now bounces on the bottom-edge of the cage you just added. Because you removed the friction from the contact with the cage and the environment, and set the restitution to be perfectly elastic, the ball will bounce like that indefinitely.

BouncingBall

To finish up with the ball, let’s remove the gravity and apply a single impulse so that it will bounce around the screen forever.

Forever bouncing

It’s time to get the ball rolling (bouncing, actually). Add the following code right after the previous lines in GameScene.swift:

physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
 
let ball = childNodeWithName(BallCategoryName) as! SKSpriteNode
ball.physicsBody!.applyImpulse(CGVector(dx: 2.0, dy: -2.0))

This new code first removes all gravity from the scene, then gets the ball from the scene’s child nodes using the name you set in the Visual Editor and applies an impulse. An impulse applies an immediate force to a physics body to get it moving in a particular direction (in this case, diagonally down to the right). Once the ball is set in motion, it will simply bounce around the screen because of the barrier you just added!

Now it’s time to try it out! When you compile and run the project, you should see a ball continuously bouncing around the screen – cool!

BouncingBallEdges

Adding the Paddle

It wouldn’t be a Breakout game without a paddle, now would it?

Go to GameScene.sks and build the paddle (and its companion physics body) via the Visual Editor just like you did for the ball by placing a Color Sprite at the bottom middle of the scene and setting its properties to:

  1. Name = paddle
  2. Texture = paddle.png
  3. Position = 284,30
  4. Z Position = 3
  5. Body Type > Bounding rectangle
  6. Uncheck Dynamic
  7. Friction: 0
  8. Restitution: 1

Most of this is similar to what you used when creating the ball. However, this time you use a Bounding rectangle to form the physics body as it will better match the rectangular paddle.

By turning off Dynamic here you are setting the paddle to be static. This ensures that the paddle does not react to forces and impulses. You will soon see why this is important.

If you build and run, you’ll see your paddle in the scene, and the ball will bounce off it (if you can wait long enough for it to get there):

The most boring game ever :/

So far so good – but now let’s allow the player to move the paddle!

Moving the Paddle

Time to get moving! Moving the paddle is going to require detecting touches. You can detect touches in GameScene by implementing the following touch handling methods:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)

But, before that, you need to add a property. Go to GameScene.swift and add the following property to the class:

var isFingerOnPaddle = false

This defines a property that stores whether the player tapped the paddle or not. You will need it to implement the dragging of the paddle.

Now, go ahead and add the code to implement touchesBegan(_:withEvent:) to GameScene.swift as follows:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  let touch = touches.first
  let touchLocation = touch!.locationInNode(self)
 
  if let body = physicsWorld.bodyAtPoint(touchLocation) {
    if body.node!.name == PaddleCategoryName {
      print("Began touch on paddle")
      isFingerOnPaddle = true
    }
  }
}

The above code gets the touch and uses it to find the location on the scene where the touch occurred. Next, it uses bodyAtPoint(_:) to find the physics body associated with the node (if any) at that location.

Finally, it checks whether there was a node at the tap location and if yes, whether that node is the paddle. This is where the object names you set up earlier come into play – you can check for a specific object by checking its name. If the object at the tap location is a paddle, then a log message is sent to the console and isFingerOnPaddle is set to true.

Now you can build and run the project again. When you tap the paddle, you should see a log message in the console.
BreakoutDebugger1

Now, go ahead and add the code for touchesMoved(_:withEvent:):

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
  // 1
  if isFingerOnPaddle {
    // 2
    let touch = touches.first
    let touchLocation = touch!.locationInNode(self)
    let previousLocation = touch!.previousLocationInNode(self)
    // 3
    let paddle = childNodeWithName(PaddleCategoryName) as! SKSpriteNode
    // 4
    var paddleX = paddle.position.x + (touchLocation.x - previousLocation.x)
    // 5
    paddleX = max(paddleX, paddle.size.width/2)
    paddleX = min(paddleX, size.width - paddle.size.width/2)
    // 6
    paddle.position = CGPoint(x: paddleX, y: paddle.position.y)
  }
}

This is where most of the paddle movement logic comes in.

  1. Check whether the player is touching the paddle.
  2. If yes, then you need to update the position of the paddle depending on how the player moves their finger. To do this, you get the touch location and previous touch location.
  3. Get the SKSpriteNode for the paddle.
  4. Take the current position and add the difference between the new and the previous touch locations.
  5. Before repositioning the paddle, limit the position so that the paddle will not go off the screen to the left or right.
  6. Set the position of the paddle to the position you just calculated.

The only thing left in touch handling is to do some cleanup in touchesEnded(_:withEvent:) as follows:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
  isFingerOnPaddle = false
}

Here, you set the isFingerOnPaddle property to false. This ensures that when the player takes their finger off the screen and then taps it again, the paddle does not jump around to the previous touch location.

Perfect! When you build and run the project now, the ball will bounce around the screen and you can influence its movement using the paddle.

Paddle Bounce

w00t – it’s feeling fun already!

Making Contact

So far, you have a ball that bounces around the screen and a paddle you can move around via touch. While this is really fun to toy around with, to make it a game you need a way for your player to win and lose the game. Losing should happen when the ball touches the bottom of the screen instead of hitting the paddle. But how do you detect this scenario using Sprite Kit?

Sprite Kit can detect the contact between two physics bodies. However, for this to work properly, you need to follow a few steps to set things up a certain way. Here’s a short overview. Each of the steps will be explained in more detail later. So, here you go:

  • Set up physics body bit masks: In your game you might have several different types of physics bodies – for example, you can have the player, enemies, bullets, bonus items etc. To uniquely identify these different types of physics bodies, each physics body can be configured using several bit masks. These include:
    • categoryBitMask: This bit mask identifies the category a body belongs to. You use categories to define a body’s interaction with other bodies. The categoryBitMask is a 32-bit integer, where each bit represents one category. So you can have up to 32 custom categories in your game. This should be enough for most games to set up a separate category for each object type. For more complex games it can be useful to remember that each body can be in several categories. So through smart design of the categories you could even overcome the limitation of 32 categories.
    • contactTestBitMask: Setting a bit in this bitmask causes Sprite Kit to notify the contact delegate when the body touches another body assigned to that particular category. By default, all bits are cleared – you are not notified about any contacts between objects. For best performance you should only set bits in the contacts mask for interactions you are really interested in.
    • collisionBitMask: Here, you can define which bodies can collide with this physics body. You can use this, for example, to avoid collision calculations for a very heavy body when it collides with a much lighter body as this would only make negligible changes to the heavy body’s velocity. But you can also use it to allow two bodies to pass right through each other.
  • Set and implement the contact delegate: The contact delegate is a property of SKPhysicsWorld. It will be notified when two bodies with the proper contactTestBitMasks begin and end colliding.
Note: Bit masks?!? In case you’ve never worked with bit masks, don’t panic! At first glance they might look complicated, but they are really useful.
So what is a bitmask? A bitmask is a multi-digit binary number. Something like this: 1011 1000. Not so complicated at all.

But why are they useful? Well, they allow you to get state information out of a binary number and give you the ability to change a specific bit in a binary number to set a specific state. You can do this with the binary operators AND and OR, like so:

Bitmask power :)

Bitmask power :]

This allows you to store a lot of information in a really compact way using just one variable and still be able to access and manipulate the stored information.

3, 2, 1, Contact: Code

First, create constants for the different categories. Do this by adding the following lines below the other constants for the category names in GameScene.swift:

let BallCategory   : UInt32 = 0x1 << 0
let BottomCategory : UInt32 = 0x1 << 1
let BlockCategory  : UInt32 = 0x1 << 2
let PaddleCategory : UInt32 = 0x1 << 3
let BorderCategory : UInt32 = 0x1 << 4

The above defines five categories. You do this by setting the last bit to 1 and all other bits to zero. Then using the << operator you shift this bit to the left. As a result, each of the category constants has only one bit set to 1 and the position of the 1 in the binary number is unique across the four categories.

For now you only need the category for the bottom of the screen and the ball, but you should set up the others anyway as you will need them later on as you expand the gameplay.

Once you have the constants in place, create a physics body that stretches across the bottom of the screen. Try to do this by yourself since this uses principles you've already learned when creating the barriers around the screen edges.

Solution Inside: Create an edge-based body that spans the bottom of the screen SelectShow>

Now, let’s get to the meat of establishing contact. First, set up the categoryBitMasks for the game objects by adding the following code to didMoveToView(_:):

let paddle = childNodeWithName(PaddleCategoryName) as! SKSpriteNode
 
bottom.physicsBody!.categoryBitMask = BottomCategory
ball.physicsBody!.categoryBitMask = BallCategory
paddle.physicsBody!.categoryBitMask = PaddleCategory
borderBody.categoryBitMask = BorderCategory

This code simply assigns the constants you created earlier to the corresponding physics body’s categoryBitMask.

Now, set up the contactTestBitMask by adding this (again to didMoveToView(_:)):

ball.physicsBody!.contactTestBitMask = BottomCategory

For now you only want to be notified when the ball makes contact with the bottom of the screen.

Next, make GameScene the delegate for all physics contact.

Change this line:

class GameScene: SKScene {

To this line:

class GameScene: SKScene, SKPhysicsContactDelegate {

This makes it official: GameScene is now an SKPhysicsContactDelegate (as it conforms to the SKPhysicsContactDelegate protocol) and will receive collision notifications for all configured physics bodies. Hurrah!

Now you need to set GameScene as the delegate in the physicsWorld. So, add this to didMoveToView(_:) right below physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0):

physicsWorld.contactDelegate = self
Setting up the SKPhysicsContactDelegate

Setting up the SKPhysicsContactDelegate

Finally, you need to implement didBeginContact(_:) to handle the collisions. Add the following method to GameScene.swift:

func didBeginContact(contact: SKPhysicsContact) {
  // 1
  var firstBody: SKPhysicsBody
  var secondBody: SKPhysicsBody
  // 2
  if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
    firstBody = contact.bodyA
    secondBody = contact.bodyB
  } else {
    firstBody = contact.bodyB
    secondBody = contact.bodyA
  }
  // 3
  if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == BottomCategory {
    print("Hit bottom. First contact has been made.")
  }
}

Let's walk through the method step by step:

  1. Create two local variables to hold the two physics bodies involved in the collision.
  2. Check the two bodies that collided to see which has the lower categoryBitmask. You then store them into the local variables, so that the body with the lower category is always stored in firstBody. This will save you quite some effort when reacting to contacts between specific categories.
  3. Profit from the sorting that you did just before. You only need to check whether firstBody is in the BallCategory and whether secondBody is in the BottomCategory to figure out that the ball has touched the bottom of the screen, as you already know that secondBody could not possibly be in the BallCategory if firstBody is in the BottomCategory (because BottomCategory has a higher bit mask than BallCategory). For now react with a simple log message.

It’s time to try out your code again. Build and run your game and if you’ve done everything correctly, you should see the log message in the console every time the ball misses the paddle and hits the bottom of the screen. Like this:

First contact has been made :)

First contact has been made :)

Allright! Now the hard part is done - all that's left is adding the bricks and gameplay logic, which you'll do in part 2.

Where To Go From Here?

Here is the example project up to this point.

Keep reading to part 2 of this series, where you'll add some bricks and finish up the game.

In the meantime, if you have any questions or comments, please join the forum discussion below!

The post How To Create a Breakout Game with Sprite Kit and Swift: Part 1 appeared first on Ray Wenderlich.

How To Create a Breakout Game with Sprite Kit and Swift: Part 2

$
0
0

breakout

Update 05/11/2016: Updated for Xcode 7.3 by Michael Briscoe. Original post by Tutorial Team member Barbara Reichart.

Welcome back to our How To Create a Breakout Game with Sprite Kit and Swift tutorial series!

In the first part of the series, you added a moving paddle and ball to the game.

In this second and final part of the series, you’ll add the bricks to the game along with the rest of the gameplay logic.

This tutorial begins where the previous tutorial left off. If you don’t have it already, here’s the example project up to this point.

Bamboo Blocks

Now that you’ve got the ball bouncing around and making contact, let’s add some bamboo blocks to break. This is a breakout game after all!

Go to GameScene.swift and add the following code to didMoveToView(_:) to introduce the blocks to the scene:

// 1
let numberOfBlocks = 8
let blockWidth = SKSpriteNode(imageNamed: "block").size.width
let totalBlocksWidth = blockWidth * CGFloat(numberOfBlocks)
// 2
let xOffset = (CGRectGetWidth(frame) - totalBlocksWidth) / 2
// 3
for i in 0..<numberOfBlocks {
  let block = SKSpriteNode(imageNamed: "block.png")
  block.position = CGPoint(x: xOffset + CGFloat(CGFloat(i) + 0.5) * blockWidth,
    y: CGRectGetHeight(frame) * 0.8)
 
  block.physicsBody = SKPhysicsBody(rectangleOfSize: block.frame.size)
  block.physicsBody!.allowsRotation = false
  block.physicsBody!.friction = 0.0
  block.physicsBody!.affectedByGravity = false
  block.physicsBody!.dynamic = false
  block.name = BlockCategoryName
  block.physicsBody!.categoryBitMask = BlockCategory
  block.zPosition = 2
  addChild(block)
}

This code creates eight blocks that are centered on the screen.

  1. Some useful constants like the number of blocks you want and their width.
  2. Here you calculate the x offset. This is the distance between the left border of the screen and the first block. You calculate it by subtracting the width of all the blocks from the screen width and then dividing it by two.
  3. Create the blocks, configure each with the proper physics properties, and position each one using blockWidth, and xOffset.

Build and run your game and check it out!

Bamboo Blocks

The blocks are now in place. But in order to listen to collisions between the ball and blocks, you must update the contactTestBitMask of the ball. Still in GameScene.swift, edit the already existing line of code in didMoveToView(_:) to add an extra category to it:

ball.physicsBody!.contactTestBitMask = BottomCategory | BlockCategory

The above executes a bitwise OR operation on BottomCategory and BlockCategory. The result is that the bits for those two particular categories are set to one while all other bits are still zero. Now, collisions between ball and floor as well as ball and blocks will be sent to to the delegate.

Breaking Bamboo

Now that you’re all set to detect collisions between the ball and blocks, let’s add a helper method to GameScene.swift to remove the blocks from the scene:

func breakBlock(node: SKNode) {
  let particles = SKEmitterNode(fileNamed: "BrokenPlatform")!
  particles.position = node.position
  particles.zPosition = 3
  addChild(particles)
  particles.runAction(SKAction.sequence([SKAction.waitForDuration(1.0), SKAction.removeFromParent()]))
  node.removeFromParent()
}

This method takes an SKNode. First, it creates an instance of SKEmitterNode from the BrokenPlatform.sks file, then sets it’s position to the same position as the node. The emitter node’s zPosition is set to 3, so that the particles appear above the remaining blocks. After the particles are added to the scene, the node (bamboo block) is removed.

Note: Emitter nodes are a special type of nodes that display particle systems created in the Scene Editor. To check it out for yourself and see how it’s configured, open BrokenPlatform.sks, which is a particle system I’ve created for you for this tutorial. To learn more about particle systems, check out our book 2D iOS & tvOS Games by Tutorials, which has a detailed chapter on the subject.

The only thing left to do is to handle the delegate notifications accordingly. Add the following to the end of didBeginContact(_:):

if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == BlockCategory {
  breakBlock(secondBody.node!)
  //TODO: check if the game has been won
}

The above lines check whether the collision is between the ball and a block. If this is the case, you pass the node to the breakBlock(_:) method and the block is removed from the scene with a particle animation flourish!

Build and run. Blocks should now break apart when the ball hits them.

Breaking Bamboo

Adding Gameplay

Now that you have all the elements of your breakout game set up, it’s time for the player to experience the the thrill of victory, or the agony of defeat.

Understanding State Machines

Most gameplay logic is governed by the current state of the game. For example, if the game is in the “main menu” state, the player shouldn’t move, but if the game is in the “play” state, it should.

A lot of simple games manage the state by using Boolean variables within the update loop. By using a state machine, you can better organize your code as your game becomes more complex.

A state machine manages a group of states, with a single current state and a set of rules for transitioning between states. As the state of the game changes, the state machine will run methods upon exiting the previous state and entering the next. These methods can be used to control gameplay from within each state. After a successful state change, the machine will then execute the current state’s update loop.

State Machine Flow

Apple introduced the GameplayKit framework in iOS 9, which has built-in support for state machines and makes working with them easy. GameplayKit is beyond the scope of this tutorial, but for now, you’ll use two of its many classes: the GKStateMachine and GKState classes.

Adding States

In Bamboo Breakout there are three game states:

  • WaitingForTap: The game has loaded and is ready to play.
  • Playing: The game is actively playing.
  • GameOver: The game is over with either a win or loss.

To save time these three GKState classes have already been added to your project (check out the Game States group if you’re curious). To create the state machine, first add the following import statement at the top of the GameScene.swift file:

import GameplayKit

Next, insert this class variable just below var isFingerOnPaddle = false:

lazy var gameState: GKStateMachine = GKStateMachine(states: [
  WaitingForTap(scene: self),
  Playing(scene: self),
  GameOver(scene: self)])

By defining this variable, you’ve effectively created the state machine for Bamboo Breakout. Notice that you’re initializing GKStateMachine with an array of GKState subclasses.

WaitingForTap State

The WaitingForTap state is when the game has loaded and is ready to begin. The player is prompted to “Tap to Play”, and the game waits for a touch event before entering the play state.

Start by adding the following code to the end of the didMoveToView(_:) method:

let gameMessage = SKSpriteNode(imageNamed: "TapToPlay")
gameMessage.name = GameMessageName
gameMessage.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
gameMessage.zPosition = 4
gameMessage.setScale(0.0)
addChild(gameMessage)
 
gameState.enterState(WaitingForTap)

This creates a sprite that displays the “Tap to Play” message, later it will also be used to display “Game Over”. You are also telling the state machine to enter the WaitingForTap state.

While you are in didMoveToView(_:) also remove the line that reads:

ball.physicsBody!.applyImpulse(CGVector(dx: 2.0, dy: -2.0)) // REMOVE

You’ll move this line to the play state a little later in this tutorial.

Now, open the WaitingForTap.swift file located in the Game States group. Replace didEnterWithPreviousState(_:) and willExitWithNextState(_:) with this code:

override func didEnterWithPreviousState(previousState: GKState?) {
  let scale = SKAction.scaleTo(1.0, duration: 0.25)
  scene.childNodeWithName(GameMessageName)!.runAction(scale)
}
 
override func willExitWithNextState(nextState: GKState) {
  if nextState is Playing {
    let scale = SKAction.scaleTo(0, duration: 0.4)
    scene.childNodeWithName(GameMessageName)!.runAction(scale)
  }
}

When the game enters the WaitingForTap state, the didEnterWithPreviousState(_:) method is executed. This function simply scales up the “Tap to Play” sprite, prompting the player to begin.

When the game exits the WaitingForTap state, and enters the Playing state, then the willExitWithNextState(_:) method is called, and the “Tap to Play” sprite is scaled back to 0.

Do a build and run, and tap to play!

Tap to Play

Okay, so nothing happens when you tap the screen. That’s what the next game state is for!

Playing State

The Playing state starts the game, and manages the balls velocity.

First, switch back to the GameScene.swift file and implement this helper method:

func randomFloat(from from:CGFloat, to:CGFloat) -> CGFloat {
  let rand:CGFloat = CGFloat(Float(arc4random()) / 0xFFFFFFFF)
  return (rand) * (to - from) + from
}

This handy function returns a random float between two passed in numbers. You’ll use it to add some variability to the balls starting direction.

Now, open the Playing.swift file located in the Game States group. First, add this helper method:

func randomDirection() -> CGFloat {
  let speedFactor: CGFloat = 3.0
  if scene.randomFloat(from: 0.0, to: 100.0) >= 50 {
    return -speedFactor
  } else {
    return speedFactor
  }
}

This code just “flips a coin” and returns either a positive, or negative number. This adds a bit of randomness to the direction of the ball.

Next, add this code to didEnterWithPreviousState(_:):

if previousState is WaitingForTap {
  let ball = scene.childNodeWithName(BallCategoryName) as! SKSpriteNode
  ball.physicsBody!.applyImpulse(CGVector(dx: randomDirection(), dy: randomDirection()))
}

When the game enters the Playing state, the ball sprite is retrieved and it’s applyImpulse(_:) method is fired, setting it in motion.

Next, add this code to the updateWithDeltaTime(_:) method:

let ball = scene.childNodeWithName(BallCategoryName) as! SKSpriteNode
let maxSpeed: CGFloat = 400.0
 
let xSpeed = sqrt(ball.physicsBody!.velocity.dx * ball.physicsBody!.velocity.dx)
let ySpeed = sqrt(ball.physicsBody!.velocity.dy * ball.physicsBody!.velocity.dy)
 
let speed = sqrt(ball.physicsBody!.velocity.dx * ball.physicsBody!.velocity.dx + ball.physicsBody!.velocity.dy * ball.physicsBody!.velocity.dy)
 
if xSpeed <= 10.0 {
  ball.physicsBody!.applyImpulse(CGVector(dx: randomDirection(), dy: 0.0))
}
if ySpeed <= 10.0 {
  ball.physicsBody!.applyImpulse(CGVector(dx: 0.0, dy: randomDirection()))
}
 
if speed > maxSpeed {
  ball.physicsBody!.linearDamping = 0.4
} else {
  ball.physicsBody!.linearDamping = 0.0
}

The updateWithDeltaTime(_:) method will be called every frame while the game is in the Playing state. You get the ball and check its velocity, essentially the movement speed. If the x or y velocity falls below a certain threshold, the ball could get stuck bouncing straight up and down, or side to side. If this happens another impulse is applied, kicking it back into an angular motion.

Also, the ball’s speed can increase as it’s bouncing around. If it’s too high, you increase the linear damping so that the ball will eventually slow down.

Now that the Playing state is set up, it’s time to add the code to start the game!

Back in GameScene.swift replace touchesBegan(_:withEvent:) with this new implementation:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  switch gameState.currentState {
  case is WaitingForTap:
    gameState.enterState(Playing)
    isFingerOnPaddle = true
 
  case is Playing:
    let touch = touches.first
    let touchLocation = touch!.locationInNode(self)
 
    if let body = physicsWorld.bodyAtPoint(touchLocation) {
      if body.node!.name == PaddleCategoryName {
        isFingerOnPaddle = true
      }
    }
 
  default:
    break
  }
}

This enables the game to check the game’s current state, and change the state accordingly. Next, you need to override the update(_:) method and implement it like so:

override func update(currentTime: NSTimeInterval) {
  gameState.updateWithDeltaTime(currentTime)
}

The update(_:) method is called before each frame is rendered. This is where you call the Playing state’s updateWithDeltaTime(_:) method to manage the ball’s velocity.

Give the game a build and run, then tap the screen to see the state machine in action!

Game in action

GameOver State

The GameOver state occurs when the all the bamboo blocks are crushed, or the ball hits the bottom of the screen.

Open the GameOver.swift file located in the Game States group, and add these lines to didEnterWithPreviousState(_:):

if previousState is Playing {
  let ball = scene.childNodeWithName(BallCategoryName) as! SKSpriteNode
  ball.physicsBody!.linearDamping = 1.0
  scene.physicsWorld.gravity = CGVectorMake(0, -9.8)
}

When the game enters the GameOver state, linear damping is applied to the ball and gravity is restored, causing the ball to drop to the floor and slow down.

That’s it for the GameOver state. Now it’s time to implement the code that determines if the player wins or loses the game!

You win some, you lose some

Now that you have the state machine all set, you have most of your game play finished. What you need now is a way to win or lose the game.

Start by opening GameScene.swift and adding this helper method:

func isGameWon() -> Bool {
  var numberOfBricks = 0
  self.enumerateChildNodesWithName(BlockCategoryName) {
    node, stop in
    numberOfBricks = numberOfBricks + 1
  }
  return numberOfBricks == 0
}

This method checks to see how many bricks are left in the scene by going through all the scene’s children. For each child, it checks whether the child name is equal to BlockCategoryName. If there are no bricks left, the player has won the game and the method returns true.

Now, add this property to the top of the class, just below the gameState property:

var gameWon : Bool = false {
  didSet {
    let gameOver = childNodeWithName(GameMessageName) as! SKSpriteNode
    let textureName = gameWon ? "YouWon" : "GameOver"
    let texture = SKTexture(imageNamed: textureName)
    let actionSequence = SKAction.sequence([SKAction.setTexture(texture),
      SKAction.scaleTo(1.0, duration: 0.25)])
 
    gameOver.runAction(actionSequence)
  }
}

Here you create the gameWon variable and attach the didSet property observer to it. This allows you to observe changes in the value of a property and react accordingly. In this case, you change the texture of the game message sprite to reflect whether the game is won or lost, then display it on screen.

Note: Property Observers have a parameter that allows you to check the new value of the property (in willSet) or its old value (in didSet) allowing value changes comparison right when it occurs. These parameters have default names if you do not provide your own, respectively newValue and oldValue. If you want to know more about this, check the Swift Programming Language documentation here: The Swift Programming Language: Declarations

Next, let’s edit the didBeginContact(_:) method as follows:

First, add this line to the very top of didBeginContact(_:):

if gameState.currentState is Playing {
// Previous code remains here...
} // Don't forget to close the 'if' statement at the end of the method.

This prevents any contact when the game is not in play.

Then replace this line:

print("Hit bottom. First contact has been made.")

With the following:

gameState.enterState(GameOver)
gameWon = false

Now when the ball hits the bottom of the screen the game is over.

And replace the // TODO: with:

if isGameWon() {
  gameState.enterState(GameOver)
  gameWon = true
}

When all the blocks are broken you win!

Finally, add this code to touchesBegan(_:withEvent:) just above default:

case is GameOver:
  let newScene = GameScene(fileNamed:"GameScene")
  newScene!.scaleMode = .AspectFit
  let reveal = SKTransition.flipHorizontalWithDuration(0.5)
  self.view?.presentScene(newScene!, transition: reveal)

Your game is now complete! Give it a build and run!

You Won

Finishing Touches

Now that Bamboo Breakout is complete, let’s kick it up a notch by adding a little juice! You’ll do this by adding some sound effects whenever the ball makes contact, and when the blocks are broken. You’ll also add a quick blast of music when the game is over. Finally, you’ll add a particle emitter to the ball, so that it leaves a trail as it bounces around the screen!

Adding sound effects

To save time the project has the various sound files already imported. To start, make sure that GameScene.swift is open, then add the following constants to the top of the class, just after the gameWon variable:

let blipSound = SKAction.playSoundFileNamed("pongblip", waitForCompletion: false)
let blipPaddleSound = SKAction.playSoundFileNamed("paddleBlip", waitForCompletion: false)
let bambooBreakSound = SKAction.playSoundFileNamed("BambooBreak", waitForCompletion: false)
let gameWonSound = SKAction.playSoundFileNamed("game-won", waitForCompletion: false)
let gameOverSound = SKAction.playSoundFileNamed("game-over", waitForCompletion: false)

You define a series of SKAction constants, each of which will load and play a sound file. Because you define these actions before you need them, they are preloaded into memory, which prevents the game from stalling when you play the sounds for the first time.

Next, update the line that sets the ball’s contactTestBitMask within the didMoveToView(_:) method, to the following:

ball.physicsBody!.contactTestBitMask = BottomCategory | BlockCategory | BorderCategory | PaddleCategory

Nothing new here, you’re just adding the BorderCategory and PaddleCategory to the ball’s contactTestBitMask so that you can detect contact with the borders of the screen, and when the ball makes contact with the paddle.

Let’s edit didBeginContact(_:) to include the sound effects by adding the following lines right after the if/else statement where you set up firstBody and secondBody accordingly:

// 1
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == BorderCategory {
  runAction(blipSound)
}
 
// 2
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == PaddleCategory {
  runAction(blipPaddleSound)
}

This code checks for two new collisions:

  1. React to ball bouncing off screen borders by playing blipSound.
  2. React to paddle contact by playing blipPaddleSound.

Of course you want a satisfying crunching sound when the ball breaks the blocks, so add this line to the top of breakBlock(_:):

runAction(bambooBreakSound)

Lastly, at the top of the class insert the following line within the didSet property observer for the gameWon variable:

runAction(gameWon ? gameWonSound : gameOverSound)

One more thing…

Now let’s add a particle system to the ball, so that it leaves a flaming trail as it bounces around!

Add this code to didMoveToView(_:):

// 1
let trailNode = SKNode()
trailNode.zPosition = 1
addChild(trailNode)
// 2
let trail = SKEmitterNode(fileNamed: "BallTrail")!
// 3
trail.targetNode = trailNode
// 4
ball.addChild(trail)

Let’s review this section by section:

  1. Create an SKNode to serve as the targetNode for the particle system.
  2. Create an SKEmitterNode from the BallTrail.sks file.
  3. Set the targetNode to the trailNode. This anchors the particles so that they leave a trail, otherwise they would follow the ball.
  4. Attach the SKEmitterNode to the ball by adding it as a child node.

That’s it – you’re all done! Build and run to see how much more polished your game feels with a little juice:

Flaming particle ball

Where To Go From Here?

You can download the final project for the Sprite Kit Breakout Game that you’ve made in this tutorial.

This is a simple implementation of Breakout. But now that you have this working, there’s a lot more you can do. You could add scoring, or you could extend this code to give the blocks hit points, have different types of blocks, and make the ball have to hit some of them (or all of them) a number of times before they are destroyed. You could add blocks which drop bonuses or power-ups, let the paddle shoot lasers toward the blocks, whatever you dream up!

If you want to learn more about Sprite Kit, you should check out our book 2D iOS & tvOS Games by Tutorials:

In this book we’ll teach you everything you need to know to make great games for iOS & tvOS – from physics, to tile maps, to particle systems, and even how to make your games “juicy” with polish and special effects.

I hope you enjoyed this tutorial, and if you have any questions or comments, please join the forum discussion below!

The post How To Create a Breakout Game with Sprite Kit and Swift: Part 2 appeared first on Ray Wenderlich.


Video Tutorial: Intermediate Core Graphics Part 3: Shadows

Sprite Kit and Inverse Kinematics with Swift

$
0
0

SpriteKit-InvKin-feature

Update 5/12/16: Updated for Xcode 7.3 by Jorge Jordán. Original tutorial by Ken Toh.

If you’ve ever added an animated character to a game, you probably pre-created animations for running, punching, jumping and so forth, and played them when the game executes the associated actions.

While this “canned” approach works for simple scenarios, there are often cases where you’d prefer your character to interact more realistically with other game objects.

For instance, if your character needs to reach out to pick up a nearby object at a variable height, you may not want to use the same animation for every picking action, or it could look really silly when the predefined hand motions don’t line up exactly with the object’s position!

Since iOS 8, Sprite Kit comes with inverse kinematics, a technique that alleviates this issue by allowing you to procedurally generate joint motions such as reaching out to a point in space. This means you don’t have to resort to making a possibly infinite number of animations to reach every possible position.

In this tutorial, you’ll learn how to use Sprite Kit’s inverse kinematics feature to implement dynamic punches and kicks in a fun and simple ninja game. :]

In particular, you’ll learn how to:

  • Set up joint hierarchies in the Sprite Kit Scene Editor.
  • Define joint constraints for more realistic joint behavior.
  • Dynamically animate selected joint hierarchies such that the terminal bones can reach out to various positions in 2D space.

Let’s get moving!

Note: This Swift tutorial assumes you have working knowledge of Sprite Kit and Swift. If you’re new to Sprite Kit, check out our Sprite Kit Swift Tutorial for Beginners or our full book, 2D iOS & tvOS Games by Tutorials. For an introduction to Swift, check out this beginner Swift tutorial.

Getting Started

Download the starter project, open it in Xcode and build and run it. You’ll see a static ninja already set up in the middle of the scene, begging to be released from his yoga stretch.

Introducing a new iOS Framework: YogaKit!

Introducing a new iOS Framework: YogaKit!

Take some time to familiarize yourself with the structure of the sample project. In particular, select GameScene.sks in your project navigator. The file should open up in the integrated Sprite Kit Scene Editor, a feature available since Xcode 6 and iOS 8.

editor

Note: Xcode’s Scene Editor provides a convenient user interface for initializing a scene by allowing you to visually manipulate your sprites and their properties such as position, scale and physics bodies. Later, you can create SKScene objects by unarchiving the .sks files you configured in the Scene Editor.

In the following steps, you’ll take advantage of the Scene Editor to set up and tweak the behavior of the joint hierarchy for your ninja, which would be difficult to visualize and set up programmatically.

Overview of Skeletal Hierarchy

In the scene, you can see that the ninja already has a basic skeleton comprised of a hierarchy of bones, each represented by a sprite node. The nodes are connected in a tree of parent-child relationships, as depicted below:

Skeletal Hierarchy of Ninja

The lower torso node, in red, is the root parent of the entire skeleton hierarchy, which in turn is a child of the scene itself.

The anchor point for each sprite node acts as a joint connecting the node with its parent. These have been adjusted with an offset so that one end of the node can rotate naturally about the joint.

Setting up a Rest Pose

While the ninja looks cool in that mid-air pose, you unfortunately aren’t building a game involving levitation, so you’ll have to bring him back to earth.

Let’s start by adjusting the legs so they touch the shadow on the ground. In the scene, select the front upper leg node, leg_upper_front, by clicking on it.

Selecting the upper front leg node

Set the rotation of leg_upper_front to -14. You can do this either by rotating the handle of the selected sprite or by setting the Rotation property manually in the editor, as shown below:

Angles

Note: Some of the other values (such as position) may be slightly different for you than this screenshot; just make sure the Rotation is -14 and you should be good!

Next, select leg_lower_front and set its rotation to -9 to keep it slightly bent backwards.

Moving on to the back leg nodes, set the rotations of leg_upper_back and leg_lower_back to 22 and -30, respectively. You should see the following:

Adjusting the legs

Now that your ninja is finally standing, let’s work on the arms. Set the rotation angles of both upper arm nodes, arm_upper_front and arm_upper_back, to -10. Also, set the rotation angles of the lower arm nodes, arm_lower_front and arm_lower_back, to 130.

Note: Selecting a particular node can be tricky, especially when it’s obscured by other nodes. One way around this is to right-click on the obscuring node(s) and select Lock Node Selection. This locks the obscuring node, allowing you to select what’s behind it.

A second way, which I find more effective, is to use the jump bars running across the top of the Editor to navigate the scene graph hierarchy and select the node you want, as shown below:

Navigating the Scene Graph

You should see the following:

Rest Pose

Finally, you’re going to do some housekeeping to ensure that the ninja and the shadow always stays centralized, regardless of the screen size. (Currently, the ninja would be off-center on the iPad 2.)

Switch to GameScene.swift and add the following code within and at the top of the GameScene class:

//1
var shadow: SKNode!
var lowerTorso: SKNode!

In didMoveToView(), add the following code:

//2
lowerTorso = childNodeWithName("torso_lower")
lowerTorso.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame) - 30)
 
//3
shadow  = childNodeWithName("shadow")
shadow.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame) - 100)

Let’s go through what you just did:

  1. You create two SKNode properties to reference the shadow node and lower torso node (the root node of the ninja), respectively.
  2. You obtain a reference to the lower torso node by its name, “torso_lower”, and assign its value to the lowerTorso property. Next, you set its position to the center of the screen with an offset of -30 units.
  3. Similarly, you grab a reference to the shadow node by its name, “shadow”, and assign its value to the shadow property. Finally, you set its position to the center of the screen with an offset of -100 units.

Build and run the project, and you’ll see your ninja in its rest stance, ready for a fight!

Ninja is ready!

With the joint hierarchy all set up and your ninja ready for action, you can begin using Sprite Kit’s inverse kinematics feature to deploy some serious martial arts.

What Is Inverse Kinematics?

Before you continue, it’s important to appreciate what inverse kinematics is all about, so the following is a quick primer to get you started.

Forward Kinematics

Forward Kinematics

Fundamentally, kinematics is the study of the motion of an object through space and time.

For an animated character represented by a skeletal hierarchy, forward kinematics is about how the tip of the last bone in a joint hierarchy (called the end-effector) moves in space when you rotate each bone lying along the chain leading up to it.

Take the example of an arm. If I rotate my upper arm about the shoulder joint in combination with extending my lower arm from my elbow joint, I would be able to geometrically determine the new position of my hand by means of forward kinematics.

Note: End-effector is a term commonly used in robotics and character animation to describe the point at the end of a skeleton chain that interacts with the environment.

Inverse Kinematics

Inverse Kinematics

However, it’s often useful to look at the positioning of the joint hierarchy from the reverse point of view.

For example, given a desired goal position of the end-effector, in this case my hand, I would solve for all the joint angles along the chain leading up to the end-effector that would allow me to achieve the desired hand position.

This approach, as you might have guessed already, is known as inverse kinematics, and it’s particularly valuable for achieving goal-oriented actions such as touching, kicking or punching at various points in space. One of the most common uses of inverse kinematics in 3D games is to adjust a character’s limbs to position its feet properly when walking over uneven terrain.

In Sprite Kit, simply specifying a single end-effector goal position in 2D space allows you to position the entire joint hierarchy automatically, as opposed to the forward kinematics approach of fiddling with multiple joint angles.

For the purposes of this tutorial, that’s all the background you need to get started. If you’re interested in delving deeper into the mathematics of inverse kinematics, I highly recommend reading this and this.

In the meantime, let’s learn what you can do with Sprite Kit’s inverse kinematics feature!

Inverse Kinematics Actions

Let’s bring the ninja to life by making his front arm reach out to a position upon a tap event.

Add the following properties to the GameScene class:

var upperTorso: SKNode!
var upperArmFront: SKNode!
var lowerArmFront: SKNode!

These properties will hold references to the upper torso, upper arm and lower arm nodes, respectively.

Next, add the following code at the end of didMoveToView():

upperTorso = lowerTorso.childNodeWithName("torso_upper")
upperArmFront = upperTorso.childNodeWithName("arm_upper_front")
lowerArmFront = upperArmFront.childNodeWithName("arm_lower_front")

Here, you traverse down the parent-child hierarchy manually from the lower torso to the right lower arm, grabbing the appropriate child nodes by their node names and storing them in the variables you declared earlier.

Defining an Inverse Kinematics Action

Next, add the following methods to the GameScene class:

func punchAtLocation(location: CGPoint) {
  // 1
  let punch = SKAction.reachTo(location, rootNode: upperArmFront, duration: 0.1)
  // 2
  lowerArmFront.runAction(punch)
}
 
// 3
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  for touch: AnyObject in touches {
    let location = touch.locationInNode(self)
    punchAtLocation(location)
  }
}

There are a few important things going on here, so let’s run through them step by step:

  1. reachTo() is an action responsible for performing inverse kinematics actions for a joint hierarchy reaching out to a point in space.

    It takes in three arguments: (1) the desired end position to reach; (2) the highest node of the hierarchy that you want to rotate; and (3) the duration of the animation.

    In your case, you set your root node to the upper arm node, since you want to move the upper arm and its descendant nodes. The animation will last for 0.1 seconds.

  2. Note: reachTo() can take a maximum velocity as an argument instead of an animation duration. In addition, there is a variant method, reachToNode(), that takes in a node instead of a position. For more details, refer to the documentation.

  3. Next, you run the action on the end node that is going to reach out to touch the end position in space, which in this case is the lower arm.
  4. Upon a touch event, you run the punch action with the tap location as the end position that you want the lower arm to reach.

Build and run the project. Tap on various locations near the ninja, and you’ll see the arm joints move in an attempt to reach to the tap position.

reachToNode action

This ninja looks like he has some problems!

Setting Up an End-Effector

While the arm joints move following your taps at various locations, there is something fundamentally strange about the actions—it seems the elbow is reaching out to the desired point instead of the fist! Why would that be happening?

Recall that each bone node has an anchor point that has been adjusted with an offset so that it’s flush with one end of the node, enabling it to rotate about its parent.

In your case, when you set the inverse kinematics action to run on the lower arm node, Sprite Kit uses the anchor point as the node reference point or end-effector. The lower arm’s anchor point is the elbow, so this is why the elbow seems to be the point reaching out to the target position.

Let’s fix this by attaching a child end-effector “fist” node at the lower tip of the lower arm.

Since the fist is already visually included with the lower arm, this node will simply be a point node without a texture.

Switch to GameScene.sks. Select the Object Library at the bottom of the Utilities pane in Xcode. From the Object Library, drag an Empty Node onto the front lower arm in the scene. Make sure to align the node with the furthest tip of the hand, as shown below:

Drag an Empty Node

With the new node selected, set its name to fist_front and its Parent to arm_lower_front in the SKNode Inspector on the right.

Setting the Node Properties

Sprite Kit will add the fist as a child, as shown below:

End-effector added

In terms of joint hierarchy, the entire front arm now looks like this: arm_upper_front (root) -> arm_lower_front -> fist_front (end-effector).

Switch back to GameScene.swift. Add the following line near the top of the GameScene class:

var fistFront: SKNode!

In addition, add the following line to the end of didMoveToView():

fistFront = lowerArmFront.childNodeWithName("fist_front")

Finally, replace the following line in punchAtLocation():

lowerArmFront.runAction(punch)

With this:

fistFront.runAction(punch)

Now that you’ve switched the end-effector node to the fist node, build and run the project. Try tapping various locations again, and you’ll see your ninja reaching out with his fist instead of his elbow. It’s a karate chop!

IKReach

Defining Joint Constraints

While tapping at various locations, you may have noticed that inverse kinematics attempts to solve for the set of joint angles that will get your end-effector as near to the target position as possible.

In some cases, however, you may get strange-looking artifacts like the following:

That looks painful!

That looks painful!

In the case above, while the joint angles indeed enable the fist to achieve the target position (illustrated by a red dot), Sprite Kit has bent the elbow joint beyond its realistic limit. Ouch!

This highlights one of the key characteristics of the inverse kinematics problem: Given a desired end-effector position, there could be more than one set of joint positions that will get the end-effector to the goal position. Imagine trying to reach out to touch a nearby object—I’m sure you can find more than one way to twist or extend your upper or lower arm and yet still touch the object!

Fortunately, you can guide the inverse kinematics engine to favor more realistic joint configurations by defining joint constraints to limit joint angles to a suitable lower and upper range.

You’ll define joint constraints for the lower arms so they don’t over-extend, but you’ll continue to allow the upper arms to rotate through the default range of 0-360 degrees.

Switch to GameScene.sks. Select the arm_lower_front node. Under IK Constraints in the SKNode Inspector on the right, keep the Min Angle‘s value 0 and set the Max Angle to 160, as shown below:

Setting IK Constraints

This ensures that the zRotation values of the lower arm node don’t cross the lower limit of 0 degrees (lower arm fully extended) and the upper limit of 160 degrees (lower arm fully retracted, with a gap angle of 20 degrees between the upper and lower arm).

Select the arm_lower_back node and repeat the same steps to enforce similar constraints.

You can also add an IK Constraint programmatically by creating a SKReachConstraint and setting it to the reachConstraints property of the desired node. The instructions above specified can be replaced in code by adding the following lines after the initialization of fistFront:

let rotationConstraintArm = SKReachConstraints(lowerAngleLimit: CGFloat(0), upperAngleLimit: CGFloat(160))
lowerArmFront.reachConstraints = rotationConstraintArm

Note: At the time of updating this tutorial there is a bug on the Scene Editor when editing the IK Constraints property of a node. If you modify either Min Angle or Max Angle none of these changes will be saved. If you experience this issue you can follow the programmatically workaround explained above.

Now, build and run the project. Tap on various locations to test the new constraints. No more over-extension!

Creating a Punching Motion

At this point, your ninja can reach out to any arbitrary tap position, but you know ninjas can do better than that. In this section, you’ll equip your ninja with the ability to punch at a location. Oooofff!

Start by adding the following properties to GameScene inside GameScene.swift:

let upperArmAngleDeg: CGFloat = -10
let lowerArmAngleDeg: CGFloat = 130

The upperArmAngleDeg and lowerArmAngleDeg properties hold the default rest pose angle values of the upper arm and lower arm joints, respectively. Recall that these are the same values you defined earlier when you set up a rest pose for the ninja.

Finally, replace punchAtLocation with the following implementation:

func punchAtLocation(location: CGPoint) {
  // 1
  let punch = SKAction.reachTo(location, rootNode: upperArmFront, duration: 0.1)
 
  // 2
  let restore = SKAction.runBlock {
    self.upperArmFront.runAction(SKAction.rotateToAngle(self.upperArmAngleDeg.degreesToRadians(), duration: 0.1))
    self.lowerArmFront.runAction(SKAction.rotateToAngle(self.lowerArmAngleDeg.degreesToRadians(), duration: 0.1))
  }
 
  // 3
  fistFront.runAction(SKAction.sequence([punch, restore]))
}

That’s quite a bit of code, so let’s dissect it line by line:

  1. The punch action is the same reaching action you defined before—it animates the joint hierarchy to reach out to a desired position.
  2. The restore action animates the restoration of the joint hierarchy to its rest pose. Unfortunately, inverse kinematics actions don’t have reversed actions, so here, you resort to using the traditional forward kinematics to rotate the joint angles back to their rest angles.

    Within this action, you run rotateToAngle() actions concurrently on both the upper and lower arm nodes to restore them to their rest angles as defined by upperArmAngleDeg and lowerArmAngleDeg, respectively. degreesToRadians is defined in a category on CGFloat to convert values between degrees and radians. You can find the function in CGFloat+Extensions.swift, included in the SKTUtils source folder.

  3. Finally, you concatenate the two actions, punch and restore, into a sequenced action, which you then run on the fist.

Build and run the project. The ninja will now punch to wherever you tap!

punching

Punching With Both Fists

Now that your ninja can punch, wouldn’t it be cool if he could use both arms? In this section, you’ll give him the ability to alternate between his left and right fists for consecutive punches.

To do so, you’ll first need to set up the back arm the same way you did the front arm.

Switch to GameScene.sks and add a fist end-effector as a child to arm_lower_back.

Name the fist fist_back. If you’ve set this up properly, you should see the following:

Adding a back fist

Next, switch to GameScene.swift and add the following properties to GameScene:

var upperArmBack: SKNode!
var lowerArmBack: SKNode!
var fistBack: SKNode!

Next, add the following code at the end of didMoveToView():

upperArmBack = upperTorso.childNodeWithName("arm_upper_back")
lowerArmBack = upperArmBack.childNodeWithName("arm_lower_back")
fistBack = lowerArmBack.childNodeWithName("fist_back")

The three properties now hold references to all the back arm nodes.

After the above code, add the reachConstraint to the lowerArmBack to avoid injuries:

lowerArmBack.reachConstraints = rotationConstraintArm

You want to alternate which fist punches, so add the following property to GameScene:

var rightPunch = true

This Boolean’s role is to keep track of whether it’s time to punch using the left or the right fist.

Finally, you’re going to do a little refactoring of punchAtLocation() into two smaller functions to neatly handle punching with either set of arm nodes.

Replace punchAtLocation() with the following code:

// 1
func punchAtLocation(location: CGPoint, upperArmNode: SKNode, lowerArmNode: SKNode, fistNode: SKNode) {
  let punch = SKAction.reachTo(location, rootNode: upperArmNode, duration: 0.1)
  let restore = SKAction.runBlock {
    upperArmNode.runAction(SKAction.rotateToAngle(self.upperArmAngleDeg.degreesToRadians(), duration: 0.1))
    lowerArmNode.runAction(SKAction.rotateToAngle(self.lowerArmAngleDeg.degreesToRadians(), duration: 0.1))
  }
 
  fistNode.runAction(SKAction.sequence([punch, restore]))
}
 
func punchAtLocation(location: CGPoint) {
  // 2  
  if rightPunch {
    punchAtLocation(location, upperArmNode: upperArmFront, lowerArmNode: lowerArmFront, fistNode: fistFront)
  }
  else {
    punchAtLocation(location, upperArmNode: upperArmBack, lowerArmNode: lowerArmBack, fistNode: fistBack)
  }
  // 3
  rightPunch = !rightPunch
}

Let’s go through the essence of what’s happening here:

  1. This first function is similar to the version you had previously, except that it now lets you specify the arm nodes as arguments. This enables you to use the same function for both the left and right arms.
  2. In the second function, you simply check if it’s time to use the left or the right arm based on the value of the rightPunch Boolean, and execute the actions accordingly.
  3. Finally, you toggle the rightPunch flag such that when the function is called again on the next tap, the Boolean flag is flipped accordingly, allowing you to alternate between the two arms.

Build and run the project. Your ninja will punch with both fists!

Punching with two fists

Facing the Target

You may have noticed that your ninja isn’t quite as adept at handling target positions behind him.

iOS Simulator Screen Shot Sep 28, 2014, 9.05.16 PM

That looks more like a dance move than a punch! Since this isn’t a dance simulator (although that sounds like a fun game idea!), let’s fix this by making the ninja always face the target position.

In touchesBegan(), add the following code just before the line that calls punchAtLocation():

lowerTorso.xScale =
  location.x < CGRectGetMidX(frame) ? abs(lowerTorso.xScale) * -1 : abs(lowerTorso.xScale)

If you detect the tap on the left half of the screen, you negate the scale of the ninja (rooted at the lower torso), which has the effect of flipping the entire ninja horizontally.

Build the project again and run it. Upon a tap, the ninja will now face the direction of the tap location.

iOS Simulator Screen Shot Sep 28, 2014, 9.00.51 PM

Head Tracking

As a bonus, you can make the ninja behave more even realistically by using Sprite Kit’s SKConstraints to make his head track the target.

SKConstraints allow you to ensure that certain relationships are true between nodes, before a scene is rendered.

For example, you can set up a constraint to make sure a node stays within a certain rectangle, to orient one node toward another, or to limit the z rotation of a node. You will combine a few constraints here to easily make the ninja’s face look toward where he’s punching.

Begin by adding the following properties to GameScene:

var head: SKNode!
let targetNode = SKNode()

Next, add the following code to the bottom of didMoveToView():

head = upperTorso.childNodeWithName("head")

This grabs a reference to the head node and stores it in head.

Now, add the following line to the end of the for loop in touchesBegan, just after the call to punchAtLocation():

targetNode.position = location

targetNode now stores the location of the latest tap location.

Finally, you’ll make use of SKConstraints to ensure that the head node is always oriented so that it “looks” at the target node. Add the following code at the end of didMoveToView():

// 1
let orientToNodeConstraint = SKConstraint.orientToNode(targetNode, offset: SKRange(constantValue: 0.0))
// 2
let range = SKRange(lowerLimit: CGFloat(-50).degreesToRadians(),
                                        upperLimit: CGFloat(80).degreesToRadians())
// 3
let rotationConstraint = SKConstraint.zRotation(range)
// 4
rotationConstraint.enabled = false
orientToNodeConstraint.enabled = false
// 5
head.constraints = [orientToNodeConstraint, rotationConstraint]

Let’s go through the code line by line:

  1. You create an orientToNode constraint, passing in targetNode as the node toward which to orient.
  2. Here, you define an angle range from -50 degrees to 80 degrees, converted to radians.
  3. You define a rotation constraint that limits the zRotation property of the head node to the angle range defined in step 2.
  4. You disable the two constraints by default, as there may not be any target node yet.
  5. Finally, you add the two constraints to the head node.

To get the constraints to work, you’ll enable the constraints upon the first tap. Add the following property to GameScene:

var firstTouch = false

Next, add the following code to the beginning of touchesBegan():

if !firstTouch {
  for c in head.constraints! {
    let constraint = c
    constraint.enabled = true
  }
  firstTouch = true
}

On the very first tap event, the code above loops through the list of constraints defined for the head node and enables all of them. It then sets the firstTouch flag to true, which ensures that the code won’t be executed again on subsequent taps.

Build and run the project once more. Voila! Your ninja now maintains constant eye contact with his target position as he punches.

puncheverywhere

Hitting Moving Targets

At this point, your ninja is raring for “real” things to punch, so let’s spawn some flying shurikens from either side of the screen for the ninja to hit.

Begin by adding the following function to the GameScene class:

func addShuriken() {
  // 1
  let shuriken = SKSpriteNode(imageNamed: "projectile")
  // 2 
  let minY = lowerTorso.position.y - 60 + shuriken.size.height/2
  let maxY = lowerTorso.position.y  + 140 - shuriken.size.height/2
  let rangeY = maxY - minY
  let actualY = (CGFloat(arc4random()) % rangeY) + minY
  // 3
  let left = arc4random() % 2
  let actualX = (left == 0) ? -shuriken.size.width/2 : size.width + shuriken.size.width/2
  // 4 
  shuriken.position = CGPointMake(actualX, actualY)
  shuriken.name = "shuriken"
  shuriken.zPosition = 1
  addChild(shuriken)
  // 5 
  let minDuration = 4.0
  let maxDuration = 6.0
  let rangeDuration = maxDuration - minDuration
  let actualDuration = (Double(arc4random()) % rangeDuration) + minDuration
  // 6 
  let actionMove = SKAction.moveTo(CGPointMake(size.width/2, actualY), duration: actualDuration)
  let actionMoveDone = SKAction.removeFromParent()
  shuriken.runAction(SKAction.sequence([actionMove, actionMoveDone]))
  // 7  
  let angle = left == 0 ? CGFloat(-90).degreesToRadians() : CGFloat(90).degreesToRadians()
  let rotate = SKAction.repeatActionForever(SKAction.rotateByAngle(angle, duration: 0.2))
  shuriken.runAction(SKAction.repeatActionForever(rotate))
}

Let’s briefly run through the code in this function:

  1. You create a brand new sprite node from the projectile.png image.
  2. You set the spawn height of the shuriken to a value between 60 units below and 130 units above the lower torso. This ensures the shuriken will be within reach of the ninja.
  3. You set the x-position of the shuriken to be either slightly left or slightly right of the screen.
  4. You then set the position of the shuriken based on the values determined in steps 2 and 3. You also assign the hard-coded name “shuriken” to the node before adding it as a child to the scene.
  5. You randomize the move duration of the shuriken to be between 4 and 6 seconds to add some sense of variance to the game.
  6. You define a sequence of two actions to run on the shuriken. The first action moves the shuriken toward the center of the screen based on the duration defined in step 5. The second action removes the shuriken once it reaches the center of the screen.
  7. Concurrently, you rotate the shuriken continuously in the direction of its motion for a more realistic effect.

You’ll want to spawn shurikens periodically for the life of the game. Add the following properties to GameScene to keep track of the time between spawns:

var lastSpawnTimeInterval: NSTimeInterval = 0
var lastUpdateTimeInterval: NSTimeInterval = 0

Then add the following methods to GameScene, as well:

func updateWithTimeSinceLastUpdate(timeSinceLast: CFTimeInterval) {
  lastSpawnTimeInterval = timeSinceLast + lastSpawnTimeInterval
  if lastSpawnTimeInterval > 0.75 {
    lastSpawnTimeInterval = 0
    addShuriken()
  }
}
 
override func update(currentTime: CFTimeInterval) {
  var timeSinceLast = currentTime - lastUpdateTimeInterval
  lastUpdateTimeInterval = currentTime
  if timeSinceLast > 1.0 {
    timeSinceLast = 1.0 / 60.0
    lastUpdateTimeInterval = currentTime
  }
  updateWithTimeSinceLastUpdate(timeSinceLast)
}

updateWithTimeSinceLastUpdate adds the time since the last update to lastSpawnTimeInterval. Once it is greater than 0.75 seconds, you call addShuriken() to spawn a new shuriken and reset the time. You call this method inside update() each frame, with a bit of math to ensure the time between frames doesn’t get out of hand.

This code is similar to the monster-spawning code in the Sprite Kit Swift Tutorial for Beginners on this site. You can refer to that tutorial if you’d like more details.

Build and run the project, and you’ll see shurikens fly in at your ninja from both sides of the screen!

Shurikens

The shurikens look dangerous, but they simply run into the ninja as if he weren’t even there. Not to worry; you’ll fix this by adding some code to check for possible intersections between the end-effector and any flying shuriken.

Add the following function to the GameScene class:

func intersectionCheckActionForNode(effectorNode: SKNode) -> SKAction {
  let checkIntersection = SKAction.runBlock {
 
    for object: AnyObject in self.children {
      // check for intersection against any sprites named "shuriken"
      if let node = object as? SKSpriteNode {
        if node.name == "shuriken" {
          // convert coordinates into common system based on root node
          let effectorInNode = self.convertPoint(effectorNode.position, fromNode:effectorNode.parent!)
          var shurikenFrame = node.frame
          shurikenFrame.origin = self.convertPoint(shurikenFrame.origin, fromNode: node.parent!)
 
          if shurikenFrame.contains(effectorInNode) {
            // play a hit sound
            self.runAction(SKAction.playSoundFileNamed("hit.mp3", waitForCompletion: false))
 
            // show a spark effect
            let spark = SKSpriteNode(imageNamed: "spark")
            spark.position = node.position
            spark.zPosition = 60
            self.addChild(spark)
            let fadeAndScaleAction = SKAction.group([
              SKAction.fadeOutWithDuration(0.2),
              SKAction.scaleTo(0.1, duration: 0.2)])
            let cleanUpAction = SKAction.removeFromParent()
            spark.runAction(SKAction.sequence([fadeAndScaleAction, cleanUpAction]))
 
            // remove the shuriken
            node.removeFromParent()
          }
          else {
            // play a miss sound
            self.runAction(SKAction.playSoundFileNamed("miss.mp3", waitForCompletion: false))
          }
        }
      }
    }
  }
  return checkIntersection
}

intersectionCheckActionForNode() takes in an end-effector node and returns an action that runs a block; you’ll see in the next section why you define the function in this manner. Within this block, you check to see if the end-effector intersects with any shurikens present in the scene.

In the event of an intersection, you play a “hit” sound, show a little spark effect and remove the shuriken sprite from the scene. Otherwise, you simply play a “miss” sound.

Next, replace the last line of punchAtLocation(_:upperArmNode:lowerArmNode:fistNode:) with the two lines below:

let checkIntersection = intersectionCheckActionForNode(fistNode)
fistNode.runAction(SKAction.sequence([punch, checkIntersection, restore]))

You’ve simply added an additional action right after the punch action, which runs a block to check for possible intersections of the fist node with the shurikens in the scene.

Since you perform the intersection test exactly at the moment when the reaching motion is complete, your ninja has to be rather precise when executing a punch, which should be the case for all ninjas anyway. :]

Build and run the project. Your ninja can now handle those shurikens like a boss!

punchall1

The shurikens still don’t hurt the ninja; you’ll implement that in a later section.

Creating a Kicking Motion

Your ninja is now a punching machine, but there’s no doubt he can do more to showcase his well-roundedness. Let’s equip him with the ability to kick at shurikens below a certain height.

You’ll begin by setting up the leg joint hierarchy for inverse kinematics. In particular, you’ll:

  • Define an end-effector node for the back leg, which will be the leg the ninja will use for kicking.
  • Set up joint constraints for each back leg joint.
  • Define inverse kinematics actions for the joint hierarchy to reach the tap location for taps made below a certain height.

These steps are similar to what you’ve done for the arms, so let’s get on with it!

Switch to GameScene.sks. Drag an Empty Node onto the back lower leg (leg_lower_back) in the scene. Make sure to align the node with the farthest tip of the foot. Keeping the node selected, set its name to foot_back and its parent to leg_lower_back in the SKNode Inspector on the right. Once done, you’ll have something like this:

foot-effector

Next, you’ll set the IK Constraints for the leg’s nodes.

Don’t do this yet; I want to explain things first.

For leg_upper_back, you’ll constrain the rotation angle to between -45 and 160 degrees, as illustrated below:

upperconstraint

As for leg_lower_back, you’ll constrain the rotation angle to between -45 and 0 degrees, as shown below:

lowerconstraint

Strangely, Scene Editor only allows positive values for the min and max angles. It also doesn’t allow the min angle to be larger than the max angle, which means it would consider a normalized range of 315 (-45) to 160 for the upper leg to be invalid, as well. Nonetheless, you will overcome this limitation by defining the constraints programmatically.

Now you can go ahead and implement this.

Inside GameScene.swift, add the following properties to GameScene:

var upperLeg: SKNode!
var lowerLeg: SKNode!
var foot: SKNode!

And add the following code to initialize these new properties in didMoveToView():

upperLeg = lowerTorso.childNodeWithName("leg_upper_back")
lowerLeg = upperLeg.childNodeWithName("leg_lower_back")
foot = lowerLeg.childNodeWithName("foot_back")
 
lowerLeg.reachConstraints = SKReachConstraints(lowerAngleLimit: CGFloat(-45).degreesToRadians(), upperAngleLimit: 0)
upperLeg.reachConstraints = SKReachConstraints(lowerAngleLimit: CGFloat(-45).degreesToRadians(), upperAngleLimit: CGFloat(160).degreesToRadians())

In the code above, you obtain references to the three leg nodes and save them in their respective properties. You then set the reachConstraints property of the lower and upper legs to the limits described previously. That’s about it!

Next, you’ll define a function that runs a kicking action on the foot node. Before you do so, add the following properties to GameScene:

let upperLegAngleDeg: CGFloat = 22
let lowerLegAngleDeg: CGFloat = -30

These two properties hold the rest angles of the upper and lower leg joints, respectively.

Next, add the following function to GameScene:

func kickAtLocation(location: CGPoint) {
  let kick = SKAction.reachTo(location, rootNode: upperLeg, duration: 0.1)
 
  let restore = SKAction.runBlock {
    self.upperLeg.runAction(SKAction.rotateToAngle(self.upperLegAngleDeg.degreesToRadians(), duration: 0.1))
    self.lowerLeg.runAction(SKAction.rotateToAngle(self.lowerLegAngleDeg.degreesToRadians(), duration: 0.1))
  }
 
  let checkIntersection = intersectionCheckActionForNode(foot)
 
  foot.runAction(SKAction.sequence([kick, checkIntersection, restore]))
}

This function is similar to the one you constructed for the arms, except it’s tailored for the leg nodes. Notice how you’re able to reuse intersectionCheckActionForNode(), this time for the foot end-effector node.

Finally, you’ll run the leg action for tap locations below a certain height. Within the for loop in touchesBegan(), replace the following line:

punchAtLocation(location)

With the code below:

let lower = location.y < lowerTorso.position.y + 10
if lower {
  kickAtLocation(location)
}
else {
  punchAtLocation(location)
}

Here, you simply run the kicking action if the tap position is below the lower torso’s height plus 10 units; otherwise you do the usual punching action.

Build and run the project. Your ninja can now dynamically punch and kick shurikens that are within range!

kick

Finishing Touches

You are almost done! Let’s tweak this project to make it into a playable game. To spice things up, you’ll give the ninja three lives, make him take damage from missed shurikens and allow him to earn points for each shuriken he hits.

Add the following properties to GameScene:

var score: Int = 0
var life: Int = 3

These properties will store the score and number of lives remaining, respectively.

Add the following lines after the code above:

let scoreLabel = SKLabelNode()
let livesLabel = SKLabelNode()

You’ll use these label nodes to display the score and remaining lives, respectively.

Next, add the following code to didMoveToView() to set up the properties of the label nodes and add them to the scene:

// setup score label
scoreLabel.fontName = "Chalkduster"
scoreLabel.text = "Score: 0"
scoreLabel.fontSize = 20
scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
scoreLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Top
scoreLabel.position = CGPoint(x: 10, y: size.height -  10)
addChild(scoreLabel)
 
// setup lives label
livesLabel.fontName = "Chalkduster"
livesLabel.text = "Lives: 3"
livesLabel.fontSize = 20
livesLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Right
livesLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Top
livesLabel.position = CGPoint(x: size.width - 10, y: size.height - 10)
addChild(livesLabel)

With the label nodes set up, add the following lines within the innermost if block in intersectionCheckActionForNode(), right before the line node.removeFromParent():

self.score += 1
self.scoreLabel.text = "Score: \(Int(self.score))"

This increments the score by 1 whenever the ninja successfully destroys a shuriken with a punch or a kick.

Now, let’s handle the lives. Every time a shuriken hits the ninja, you’ll decrement the ninja’s life by 1. If he has no remaining lives, you’ll show a “Game Over” screen briefly and restart the scene.

Begin by creating a new scene to display the “Game Over” message. Create a new file with the iOS\Source\Swift class template, name the file GameOverScene, click Next and then click Create.

Replace the contents of GameOverScene.swift with the following code:

import SpriteKit
 
class GameOverScene: SKScene {
  override func didMoveToView(view: SKView) {
 
    let myLabel = SKLabelNode(fontNamed:"Chalkduster")
    myLabel.text = "Game Over"
    myLabel.fontSize = 65
    myLabel.position = CGPoint(x:CGRectGetMidX(frame), y:CGRectGetMidY(frame))
    addChild(myLabel)
 
    runAction(SKAction.sequence([
      SKAction.waitForDuration(1.0),
      SKAction.runBlock({
        let transition = SKTransition.fadeWithDuration(1.0)
        let scene = GameScene(fileNamed:"GameScene")
        scene!.scaleMode = .AspectFill
        scene!.size = self.size
        self.view?.presentScene(scene!, transition: transition)
      })]))
  }
}

The code above displays a label showing a “Game Over” message. It then runs an action on the scene that presents a new GameScene with a fading transition after a delay of one second.

Now, switch back to GameScene.swift. In addShuriken(), add the following code right after the line that creates actionMoveDone:

let hitAction = SKAction.runBlock({
  // 1
  if self.life > 0 {
    self.life -= 1
  }
  // 2
  self.livesLabel.text = "Lives: \(Int(self.life))"
 
  // 3      
  let blink = SKAction.sequence([SKAction.fadeOutWithDuration(0.05), SKAction.fadeInWithDuration(0.05)])
 
  // 4
  let checkGameOverAction = SKAction.runBlock({
    if self.life <= 0 {
      let transition = SKTransition.fadeWithDuration(1.0)
      let gameOverScene = GameOverScene(size: self.size)
      self.view?.presentScene(gameOverScene, transition: transition)
    }
  })
  // 5
  self.lowerTorso.runAction(SKAction.sequence([blink, blink, checkGameOverAction]))
})

In the code you just added, you create an additional action to be run when the shuriken reaches the center of the screen. The action runs a block that does the following:

  1. It decrements the number of lives.
  2. It accordingly updates the label depicting the number of lives remaining.
  3. It defines a blink action with fade-in and fade-out durations of 0.05 seconds each.
  4. It defines another action running a block that checks if the number of remaining lives has hit zero. If so, the game is over, so the code presents an instance of GameOverScene.
  5. It then runs the actions in steps 3 and 4 in sequence on the lower torso, the root of the ninja.

Finally, add hitAction to the sequence of actions you run on each shuriken. Replace the following line in addShuriken:

shuriken.runAction(SKAction.sequence([actionMove, actionMoveDone]))

With this:

shuriken.runAction(SKAction.sequence([actionMove, hitAction, actionMoveDone]))

Build and run the project. You’ll see the new number of lives and score labels. In addition, your ninja is no longer immune, which makes the game a bit more challenging!

finalscreen

Gratuitous Background Music

Last but not least, every ninja game needs good background music, so switch to GameViewController.swift and add the following import at the top of the file:

import AVFoundation

This gives you access to the AVFoundation framework, which is necessary to play background music.

Add the following property to the GameViewController class:

var audioPlayer: AVAudioPlayer?

Next, you’ll write a function that plays your background music. Add the following function to the GameViewController class:

  func startBackgroundMusic() {
    if let path = NSBundle.mainBundle().pathForResource("bg", ofType: "mp3") {
      audioPlayer = try! AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: path), fileTypeHint: "mp3")
      if let player = audioPlayer {
        player.prepareToPlay()
        player.numberOfLoops = -1
        player.play()
      }
    }
  }

The function looks for the background music file bg.mp3 in the resource path, loads it into memory and plays it indefinitely.

Note: The AVAudioPlayer() initializer can throw errors that need to be handled. As the audio resource is provided on the project no error will be thrown so that’s why you wrote try!, in order to disable error propagation. For more details, refer to the documentation.

Finally, add the following line to the bottom of viewDidLoad() in GameViewController to play the music upon loading the main view:

startBackgroundMusic()

That’s it! Build and run the project, and strike shurikens to the beat of your new background music.

Ninja

Where to Go From Here?

You can download the complete project for this tutorial here.

At this point, you should have a solid grasp of the key concepts of inverse kinematics in Sprite Kit.

Inverse kinematics is a powerful technique that brings a new level of dynamism to traditional character animation. There are many possible goal-oriented scenarios where inverse kinematics would apply an additional touch of realism—from having a snake whip its neck around to face the user, to a goalkeeper adjusting both hands to catch an oncoming ball, to a wizard dexterously waving a wand in mid-air—it’s all up to your imagination!

In case you’re wondering, 3D inverse kinematics is also available in Scene Kit, Apple’s 3D Graphics API. The feature allows you to blend inverse kinematics on top of existing animations, bringing an even greater sense of realism.

If you’d like to learn more, you should check out our book 2D iOS Games by Tutorials. The book teaches you everything you need to know to make 2D iOS games, by making a series of mini-games like this one, from an action game to a puzzle game to a tower defense game.

I hope you enjoyed this tutorial, and I look forward to seeing how you use inverse kinematics to spice up character animations in your own games!

Credits: Art by Vicki Wenderlich from gameartguppy.com. Background music from Kevin MacLeod. Hit Sound Effect from Mike Koenig, and Miss Sound Effect from Mark DiAngelo.

The post Sprite Kit and Inverse Kinematics with Swift appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Core Graphics Part 4: Drawing Text and Images

Top 5 iOS and Swift Newsletters

$
0
0

Top 5 iOS and Swift Newsletters

It’s hard to keep up-to-date as an iOS and Swift developer.

Every day, new articles, tutorials, and open source libraries are released. How do you keep up with this flood of information?

One good way is to subscribe to iOS and Swift newsletters, so that every week you can receive an email with the week’s highlights.

In this article, we’ll share a list of what the tutorial team and I consider the top 5 iOS and Swift newsletters, that every serious developer should subscribe to.

Let’s dive in!

The Newsletters

Note: These newsletters are listed in no particular order – they’re all great!

iOS Dev Weekly

iOS Dev Weekly

iOS Dev Weekly is the first newsletter that was created in the iOS community. The first issue was published Aug 5th 2011. That’s a long time ago in Internet years :]

iOS Dev Weekly is organized in different sections that include topics like code, design, tools and business. There’s also a nice one-more-thing kind of link at the end of each issue.

“I love the fact that each section of iOS Dev Weekly has color coding – e.g. ‘design’, ‘code’, ‘tools’ – this makes it super simple to scan if you’re in a hurry. Dave Verwer’s summary is always insightful.”
Gemma Barlow

“I look forward to iOS Dev Weekly every Friday. It’s tough to keep up with all the information that passes by through Slack and Twitter. I really like how iOS Dev Weekly allows the cream to rise to the top, and sends the best of the best news related to iOS development from the week to my inbox, at a reliable time each week on Friday.”
Andy Obusek

This Week in Swift

This Week in Swift

This week in Swift features content related to Swift and its evolution. It was started a few weeks after the announcement of Swift at WWDC 2014.

Every week Natasha publishes some thoughts and then lists relevant links that have been discussed. There are sections about the evolution of Swift, open source projects, design and business.

“I subscribed to the This Week in Swift newsletter, which I read each and every single Monday, because I like Natasha’s friendly tone, enthusiasm and way of explaining things. She is so excited about everything new she discovers in Swift, that I always feel the need to immediately open an Xcode playground and try out the new feature she is talking about right away.”
Cosmin Pupăză

“I like Natasha’s newsletter because it’s mostly focused on Swift, and every week I find what I need to stay up to date with the language, but not neglecting iOS, watchOS and tvOS. I also like her own articles/posts, because they are short and usually focusing on solving specific problems, showing creative ways of doing things, and often also explaining mistakes she made.”
Antonio Bello

raywenderlich.com Weekly

raywenderlich.com Weekly

Full Disclosure: raywenderlich.com Weekly is this site’s newsletter. We might be a little biased :]

If you want to keep up-to-speed on what’s going on here at raywenderlich.com, this is the newsletter for you!

Every week Ray puts together a summary of the new tutorials and articles released on this site, plus other relevant links that have been discussed in our Slack channels or on the web.

This is the largest newsletter on this list, with over 78K subscribers. It contains sections on Swift, iOS, OS X, Android, Mac OS X, books recently released or updated, and videos.

The last link is usually non technical and often fun, but still very relevant to the Cocoa community and the world of building software in general.

“I love Ray’s newsletters because it gives a bite sized summary of interesting articles to read for the week.”
Kelvin Lau

“I don’t subscribe to many newsletters. However, there is one that I enjoy. In fact, when I see the raywenderlich.com Weekly show up in my inbox, I usually stop what I’m doing to read it.”
Tammy Coron

iOS Goodies

iOS Goodies

While most of the newsletters collect links that are hand picked by the curators, iOS Goodies is “made in the open”.

Anybody can suggest links to be included in the next issue by submitting a pull request on GitHub. If you are interested in contributing here are the guidelines.

Sections include links about technical articles, business and user experience. It’s a handy way to keep up with the bits that might be excluded by other newsletters but are still very relevant in the Cocoa community.

“I enjoy iOS Goodies because there’s usually several links that I hadn’t seen before that are quite interesting. It’s also the only newsletter I know of that’s open source – feel free to contribute links you like too!”
Ray Wenderlich

“I subscribed because it kept me informed with the latest iOS news and article. I did it some long time ago, before iOS newsletters were cool and there were not that many out there. I love the idea of an open source newsletter. I also contribute to it.”
Marius Constantinescu

Release Notes

Release notes

Well written code built with effective tools is just a part of a successful project. All the rest includes devising a sustainable business model and spreading the word about the product.

The Release Notes newsletter features links that revolve around the business and marketing side of things. You’ll find articles about changing business model, effectively approaching the press, product-market fit and the like. “Anything but the code” :]

“I subscribe to quite a few iOS related newsletters. I love that the Release Notes monthly newsletter is different from the rest in that it addresses the non-technical sides of running an indie app business. Everything from marketing to inspiration to business tips from other devs. The articles and blog posts which Charles and Joe include are all high quality and I learn a *ton* from each edition. I highly recommend the newsletter (and the podcast) to anyone who has an indie app business or is looking to make the leap.”
Yono Mittlefehldt

“I subscribe to a few developer email newsletters, but Release Notes is the only one for a podcast. It’s a great way to get a quick summary of some of the recent episodes, just in case I’m behind listening to the show and don’t want to miss a particular topic. Joe and Charles also include a bunch of good blog post links, for recent developer- and business-focused posts from the community.”
Manton Reece

Honorable mentions

There are so many valuable iOS and Swift newsletters out there, that picking the top 5 wasn’t an easy task. Some have been left out, but they deserve an honorable mention.

  • iOS Cookies lists hand picked iOS libraries written in Swift. The list is nicely organized into categories so it’s easy to browse.
  • Indie iOS is a weekly newsletter featuring links about iOS but with a slant towards indie developers.
  • Swift Sandbox is a newsletter dedicated exclusively to Swift. It features articles about the core, foundation and evolution of Swift.

Where To Go From Here?

The iOS community is very vibrant and keeping up with all the news on your own can be complicated. But if you subscribe to all of these newsletters, it’s easy! :]

If you want to be even more involved, you can attend some iOS conferences in 2016.

What do you consider the top iOS and Swift newsletters? Please join our forum discussion below!

Note: Huge thanks to everyone who contributed thoughts and quotes to this article! :]

The post Top 5 iOS and Swift Newsletters appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Core Graphics Part 5: PDF Printing

Viewing all 4370 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>