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

Scene Kit Tutorial with Swift Part 2: Nodes

$
0
0
Note: This is an abbreviated chapter from the 3D iOS Games by Tutorials, to give you a sneak peek of what’s inside the book, released as part of 3D iOS Games by Tutorials Week. We hope you enjoy!

Thumb

Welcome back to our Scene Kit Tutorial with Swift series!

This tutorial series will show you how to create your first game with Scene Kit, Apple’s built-in 3D game framework.

In the first part of the series, you learned how to make an empty Scene Kit project as a good starting point.

In this second part of the series, you’ll get started making your game, learning about Scene Kit nodes along the way.

Let’s dive back in!

Note: This tutorial begins where the previous tutorial left off. If you didn’t follow along, no sweat – you can simply use the starter project for this tutorial.

Getting Started

Sprite Kit organizes the components of your game into a hierarchy known as the scene graph.

Each element of your game (such as lights, cameras, geometry, or particle emitters) is called a node and is stored in this tree-like structure.

To illustrate how this works, think back to a nursery rhyme you might have heard in your childhood…

🎵 The hip bone’s connected to the back bone 🎵 The back bone’s connected to the shoulder bone… 🎵

You’re right, it’s the classic song Dem Dry Bones! Bonus points if you can think of a classic video game that makes particularly good use of this ;]

With those lyrics in mind, take a look at the following anatomically-correct structure of a rare four-fingered skeleton:

Skeletons

To help illustrate how you could construct a node-based hierarchy from this skeleton, think of each bone in the skeleton as a node.

As the song points out, the shoulder bone’s connected to the back bone. So consider the back bone as the parent node of the shoulder bone, and the shoulder bone as the child node of the back bone.

To add the shoulder bone to the scene, you add it as a child of the back bone. You can continue to construct the whole arm in this way, adding child bones to parent bones, right up to the little pinky.

To position a bone, you position it relative to its parent. For example, to wave the skeleton’s left arm, you simply rotate the shoulder node back and forth as indicated by the little blue arrow. All child nodes of the shoulder node will rotate along with their parent.

Congratulations! You just passed skeleton anatomy 101! :]

Node in Code

From a technical perspective, a single node is represented by the SCNNode class and represents a position in 3D space relative to its parent node. A node on its own has no visible content and is invisible when rendered as part of a scene. To create visible content, you have to add other components such as lights, cameras or geometries (such as bones) to the node.

The scene graph contains a special node which forms the foundation of your node-based hierarchy: the root node. To construct your scene, you add your nodes either as child nodes of the root node or as a child of one of the root node’s descendants.

Scene Kit Asset Catalog

Once you’re a successful and rich 3D game designer, you’ll have enough money to hire your very own graphics artist and sound engineer, which will free you up to focus on the game code alone. :] The Scene Kit asset catalog has been designed specifically to help you manage your game assets separately from the code.

An asset catalog lets you manage your game assets in a single folder; to use it, simply add a folder with the .scnassets extension to your project and save all your game assets in that folder. Xcode will copy everything in your catalog to your app bundle at build time. Xcode preserves your assets folder hierarchy; this gives you full control over the folder structure.

By sharing your assets folder with your artists, they can quickly fix any issues, such as a not-quite-so-scary cross-eyed monster and have it ready for the next build – without having to copy the changed assets back into the project.

Now that you understand what the asset catalog is all about, you’ll add one to Geometry Fighter.

Drag and drop the GeometryFighter.scnassets folder from the tutorial resources into your game project in Xcode. In the popup that appears, make sure that Copy items if needed, Create Groups, and your GeometryFighter target are all checked, and click Finish.

CopySCNAssetsFolder0

Select the GeometryFighter.scnassets folder in your Project Navigator and note you can see some settings unique to the asset catalog in the right hand pane. Expand the GeometryFighter.scnassets folder and sub-folders to see more detail about your assets:

CopySCNAssetsFolder1

There are two folders inside the asset catalog: the Sounds folder contains all the sound assets you’ll need for your game, while the Textures folder contains all the images you’ll need. Feel free to take a sneak peek of what’s inside.

Adding the Launch Screen

Now that you’ve imported the asset catalog, you’ll take care of some basic housekeeping steps and add a proper image to the launch screen.

First, click Assets.xcassets in the project navigator. Drag and drop GeometryFighter.scnassets\Textures\Logo_Diffuse.png into the assets, below the AppIcon.

AddLogoToXCAssets

Next, click LaunchScreen.storyboard in the project navigator. Select the main view and set the Background property to a dark blue (or some other color you like):

SetViewBackgroundColor

Next, drag the Logo_Diffuse image from the Media Library into the center of the view. Set the Mode property of your new image to Aspect Fit:

AddLogoToView

You’re almost done with your launch screen; all that’s left is to add some constraints so that the splash image will work on all devices. Click the Pin button at the bottom, toggle the constraints on for all four edges and click Add 4 Constraints as shown below:

AddConstraints0

You’re done setting up your launch screen! Build and run your app; you’ll see your shiny new launch screen appear:

BuildAndRun0

Adding a Background image

Once your splash screen disappears, you’re dumped back to the black screen of opportunity. Time to add a nice clean background so you don’t feel like you’re staring into a black hole.

To do this, add the following line of code to the bottom of setupScene() in GameViewController.swift:

scnScene.background.contents = "GeometryFighter.scnassets/Textures/Background_Diffuse.png"

This line of code instructs the scene to load the Background_Diffuse.png image from the asset catalog and use it as the material property of the scene’s background.

Build and run; you should now see a blue background image once the game starts:

BuildAndRun1

You’ve finished all the basic housekeeping tasks for your project. Your game now has a flashy app icon, a splash screen, and a pretty background that’s all ready to display the nodes you’re about to add to the scene.

The Scene Kit Coordinate System

Before you can start adding nodes to the scene, you first need to understand how Scene Kit’s coordinate system works so you can position your nodes where you want them.

In a 2D system such as UIKit or Sprite Kit, you use a point to describe the position of a view or a sprite on the x and y axes. To place an object in 3D space, you also need to describe the depth of the object’s position on the z-axis.

Consider the following simple illustration:

CoordinateSystem

Scene Kit uses this three-axis system to represent position in 3D space. The red blocks are placed along the x-axis, the green blocks along the y-axis and the blue blocks along the z-axis. The grey cube in the very center of the axes indicates the origin, which has coordinates of (x:0, y:0, z:0).

Scene Kit uses the SCNVector3 data type to represent coordinates in three dimensions as a three-component vector. Here’s how you create a vector in code:

let position = SCNVector3(x: 0, y: 5, z: 10)

This declares the variable position with a vector of (x:0, y:5, z:10). You can easily access individual properties of the vector like so:

let x = position.x
let y = position.y
let z = position.z

If you’ve worked with CGPoint before, you can easily draw comparisons between it and SCNVector3.

Note: Nodes added to the scene have have a default position of (x:0, y:0, z:0), which is always relative to the parent node. To place a node at the desired location, you need to adjust the position of the node relative to its parent (local coordinates) – not the origin (world coordinates).

Working with Cameras

Now that you understand how to position nodes in Scene Kit, you’re probably wondering how to actually display something onscreen. Think back to the analogy of the movie set from Chapter 1: to shoot a scene, you’d position a camera looking at the scene and the resulting image of that scene would be from the camera’s perspective.

Scene Kit works in a similar fashion; the position of the node that contains the camera determines the point of view from which you view the scene.

The following illustration demonstrates how a camera works in Scene Kit:

CameraNode

There are a couple of key points in the previous diagram:

  • The camera’s direction of view is always along the negative z-axis of the node that contains the camera.
  • The field of view is the limiting angle of the viewable area of your camera. A tight angle provides a narrow view, while a wide angle provides a wide view.
  • The viewing frustum determines the visible depth of your camera. Anything outside this area – that is, too close or too far from the camera – will be clipped and won’t appear on the screen.

A Scene Kit camera is represented by SCNCamera, whose xPov and yPov properties let you adjust the field of view, while zNear and zFar let you adjust the viewing frustum.

One key point to remember is that a camera by itself won’t do anything unless it’s a part of the node hierarchy.

Adding the Camera

Let’s try this out. Open GameViewController.swift and add the following property below scnScene:

var cameraNode: SCNNode!

Next, add the following method below setupScene():

func setupCamera() {
  // 1
  cameraNode = SCNNode()
  // 2
  cameraNode.camera = SCNCamera()
  // 3
  cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
  // 4
  scnScene.rootNode.addChildNode(cameraNode)
}

Taking a closer look at the code:

  1. You first create an empty SCNNode and assign it to cameraNode.
  2. You next create a new SCNCamera object and assign it to the camera property of cameraNode.
  3. Then you set the position of the camera at (x:0, y:0, z:10).
  4. Finally, you add cameraNode to the scene as a child node of the scene’s root node.

Finish things off by calling the method you just added in viewDidLoad(), right below setupScene():

setupCamera()

There’s no need to build and run at this point in time, as you won’t see that anything’s changed. Even though your scene now has a camera, there’s still nothing to look at. To fix this, let’s add some actors to this scene.

Working with Geometry

In order to create visible content, you need to add a geometry object to a node. A geometry object represents a three-dimensional shape and is created of many points known as vertices.

Additionally, a geometry object can contain material objects that modify the appearance of a geometry’s surface. Materials let you specify information such as the color and texture of the geometry’s surface and how the geometry should respond to light along with other visual effects. A collection of vertices and materials is known as a model or a mesh.

Scene Kit includes the following built-in geometric shapes, also known as primitives:

PrimitiveGeometry

In the front row from the left, you have a cone, a torus, a capsule and a tube. In the back row from the left, you have a pyramid, a box, a sphere and a cylinder.

Note: You can provide your own custom geometry data, but you’ll cover this in later chapters.

Adding ShapeTypes

Before you start adding geometric shapes to the scene, create a new Swift file to define a ShapeType enum for the various different shapes you’ll use in the game.

Right-click on the GeometryFighter group and select New File…. Select the iOS\Source\Swift File template and click Next:

AddNewSwiftFile0

Name the file ShapeType.swift, make sure it’s included in your project, then click Create.

Once the file’s been created, open ShapeType.swift and replace its contents with the following:

import Foundation
 
// 1
public enum ShapeType:Int {
 
  case Box = 0
  case Sphere
  case Pyramid
  case Torus
  case Capsule
  case Cylinder
  case Cone
  case Tube
 
  // 2
  static func random() -> ShapeType {
    let maxValue = Tube.rawValue
    let rand = arc4random_uniform(UInt32(maxValue+1))
    return ShapeType(rawValue: Int(rand))!
  }
}

The code above is relatively straightforward:

  1. You create a new public enum ShapeType that enumerates the various shapes.
  2. You also define a static method random() that generates a random ShapeType. This feature will come in handy later on in your game.

Adding a Geometry Node

Your next task is to create a method that spawns the various random shapes defined in the ShapeType enumerator.

Add the following method to GameViewController.swift, right below setupCamera():

func spawnShape() {
  // 1
  var geometry:SCNGeometry
  // 2
  switch ShapeType.random() {
  default:
    // 3
    geometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
  }
  // 4
  let geometryNode = SCNNode(geometry: geometry)
  // 5
  scnScene.rootNode.addChildNode(geometryNode)
}

Taking each numbered comment in turn;

  1. First you create a placeholder geometry variable for use a bit later on.
  2. Next, you define a switch statement to handle the returned shape from ShapeType.random(). It’s incomplete at the moment and only creates a box shape; you’ll add more to it in the challenge at the end of this chapter.
  3. You then create an SCNBox object and store it in geometry. You specify the width, height, and length, along with the chamfer radius (which is a fancy way of saying rounded corners).
  4. This statement creates an instance of SCNNode named geometryNode. This time, you make use of the SCNNode initializer that takes a geometry parameter to create a node and automatically attach the supplied geometry.
  5. Finally, you add the node as a child of the scene’s root node.

You now need to call this method from somewhere. Add the following line to viewDidLoad() below setupCamera():

spawnShape()

Build and run; you’ll see a white square displayed onscreen:

BuildAndRun2

There’s a few things to observe here:

  • The box node is the default shape from spawnShape(), and sits at (x:0, y:0, z:0) in the scene.
  • You’re viewing the scene through your cameraNode. Since the camera node lives at (x:0, y:0: z:10), the box is smack dab in the center of the camera’s viewable area.

Yes, it’s not very exciting (and hardly three-dimensional looking), but fear not – the next section will change all that.

Using Built-in View Features

SCNView comes with a few out-of-the-box features that help make your life easier.

Add the following lines to setupView() in GameViewController.swift, just below the current implementation:

// 1
scnView.showsStatistics = true
// 2
scnView.allowsCameraControl = true
// 3
scnView.autoenablesDefaultLighting = true

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

  1. showStatistics enables a real-time statistics panel at the bottom of your scene.
  2. allowsCameraControl lets you manually control the active camera through simple gestures.
  3. autoenablesDefaultLighting creates a generic omnidirectional light in your scene so you don’t have to worry about adding your own light sources for the moment.

Build and run; things should look a little more exciting this time around!

BuildAndRun3

You can use the following gestures to control the active camera in your scene:

  • Single finger swipe: Rotates your active camera around the contents of the scene.
  • Two finger swipe: Moves, or pans your camera left, right, up or down in the scene.
  • Two finger pinch: Zooms the camera in and out of the scene.
  • Double-tap: If you have more than one camera, this switches between the cameras in your scene. Of course since you have only one camera this won’t don that. However, it also has the effect of resetting the camera to its original position and settings.

Challenge

At this point, I’ll leave you off with a challenge to practice what you learned: to improve the switch statement inside spawnShape() to handle the remaining shapes in the enumerator.

Use Apple’s official Scene Kit documentation as a guide to the various geometric shapes. Also take a look at the ShapeType enum to see which shapes are left to create; their names should give you a good idea of where to start.

Don’t worry too much about the sizes to use; just try to make them about the same relative size as the box you made earlier.

If you get this working, congratulations, you are getting a firm grasp of some of the most fundamental concepts in Scene Kit! :]

Where To Go From Here?

Here is the example code from this Scene Kit tutorial with Swift (with the challenge completed).

At this point, you should keep reading to the third part of this tutorial series, where you’ll learn how to make the geometry move via Scene Kit physics.

If you’d like to learn more, you should check out our book 3D iOS Games by Tutorials. The book teaches you everything you need to know to make 3D iOS games, by making a series of mini-games like this one, including a games like Breakout, Marble Madness, and even Crossy Road.

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

The post Scene Kit Tutorial with Swift Part 2: Nodes appeared first on Ray Wenderlich.


Video Tutorial: Advanced watchOS Part 7: Complications I

Scene Kit Tutorial with Swift Part 3: Physics

$
0
0
Note: This is an abbreviated chapter from the 3D iOS Games by Tutorials, to give you a sneak peek of what’s inside the book, released as part of 3D iOS Games by Tutorials Week. We hope you enjoy!

Thumb

Welcome back to our Scene Kit Tutorial with Swift series!

This tutorial series will show you how to create your first game with Scene Kit, Apple’s built-in 3D game framework.

In the first part of the series, you learned how to make an empty Scene Kit project as a good starting point.

In the second part of the series, you started making your game, learning about Scene Kit nodes along the way.

In this third part of the series, you’ll learn how to make your geometry move through the power of Scene Kit physics.

Let’s dive back in!

Note: This tutorial begins where the previous tutorial left off. If you didn’t follow along, no sweat – you can simply use the starter project for this tutorial.

Getting Started

Scene Kit’s physics engine is powerful, yet easy to use. You simply tell Scene Kit on which objects you want to apply physics; the engine will take over from that point and simulate things such as gravity and collisions for you.

Before you dive into integrating physics in your game, you’ll first need to add some some game utilities to your project.

The game utilities were created especially for you to make your life a little easier. These utilities include a bunch of helper methods that handle the complicated bits in your game to let you focus on the gameplay.

To add the game utilities, simply drag and drop the GameUtils folder from the tutorial resources into your project under the GeometryFighter group folder:

AddGameUtils0

Leave all the settings at their defaults and click Finish:

AddGameUtils1

This imports the entire GameUtils folder into your project as a group. Expand this folder and have a quick look at some of the helper methods, but don’t worry too much if some of the code doesn’t make sense to you yet.

Note: Build and run the project after you import GameUtils. If you get an error in loadSound(_:fileNamed:), you could be running an old Xcode version. To fix this, modify the line that gives you an error as follows: sound!.load().

Introducing Physics

Time for a quick status check of the current state of your game. Run up the game; a cool random geometric object spawns out of thin air like some kind of dark magic. This might not seem like much right now, but things will definitely start to “shape” up soon! :]

The freshly spawned object just hangs there in an empty space and doesn’t do much. Sure, you can rotate the camera around it and zoom in and out, but that’s about it. It’s not much of a fun game. To pump up the excitement level, it would be nice if the object at least moved around a little.

Now, you could take the long way around and manipulate the object’s position and rotation over time so that it spins and moves around. You’d soon realize that although it’s possible to animate objects in this manner, it requires a lot of coding effort, especially when you add other features like realistic collisions and interactions between objects to the mix.

Thankfully, the developers at Apple have already thought about this; to this end, they integrated a very powerful 3D physics engine into Scene Kit. To make use of this built-in physics engine, you simply need to make the engine aware of your object.

In the same way you attach geometry information to your node, you can attach a physics body to your node. The physics body describes all the physical properties of your node, which includes things such as shape, mass, friction, damping and restitution. The physics engine takes all this information into account when it simulates the real-world physics interactions of your objects. This includes things such as gravity, friction and collisions with other bodies within the physics world.

The next section details some of the important characteristics of a physics body.

Working with Physics Body Types

One of the key properties you must specify when creating a physics body is its type. The physics body’s type defines how the body interacts with forces and other bodies in the simulation.

There are three types used in Scene Kit:

  • Static bodies don’t move: while other objects can collide with these bodies, the static bodies themselves are unaffected by any forces and collisions in the simulation. You could use this type for things like walls and massive immobile boulders.
  • Dynamic bodies are affected by forces and collisions; you could use this type for things such as movable chairs, tables and cups.
  • Kinematic bodies are similar to static bodies, in that they are also unaffected by forces and collisions. However, you can move these types around and they can also collide with dynamic bodies. You could use this type of body for things such as moving elevators or a door that can open and close.

Working with Physics Shapes

In addition to the type of the body, another import property you must specify when creating a physics body is its shape. The physics shape defines the 3D shape used by the physics engine during collision detections. While the geometry defines the visuals of the node, the physics body defines how the node interacts with other objects in a physics simulation.

To let the physics simulation run as fast as possible, you should make use of simple geometries to define the physics shape. You’d typically set the physics shape to a simple bounding box, sphere, or one of the provided primitive shapes that roughly matches the node’s visible appearance like so:

PhysicsShapes

Adding Physics

Now that you’ve learned the theory behind the physics, it’s time to start using these concepts to move things around in your game.

In Scene Kit, all the physics bodies are SCNPhysicsBody objects. You can then assign the bodies to the physicsBody property of the SCNNode instance that will use that physics body. Once you’ve assigned the physics body, the physics engine can then simulate the physics for you. It’s that simple! :]

Open GameViewController.swift and add the following after the line of code that creates geometryNode in spawnShape():

geometryNode.physicsBody = SCNPhysicsBody(type: .Dynamic, shape: nil)

This line of code creates a new instance of SCNPhysicsBody and assigns it to the physicsBody property of geometryNode. When you create a physics body, you specify the type and shape the body should have. If you pass in nil for the physics shape, Scene Kit will automatically generate a shape based on the geometry of the node. Neat, huh?

If you want to add more detail to the physics shape, you could create a SCNPhysicsShape and use that for the shape instead of passing in nil.

Build and run your game; a random shape spawns into the scene, and then drops out of the air with all the grace of a dead bird, falling out of sight:

BuildAndRun0

You can even pan the camera to watch the object fall into oblivion. What you’re witnessing here is the effect of gravity acting on the object. A scene in Scene Kit has gravity turned on by default. Now that the spawned object has a physics body, the physics simulation will apply simulated forces such as gravity to the object.

Working with Forces

Think about objects in real life for a moment: to make something move, such as a spoon on top of a table, you have to apply some sort of physical force on it. Unless you’re living inside the Matrix, your name is Neo, and there isn’t even an actual spoon to begin with. :]

The Scene Kit physics engine does a pretty good job mimicking real-life physics, so just as you’d apply a force to move an object in real life, you’ll need to apply a force on your physics body to move it around.

When you apply a force to a physics body, you use applyForce(_: atPosition: impluse:) and pass in an instance of SCNVector3 for both the force and the position where you want to apply that force, along with whether or not the force will be applied as an impulse. The force that you apply will affect both the linear and angular acceleration of the physics body.

An impulse applies the force only once to the physics body, such as when you kick a ball. Forces that aren’t impulses are applied at each step in the physics simulation. Scene Kit will add up all applied forces on the object and accelerate the physics body according to the net result of those forces. This can simulate something like a booster rocket, where the force is continuous.

Earlier you learned that a force is a vector with an x, y and z component. But what does that mean? Take a look at the diagram below:

ForceVector

A force has both magnitude and direction, so the vector determines the magnitude of the force for each individual axis. In the example above, applying a force with a vector of (x:0, y:10, z:0) moves the body upwards with a vertical force.

To apply a horizontal force, you would only specify the magnitude of the force on the x axis using a vector of (x:10, y:0, z:0). To move the body left instead of right, you would apply a negative magnitude of force on the x axis. When you combine various vectors together like (x:10, y:10, z:0), you can control exactly how you want the body to move – in this case, diagonally.

Forces can also be applied at a specific position on a physics body to produce different movements:

ForceAtLocation

Again, it helps to think of real-life examples. If you had a block in front of you and pushed it, the block would move differently depending on the spot you applied the push. Applying the same force to the left or right of the body’s center of mass, for example, at (x:1, y:0, z:0) would cause it to spin. Applying the force directly in line with the center of mass at (x:0, y:0, z:0) won’t produce a spin.

Applying Forces

Roll up your sleeves – it’s time to apply some force! :]

Add the following code after the line where you create the physics body for geometryNode inside spawnShape():

// 1
let randomX = Float.random(min: -2, max: 2)
let randomY = Float.random(min: 10, max: 18)
// 2
let force = SCNVector3(x: randomX, y: randomY , z: 0)
// 3
let position = SCNVector3(x: 0.05, y: 0.05, z: 0.05)
// 4
geometryNode.physicsBody?.applyForce(force, atPosition: position, impulse: true)

Taking each commented line in turn:

  1. This creates two random float values that represent the x- and y-components of the force. It uses an extension on Float from the utilities you added earlier in this chapter.
  2. Next, you use those random components to create a vector to represent this force.
  3. This creates another vector that represents the position the force will be applied to. The position is slightly off-center so as to create a spin on the object.
  4. Finally, using all those components, you apply the force to geometryNode‘s physics body using applyForce(_: atPosition: impluse).

Build and run; as the object spawns out of thin air, some magical force kicks it up into the air instead of dropping like a dead bird:

BuildAndRun1

As gravity takes its toll, the object eventually falls back down.

Working with Torque

Torque is another rotational force you can apply to a body using applyTorque(_: impulse:). Torque only affects the angular momentum of the physics body, not the linear momentum. Applying torque causes an object to spin around its center of mass.

To see how torque affects a physics body, take a look at the following illustration:

TorqueAngles

When applying a torque force, you specify a four-component vector using SCNVector4 rather than a three-component vector as you do with forces. The x-, y- and z-components determine the rotation axis, while the w-component determines the rotation angle, that is, the magnitude of the torque.

Just as you do with applyForce(_: atPosition: impulse:), you can choose whether or not to apply the torque as an impulse, which affect how the physics engine treats the vector.

If the torque is an impulse, the directional vector is treated as an instantaneous change in the angular momentum. Think of spinning a basketball on your finger; to keep the ball spinning, you have to quickly flick the side of the ball with you hand, which applies an a impulse with each flick that instantaneously increases the angular momentum of the ball.

When a torque is not applied as in impulse, it’s applied after each physics simulation step. Scene Kit will sum all applied forces and torques and accelerate the angular force of the physics body according to the net effect of those forces. Think of this as a planet spinning at a constant speed around its own axis.

Note: The Scene Kit physics simulation uses the International System of Units (SI) for measurements: Kilograms for units of mass, Newtons for units of force, Newton-second for units of impulse, and Newton-meter for units of torque.

Adding some Flair

Now that you’ve got your geometric object moving, you may have noticed it spawns out of thin air right in the middle of the screen, which looks a bit awkward. To fix that, you’ll shift the camera on the y-axis a bit so that the object spawns off-screen.

Positioning the Camera

To move the camera position up, replace the line where you set the camera’s position in setupCamera() with the following:

cameraNode.position = SCNVector3(x: 0, y: 5, z: 10)

Build and run, and you’ll see that the object appears to spawn off-screen!

Offscreen

Adding Color

As a final touch, you’ll add a bit of variety to your randomly generated shapes.

Add the following lines inside spawnShape(), after the spot where you randomly create geometry, but just before you create geometryNode:

geometry.materials.first?.diffuse.contents = UIColor.random()

To color your random object, you modify materials on geometry; this line gets the first available material of geometry and sets the diffuse property’s contents to a random UIColor. The random() method on UIColor is another helper defined as an extension inside the game utilities.

Note: You’ll learn more about materials and their properties in Section II of this book. The takeaway here is that you can assign a UIColor to the diffuse property’s content in order to change the object’s color.

Finally, build and run your game to see a beautifully colored object:

BuildAndRun2

Wouldn’t it be neat if you could spawn more than one object? You’ll fix this…in the next part of the series! :]

Where To Go From Here?

Here is the example code from this Scene Kit tutorial with Swift.

At this point, you should keep reading to the fourth part of this tutorial series, where you’ll learn how to make geometry spawn over time using the Scene Kit render loop.

If you’d like to learn more, you should check out our book 3D iOS Games by Tutorials. The book teaches you everything you need to know to make 3D iOS games, by making a series of mini-games like this one, including a games like Breakout, Marble Madness, and even Crossy Road.

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

The post Scene Kit Tutorial with Swift Part 3: Physics appeared first on Ray Wenderlich.

Scene Kit Tutorial with Swift Part 4: Render Loop

$
0
0
Note: This is an abbreviated chapter from the 3D iOS Games by Tutorials, to give you a sneak peek of what’s inside the book, released as part of 3D iOS Games by Tutorials Week. We hope you enjoy!

Thumb

Welcome back to our Scene Kit Tutorial with Swift series!

This tutorial series will show you how to create your first game with Scene Kit, Apple’s built-in 3D game framework.

In the first part of the series, you learned how to make an empty Scene Kit project as a good starting point.

In the second part of the series, you started making your game, learning about Scene Kit nodes along the way.

In the third part of the series, you learned how to make your geometry move through the power of Scene Kit physics.

In this fourth part of the series, you’ll learn how to make your geometry spawn over time through the Scene Kit render loop.

Let’s dive back in!

Note: This tutorial begins where the previous tutorial left off. If you didn’t follow along, no sweat – you can simply use the starter project for this tutorial.

Getting Started

In the previous tutorial, you enabled basic physics for your spawned object and applied an impulse to kick it up into the air. Eventually, the object fell back down due to the simulated effect of gravity and disappeared into the abyss.

Although the effect is neat, it would be so much cooler to spawn multiple objects that collide with each other. That would certainly push the excitement factor up a notch!

Right now, your game calls spawnShape() just once. To spawn multiple objects you’ll need to call spawnShape() repeatedly. Introducing…the Render Loop!

As you learned in previous chapters, Scene Kit renders the contents of your scene using an SCNView object. SCNView has a delegate property that you can set to an object that conforms to the SCNSceneRendererDelegate protocol, and SCNView will then call methods on that delegate when certain events occur within the animation and rendering process of each frame.

In this way, you can tap into the steps Scene Kit takes to render each frame of a scene. These rendering steps are what make up the render loop.

So – what exactly are these steps? Well, here’s a quick breakdown of the render loop:

RenderLoop

Is this Wheel of Fortune? :] No, it’s simply a depiction of the nine steps of the render loop. In a game that runs at 60 fps, these steps run… you guessed it… 60 times a second.

The steps always execute in the following order, which lets you inject your game logic exactly where it’s needed:

  1. Update: The view calls renderer(_: updateAtTime:) on its delegate. This is a good spot to put basic scene update logic.
  2. Execute Actions & Animations: Scene Kit executes all actions and performs all attached animations to the nodes in the scene graph.
  3. Did Apply Animations: The view calls its delegate’s renderer(_: didApplyAnimationsAtTime:). At this point, all the nodes in the scene have completed one single frame’s worth of animation, based on the applied actions and animations.
  4. Simulates Physics: Scene Kit applies a single step of physics simulation to all the physics bodies in the scene.
  5. Did Simulate Physics: The view calls renderer(_: didSimulatePhysicsAtTime:) on its delegate. At this point, the physics simulation step has completed, and you can add in any logic dependent on the physics applied above.
  6. Evaluates Constraints: Scene Kit evaluates and applies constraints, which are rules you can configure to make Scene Kit automatically adjust the transformation of a node.
  7. Will Render Scene: The view calls renderer(_: willRenderScene: atTime:) on its delegate. At this point, the view is about to render the scene, so any last minute changes should be performed here.
  8. Renders Scene In View: Scene Kit renders the scene in the view.
  9. Did Render Scene: The final step is for the view to call its delegate’s renderer(_: didRenderScene: atTime:). This marks the end of one cycle of the render loop; you can put any game logic in here that needs to execute before the process starts anew.

Because the render loop is, well, a loop, it’s the perfect place to call to spawnShape() – your job is to decide where to inject the spawn logic.

Adding the Renderer Delegate

It’s time to put this cool feature to use in your game.

First, make the GameViewController class conform to the SCNSceneRendererDelegate protocol by adding the following to the bottom of GameViewController.swift:

// 1
extension GameViewController: SCNSceneRendererDelegate {
  // 2
  func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
    // 3
    spawnShape()
  }
}

Taking a closer look at the code above:

  1. This adds an extension to GameViewController for protocol conformance and lets you maintain code protocol methods in separate blocks of code.
  2. This adds an implemention of the renderer(_: updateAtTime:) protocol method.
  3. Finally, you call spawnShape() to create a new shape inside the delegate method.

This give you your first hook into Scene Kit’s render loop. Before the view can call this delegate method, it first needs to know that GameViewController will act as the delegate for the view.

Do this by adding the following line to the bottom of setupView():

scnView.delegate = self

This sets the delegate of the Scene Kit view to self. Now the view can call the delegate methods you implement in GameViewController when the render loop runs.

Finally, clean up your code a little by removing the single call to spawnShape() inside viewDidLoad(); it’s no longer needed since you’re calling the function inside the render loop now.

Build and run; unleash the spawning fury of your render loop! :]

BuildAndRun0

The game starts and spawns an insane amount of objects, resulting in a moshpit of colliding objects – awesome! :]

So what’s happening here? Since you’re calling spawnShape() in every update step of the render loop, you’ll spawn 60 objects per second – if the device you’re running on can support your game at 60 fps. But less-powerful devices, which includes the simulator, can’t support that frame rate.

As the game runs, you’ll notice a rapid decrease in the frame rate. Not only does the graphics processor have to deal with increasing amounts of geometry, the physics engine has to deal with an increasing number of collisions, which also negatively affects your frame rate.

Things are a bit out of control at the moment, as your game won’t perform terribly well on all devices.

Adding a Spawn Timer

To make the gaming experience consistent across devices, you need to make use of time. No, I don’t mean taking more time to write your game! :] Rather, you need to use the passage of time as the one constant across devices; this lets you animate at a consistent rate, regardless of the frame rate the device can support.

Timers are a common technique in many games. Remember the updateAtTime parameter passed into the update delegate method? That parameter represents the current system time. If you monitor this parameter, you can calculate things like the elapsed time of your game, or spawn a new object every three seconds instead of as fast as possible.

Geometry Fighter will use a simple timer to spawn objects at randomly timed interval that any processor should be able to handle.

Add the following property to GameViewController below cameraNode:

var spawnTime:NSTimeInterval = 0

You’ll use this to determine time interval until you spawn another shape.

To fix the continuous spawning, replace the entire body of renderer(_: updateAtTime:) with the following:

// 1
if time > spawnTime {
  spawnShape()
 
  // 2
  spawnTime = time + NSTimeInterval(Float.random(min: 0.2, max: 1.5))
}

Taking each commented line in turn:

  1. You check if time (the current system time) is greater than spawnTime. If so, spawn a new shape; otherwise, do nothing.
  2. After you spawn an object, update spawnTime with the next time to spawn a new object. The next spawn time is simply the current time incremented by a random amount. Since NSTimeInterval is in seconds, you spawn the next object between 0.2 seconds and 1.5 seconds after the current time.

Build and run; check out the difference your timer makes:

BuildAndRun1

Mesmerizing, eh?

Things look a bit more manageable, and the shapes are spawning randomly. But aren’t you curious about what happens to all those objects after they fall out of sight?

Cleaning up Your Scene

spawnShape() continuously adds new child nodes into the scene – but they’re never removed, even after they fall out of sight. Scene Kit does an awesome job of keeping things running smoothly for as long as possible, but that doesn’t mean you can forget about your children. What kind of parent are you?! :]

To run at an optimal performance level and frame rate, you’ll have to remove objects that fall out of sight. And what better place to do this than – that’s right, the render loop! Handy thing, isn’t it?

Once an object reaches the limits of its bounds, you should remove it from the scene.

Add the following to the end of your GameViewController class, right below spawnShape():

func cleanScene() {
  // 1
  for node in scnScene.rootNode.childNodes {
    // 2
    if node.presentationNode.position.y < -2 {
      // 3
      node.removeFromParentNode()
    }
  }
}

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

  1. Here you simply create a little for loop that steps through all available child nodes within the root node of the scene.
  2. Since the physics simulation is in play at this point, you can’t simply look at the object’s position as this reflects the position before the animation started. Scene Kit maintains a copy of the object during the animation and plays it out until the animation is done. It’s a strange concept to understand at first, but you’ll see how this works before long. To get the actual position of an object while it’s animating, you leverage the presentationNode property. This is purely read-only: don’t attempt to modify any values on this property!
  3. This line of code makes an object blink out of existence; it seems cruel to do this to your children, but hey, that’s just tough love.

To use your method above, add the following line to call cleanScene() just after the if statement inside renderer(_: updatedAtTime:):

cleanScene()

There’s one last thing to add: by default, Scene Kit enters into a “paused” state if there aren’t any animations to play out. To prevent this from happening, you have to enable the playing property on your SCNView instance.

Add the following line of code to the bottom of setupView():

scnView.playing = true

This forces the Scene Kit view into an endless playing mode.

Build and run; as your objects start to fall, pinch to zoom out and see where they disappear into nothingness:

BuildAndRun2

Objects that fall past the lower y-bound (noted by the red line in the screenshot above), are removed from the scene. That’s better than having all those objects lying around the dark recesses of your iPhone. :]

Where To Go From Here?

Here is the example code from this Scene Kit tutorial with Swift.

At this point, you should keep reading to the fifth and final part of this tutorial series, where you’ll add some particle systems and wrap up the game.

If you’d like to learn more, you should check out our book 3D iOS Games by Tutorials. The book teaches you everything you need to know to make 3D iOS games, by making a series of mini-games like this one, including a games like Breakout, Marble Madness, and even Crossy Road.

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

The post Scene Kit Tutorial with Swift Part 4: Render Loop appeared first on Ray Wenderlich.

POP in Practice, and RWDevCon ’16 – Podcast S05 E10

$
0
0
rwdevcon

Curious about how great was RWDevCon ’16 was? Find out in this episode!

Join Mic, Jake, and Andrew as they discuss putting Protocol-orientated Programming into practice, before looking back at RWDevCon ’16 and just what makes the conference so unique.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

This episode was brought to you by the kind folks over at WillowTree.

WillowTree is a new breed mobile engagement partner focused on creating great software to improve users’ lives, and they’re hiring!

Much more than a mobile app development company, they work with clients such as GE, Johnson & Johnson, Pepsi and the NBA to create the best mobile experiences possible. WillowTree excel at bleeding-edge projects that allow them to push boundaries and challenge themselves to keep evolving.

How do they do it? They hire the smartest and most passionate people in the industry, and give them what they need to keep growing and learning. WillowTree have all the perks of other leading development shops, but what makes them unique is their “maker” culture, which gives great designers and developers the freedom to produce incredible results.

Visit willowtreeapps.com/careers to find out more!

Interested in sponsoring a podcast episode? We sell ads via Syndicate Ads, check it out!

Show Notes

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Be sure to subscribe in iTunes to get notified when the next episode comes out.

We’d love to hear what you think about the podcast, and any suggestions on what you’d like to hear in future episodes. Feel free to drop a comment here, or email us anytime at podcast@raywenderlich.com.

The post POP in Practice, and RWDevCon ’16 – Podcast S05 E10 appeared first on Ray Wenderlich.

Scene Kit Tutorial with Swift Part 5: Particle Systems

$
0
0
Note: This is an abbreviated chapter from the 3D iOS Games by Tutorials, to give you a sneak peek of what’s inside the book, released as part of 3D iOS Games by Tutorials Week. We hope you enjoy!

Thumb

Welcome back to our Scene Kit Tutorial with Swift series!

This tutorial series will show you how to create your first game with Scene Kit, Apple’s built-in 3D game framework.

In the first part of the series, you learned how to make an empty Scene Kit project as a good starting point.

In the second part of the series, you started making your game, learning about Scene Kit nodes along the way.

In the third part of the series, you learned how to make your geometry move through the power of Scene Kit physics.

In the fourth part of the series, you learned how to make your geometry spawn over time through the Scene Kit render loop.

In this fifth and final part of the series, you’ll add some cool particle systems to the game and wrap it up along the way! :]

Let’s dive back in!

Note: This tutorial begins where the previous tutorial left off. If you didn’t follow along, no sweat – you can simply use the starter project for this tutorial.

Getting Started

Picture yourself in the movie theatre, popcorn in hand; on the screen, a bad guy from The Fast and the Furious smashes his roaring, high-performance dragster into a highly volatile fuel tanker which explodes in a massive fireball of death and carnage. Yeah! :]

Now think of that same scene, but without the massive fireball explosion: you can almost feel the collective disappointment of audiences around the world. :[

Just like a Hollywood blockbuster, your game needs special effects to amp up the excitement level; these special effects come in the form of what’s known as particle systems. You can use particle systems for a multitude of effects, from moving star fields, to burning rocket boosters, to rain and snow, to metal sparks – and yes, even massive exploding fireballs!

Let’s take a look at how you can add some of these neat special effects to Geometry Fighter.

SCNParticleSystem

In Scene Kit, SCNParticleSystem manages the creation, animation and removal of particles from the scene graph.

A particle is essentially a small image sprite. The particle system doesn’t add the individual particles into the scene graph itself, so you don’t have direct access to each particle – the particle system manages the particles and their look, size, and location.

However, you can influence the particle system by modifying various properties on it, such as:

  • Appearance: Each particle of the system can be rendered as a single image, or an animated sequence of images. You can adjust the size, tint color, blending mode and other rendering parameters of the particles generated.
  • Life Span: The system uses a particle emitter, which gives birth to each individual particle. The lifespan of the particle determines how long it stays visible in the scene.
  • Emitter behavior: You can control various parameters of the emitter, such as where particles spawn and the spawn rate.
  • Variation: Introducing variations into your particle system can make it look more, or less, random.
  • Movement: You can adjust how particles move once they’ve spawned. Particles use a simplified physics simulation to speed up performance, but the particles can still interact with objects managed by the physics engine.
Note: You can find the starter project for this chapter under the /starter/Geometry Fighter/ folder, or carry on with the completed project from the last chapter.

Particle System Editor

Before you add a particle system to your game world, you’ll need a group to house this particle system to keep your project organized. Right-click on the GeometryFighter group and select New Group, like so:

CreateParticlesGroup0

Name this new group Particles. Right-click on the group and select New File. Select the iOS\Resource\SceneKit Particle System template and click Next to continue:

AddParticleSystem0

On the next screen, select Fire for Particle system template then click Next. Save the file as Trail.scnp and click Create. Once you’re done, you should see the following in your scene:

AddParticleSystem1

Hot stuff! :] Say “hello” to Xcode’s built-in particle system editor.

Here’s a quick overview of the various sections of the editor as annotated above:

  1. Center Stage: The center holds a visual representation of your particle system. You can use this to get an idea of what the end result will look like.
  2. Gesture Controls: You can use gestures to manipulate the camera view; it’s similar to how you’d move the camera around in a scene.
  3. Pause/Play Button: You can pause your particle system simulation and inspect it in more detail. While paused, the pause button changes to a play button you can use to resume the simulation.
  4. Restart Button: This lets you restart your particle simulation from the beginning.
  5. Camera Reset Button: Use this to reset your camera view to its default position.
  6. Color Button: This lets you set an appropriate background color for your editor; for example, it’s easier to see snowflakes against a black background.
  7. Particle System Properties: Selecting the Attributes Inspector reveals a host of properties which you’ll learn about in the next section.

Configuring the Trail Particle System

In this section, you’ll take an in-depth look at the particle system attributes on the right-hand side of the editor. As you go through each section, copy the values of each setting in the screenshots into your own particle system.

Keep an eye on the particle system editor as you change each attribute; you’ll see how each parameter affects the behavior of the particle system. Later on, you’ll use this particle effect in your game to create a trail of particles falling from your spawned objects.

Emitter Attributes

The particle emitter is the origin from where all particles spawn. Here’s the emitter attributes:

TrailParticleSettings0

  • Birth rate: Controls the emitted rate of particles. Set this to 25, instructing the particle engine to spawn new particles at a rate of 25 particles per second.
  • Warmup duration: The amount of seconds the simulation runs before it renders particles. This can be used to display a screen full of particles at the start, instead of waiting for the particles to fill the screen. Set this to 0 so that simulation can be viewed from the very beginning.
  • Location: The location, relative to the shape, where the emitter spawns its particles. Set this to Vertex, which means the particles will use the geometry vertices as spawning locations.
  • Emission space: The space where emitted particles will reside. Set this to World Space so that the emitted particles are emitted into the world space, and not the local space of the object node itself.
  • Direction mode: Controls how spawned particles travel; you can move them all in a constant direction, have them travel radially outwards from the surface of the shape, or simply move them in random directions. Set it to Constant, keeping all emitted particles moving in a constant direction.
  • Direction: Specifies a directional vector to use when direction mode is constant. Set this vector to (x: 0, y: 0, z:0), setting the direction to nothing.
  • Spreading angle: Randomizes the emitting angle of spawned particles. Set this to , thus emitting particles exactly in the previously set direction.
  • Initial angle: The initial angle at which to emit particles. Set this to as this does not matter with a zero direction vector.
  • Shape: The shape from which to emit particles. Set the shape up as a Sphere, thus using a sphere shape as the geometry.
  • Shape radius: This existence of this attribute depends on which shape you’re using; for an spherical emitter, this determines the size of the sphere. Set this to 0.2, which defines a sphere just large enough for what you need.
Note: Note that some of the attributes have two input areas, one of which has a Δ= symbol next to it (see Birth Rate and Initial angle). The first input area contains the base value, and the Δ= input area contains the delta value. Each time a particle is spawned, it uses the base value plus a random value in the range (-delta value, +delta value). This allows you to get some random variance for these properties.

Simulation Attributes

The simulation attributes manage the motion of particles over their lifetimes. This lets you manage their movement without having to use the physics engine:

TrailParticleSettings1

  • Life span: Specifies the lifetime of a particle in seconds. Set this to 1, so that a single particle will only exist for a total time of a single second.
  • Linear velocity: Specifies the linear velocity of the emitted particles. Set this to 0, the particles are spawned with no direction or velocity.
  • Angular velocity: Specifies the angular velocity of the emitted particles. Set this to 0, the particles will not be spinning.
  • Acceleration: Specifies the force vector applied to the emitted particles. Set this to (x: 0, y: -5, z: 0), which is a downwards vector, simulating a soft gravity effect on the particles once spawned.
  • Speed factor: A multiplier that sets the speed of the particle simulation. Set this to 1, running the simulation at a normal speed.
  • Stretch factor: A multiplier that stretches particles in their direction of motion. Set this to 0, keeping the particle image un-stretched.

Image Attributes

The image attributes control the visual aspects of the particles. They also govern how the appearance of those particles can change over their lifetimes:

TrailParticleSettings2

  • Image: Specifies an image with which each particle will be rendered. Select the CircleParticle.png image, giving the particle its primary shape.
  • Color: Sets the tint of the specified image. Set the color to White, giving the particle system a base color of white.
  • Animate color: Causes particles to change color over their lifetimes. Un-check this, because the particle color is not going to change at all.
  • Color variation: Adds a bit of randomness to the particle color. You can set this to (h: 0, s: 0, b: 0, a: 0), because the particle color will not vary.
  • Size: Specifies the size of the particles. Set this to 0.1, so that the emitted particles are small in size.

Image Sequence Attributes

To create an animated image for your particles, you arrange each frame of the animation into a grid on a single image (like a sprite sheet in a game). Then you simply use that grid image as the image for your particle emitter. The image sequence attributes let you control the basic animation properties of the particle:

TrailParticleSettings3

  • Initial frame: Sets the first zero-based frame of the animation sequence. The zeroth frame corresponds to the top left image in the grid. You’re using a single frame image, so set this to 0.
  • Frame rate: Controls the rate of the animation in frames per second. Set this to 0, it only applies when using an image containing multiple frames.
  • Animation: Specifies the behaviour of the animation sequence. Repeat loops the animation, Clamp only plays once, and Auto Reverse plays from the start to the end, then back again. You can leave this on Repeat, it doesn’t matter when using a single frame image.
  • Dimensions: Specifies the number of rows and columns in the animation grid. Set this to (Rows: 1, Columns: 1), because you’re using a single frame image.

Rendering Attributes

The rendering attributes define how the render phase treats the particles:

TrailParticleSettings4

  • Blending: Specifies the blend mode of the renderer when drawing the particles into the scene. Set this to Alpha, which will use the image alpha channel information for transparency.
  • Orientation: Controls the rotation of the particles. Set this to Billboard screen-aligned, which will keep the flat particles facing the camera view at all times, so you won’t notice that the particles are indeed flat images.
  • Sorting: Sets the rendering order of the particles. This property works in conjunction with the blend mode and affects how the blending is applied. Set this to None, the particle system will not make use of sorting.
  • Lighting: Controls whether Scene Kit applies lighting to the particles. Un-check this, so that the particle system ignores any lights in the scene.

Physics Attributes

The physics attributes let you specify how particles behave in the physics simulation:

TrailParticleSettings5

  • Affected by gravity: Causes the scene’s gravity to affect the particles. Un-check this, you don’t want the particle system to participate in the physics simulation.
  • Affected by physics fields: Causes physics fields within the scene to affect the particles. Un-check this, you don’t want physics fields to have an effect on the particles.
  • Die on Collision: Lets physics bodies in your scene collide and destroy the particles. Un-check this, you don’t want particles to be removed when they collide with node objects in the scene.
  • Physics Properties: Basic physics properties that control the physics behaviour of the particles during the physics simulation. You can leave all these at their default values, because the particle system will not make use of this.

Life Cycle Attributes

The life cycle attributes let you control the overall life cycle of your particle system:

TrailParticleSettings6

  • Emission Duration: Controls the length of time that the emitter will emit new particles. Set this to 1, which will activate the particle emitter for a total length of 1 second.
  • Idle Duration: Looping particle systems emit particles for the specified emission duration, then become idle for the specified idle duration, after which the cycle repeats. Set this to 0, the particle system will only emit once.
  • Looping: Specifies whether the particle system emits particles once, as in an explosion, or continously, as a volcano would. Set this to Loops continuously, so that the emitter emits for as long as it can before it is removed from the scene again.

Phew! There are a lot of attributes to consider for a single particle system, but this gives you a lot of control to get the exact special effect you’re looking for.

If you diligently copied over the values from the screenshots to your particle system, you will have a system that represents the following effect:

TrailParticleSystem

If yours doesn’t look like this, try rotating the camera. It might also help to change the background color to a dark blue like you see here to make the particle system easier to see.

Adding the Trail Particles

It’s finally time to add the cool particle effect to your game. Add the following to your GameViewController.swift class:

// 1
func createTrail(color: UIColor, geometry: SCNGeometry) -> SCNParticleSystem {
  // 2
  let trail = SCNParticleSystem(named: "Trail.scnp", inDirectory: nil)!
  // 3
  trail.particleColor = color
  // 4
  trail.emitterShape = geometry
  // 5
  return trail
}

Here’s what’s going on above:

  1. This defines createTrail(_: geometry:) which takes in color and geometry parameters to set up the particle system.
  2. This loads the particle system from the file you created earlier.
  3. Next, you modify the particle’s tint color based on the parameter passed in.
  4. This uses the geometry parameter to specify the emitter’s shape.
  5. Finally, this returns the newly created particle system.

This method helps you create instances of SCNParticleSystem, but you still need to add the particle systems to your spawned shape objects.

Note that createTrail(_: geometry:) takes in a color parameter and uses it to tint the particles. You will set the color of the particle system to be the same as the color of the shape.

Find the line in spawnShape() where you set the shape’s material diffuse contents and split it up so that the random color is stored in a constant like so:

let color = UIColor.random()
geometry.materials.first?.diffuse.contents = color

Next, add the following lines further down in spawnShape(), just after you apply a force to the physics body of geometryNode:

let trailEmitter = createTrail(color, geometry: geometry)
geometryNode.addParticleSystem(trailEmitter)

This uses createTrail(_: geometry:) to create a particle system and attach it to geometryNode.

Build and run; take a look at your hard work in action!

BuildAndRun0

Woot! :] It looks great – but what would really make this shine is a heads-up display.

Adding a Heads-up Display

In this short section you’ll use the Game Utils to quickly add a little heads-up display to show your player’s remaining lives, best score, and current score. The code behind the scenes uses a Sprite Kit label and uses the output of the label as a texture for a plane.

Add the following new property to GameViewController.swift, right below spawnTime:

var game = GameHelper.sharedInstance

This lets you quickly access the GameHelper shared instance, which contains a set of methods to do the heavy lifting for you.

Add the following method to the bottom of GameViewController, below createTrail():

func setupHUD() {
  game.hudNode.position = SCNVector3(x: 0.0, y: 10.0, z: 0.0)
  scnScene.rootNode.addChildNode(game.hudNode)
}

Here you make use of game.hudNode from the helper library. You set its the HUD node’s position and add it to the scene.

Next, you need to call setupHUD() from somewhere. Add the following line to the bottom of viewDidLoad():

setupHUD()

Now that you have a heads-up display, you need to keep it up to date. Add the following call to game.updateHUD() to the bottom of renderer(_: updateAtTime:)

game.updateHUD()

Build and run; you’ll see your display at the top of the screen as shown below:

BuildAndRun1

Your game now has a nifty little HUD with a life counter, the high score and the current score.

Okay, the heads-up display is nice, but it’s high time to add some interaction to your game.

Adding Touch Handling

As is usually the case, enabling touch in your app isn’t as straightforward as one would hope.

The first step is to understand how touch handling works in 3D. The image below shows a touch point in a side view of your scene and how Scene kit translates that touch point into your 3D scene to determine which object you’re touching:

3DPicking

So what steps do you take to handle the user’s touch event?

  1. Get Touch Location. First, you need to get the location of the user’s touch on the screen.
  2. Convert to View Coordinates. After that, you need to translate that touch location to a location relative to the SCNView instance that’s presenting the scene.
  3. Fire a Ray for a Hit Test. Once you’ve established a touch location relative to the view, Scene Kit can perform a hit test for you by firing off a ray (No, not that Ray! :]) into your scene and returning a list of objects that intersect with the ray.

Naming Nodes

Before you can activate the touch ray of death, you need a way to identify each spawned object. The simplest approach is to give them names.

Add following to spawnShape(), right after you add the particle system to geometryNode:

if color == UIColor.blackColor() {
  geometryNode.name = "BAD"
} else {
  geometryNode.name = "GOOD"
}

True to the spirit of the black-hatted villains of old Western movies, you assign the moniker "BAD" to black-colored objects and "GOOD" to all others.

Adding a Touch Handler

Next you need to write a method that you will later call when you detect that the user has tapped a particular node.

Add the following method to the bottom of GameViewController, below setupHUD():

func handleTouchFor(node: SCNNode) {
  if node.name == "GOOD" {
    game.score += 1
    node.removeFromParentNode()
  } else if node.name == "BAD" {
    game.lives -= 1
    node.removeFromParentNode()
  }
}

This method checks the moniker of the touched node; good nodes increase the score and bad (black) nodes reduce the number of lives by one. In either case, you remove the node from the screen as it’s destroyed.

Using the Touch Handler

To capture the user’s touches, you’ll use touchesBegan(_: withEvent:), which is called every time the player touches the screen.

To implement your own version, add the following to GameViewController, right below handleTouchFor(_:):

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  // 1
  let touch = touches.first!
  // 2
  let location = touch.locationInView(scnView)
  // 3
  let hitResults = scnView.hitTest(location, options: nil)
  // 4
  if hitResults.count > 0 {
    // 5
    let result = hitResults.first!
    // 6
    handleTouchFor(result.node)
  }
}

Taking each numbered comment in turn:

  1. Grab the first available touch.
  2. Translate the touch location to a location relative to the coordinates of scnView.
  3. hitTest(_: options:) gives you an array of SCNHitTestResult objects that represent any intersections that hit ray starting from the spot inside the view that the user touched, and going away from the camera.
  4. Check if there are any results from the hit test.
  5. If there are, take the first result in the set.
  6. Finally, you pass the first result node to your touch handler, which will either increase your score – or cost you a life!

One final step. You don’t need the camera control anymore so change the line in setupView() as follows:

scnView.allowsCameraControl = false

Build and run; get ready to unleash your deadly finger of annihilation! :]

BuildAndRun1

Tap on the spawned objects and make them disintegrate into thin air. Whoo-hoo! :]

Challenge

Time to up the cool factor – and what’s cooler than explosions? I know: nothing, right?

That brings you to the challenge of this chapter: create another particle system and name it Explode.scnp. See if you can figure out what attributes to modify to make those particles explode.

The effect should look something similar to this:

ExplosionParticleSystem

You can use the following image as a starting point for your particle system:

CreateExplosionParticles0

Note: If you get stuck or don’t want to try the challenge, download the solution particle system and add it to your project.

Shaping Particle Explosions

Now that you’ve created the explosion particle system, you need to add some code to make those nodes explode. You’re going to use some special properties to make the explosion take the same shape as whatever node you touch.

Add the following to the bottom of GameViewController, below touchesBegan(_: withEvent):

// 1
func createExplosion(geometry: SCNGeometry, position: SCNVector3,
  rotation: SCNVector4) {
  // 2
  let explosion =
    SCNParticleSystem(named: "Explode.scnp", inDirectory:
  nil)!
  explosion.emitterShape = geometry
  explosion.birthLocation = .Surface
  // 3
  let rotationMatrix =
    SCNMatrix4MakeRotation(rotation.w, rotation.x,
      rotation.y, rotation.z)
  let translationMatrix =
    SCNMatrix4MakeTranslation(position.x, position.y,
      position.z)
  let transformMatrix =
    SCNMatrix4Mult(rotationMatrix, translationMatrix)
  // 4
  scnScene.addParticleSystem(explosion, withTransform:
    transformMatrix)
}

Here’s the play-by-play of the above code:

  1. createExplosion(_: position: rotation:) takes three parameters: geometry defines the shape of the particle effect, while position and rotation help place the explosion into the scene.
  2. This loads Explode.scnp and uses it to create an emitter. The emitter uses geometry as emitterShape so that particles will emit from the surface of the shape.
  3. Enter the Matrix! :] Don’t be scared by these three lines; they simply provide a combined rotation and position (or translation) transformation matrix to addParticleSystem(_: withTransform:).
  4. Finally you call addParticleSystem(_: wtihTransform) on scnScene to add the explosion to the scene.

You’re so close to replicating those great Hollywood explosions! Add the following line twice inside handleTouchFor(_:), once to the “good” if block and once to the “bad” else block, right before you remove node from the parent:

createExplosion(node.geometry!, position: node.presentationNode.position,
  rotation: node.presentationNode.rotation)

This uses the presentationNode property to retrieve the position and rotation parameters of node . You then call createExplosion(_: position: rotation:) with those parameters.

Note: You’re using presentationNode because the physics simulation is currently moving the node.

Build and run; tap away and make those nodes explode!

BuildAndRun2

Juice

Congratulations! At this point you have completed your first Scene Kit game.

However, there’s still plenty room for improvement, right? To push your game to that next level, you absolutely have to add something known as juice. Juice will give your game that little something special, just to make it stand out above the rest.

Here’s a few ideas that will definitely juice things up:

  • Game state management. With basic game state management you’ll be able to control certain game machanics based on a game state like TapToPlay, Playing or GameOver.
  • Splash screens. Use pretty splash screens. They provide the player with visual clues of the current game state.
  • Sound effects. Add cool sound effects to provide the player with crucial audio feedback of good and bad interaction with the game elements.
  • Camera shakes. Really bad explosions produce really big shockwaves. Adding a shaking camera effect just that little something extra.

Where To Go From Here?

Here is the example code from this Scene Kit tutorial with Swift (with the juice applied).

If you’d like to learn more, you should check out our book 3D iOS Games by Tutorials. The book teaches you everything you need to know to make 3D iOS games, by making a series of mini-games like this one, including a games like Breakout, Marble Madness, and even Crossy Road.

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

The post Scene Kit Tutorial with Swift Part 5: Particle Systems appeared first on Ray Wenderlich.

Video Tutorial: Advanced watchOS Part 8: Complications II

Video Tutorial: Advanced watchOS Part 9: Accessibility


3D iOS Games by Tutorials Giveaway Winners – And Last Day for Discount!

$
0
0

tvt-giveaway-feature

Thank you for being a part of the 3D iOS Games by Tutorials Week!

During the 3D iOS Games by Tutorials week, we released five free Scene Kit tutorials, and the definitive book on Scene Kit game development, 3D iOS Games by Tutorials. But now, it’s time to say goodbye.

But first, there’s two important pieces of news!

3D iOS Games by Tutorials Giveaway Winners

To celebrate the 3D iOS Games by Tutorials Week, we had a giveaway for three free copies of 3D iOS Games by Tutorials. All you had to do to enter was comment on the announcement post.

We had over 180 applicants, and we’ve selected some random winners from among them.

And now it’s time to announce the 3 lucky winners… drum roll please!

The 3 lucky book winners are: jeppe_07, fern4344, and poortom. Congratulations! :]

Each winner will receive a free PDF copy of the 3D iOS Games by Tutorials (or a PDF of their choice if they already have a copy). We will be in touch with the winners directly via email.

Last Day for Discount!

Finally I’d like to remind everyone that today is the last day for the current discounted price for 3D iOS Games by Tutorials.

Starting tomorrow, the book will be raised to its normal price ($10 more). So be sure to grab the discount while you still can!

Thanks to everyone who entered the 3D iOS Games by Tutorials giveaway, bought the book, or simply read these posts. We really appreciate each and every one of you, and thank you for your support and encouragement – it is so amazing being a part of this community.

We can’t wait to see some great 3D iOS Games by you! :]

The post 3D iOS Games by Tutorials Giveaway Winners – And Last Day for Discount! appeared first on Ray Wenderlich.

Video Tutorial: Advanced watchOS Part 10: Localization

Video Tutorial: Advanced watchOS Part 11: Conclusion

Beginning Audio with AVFoundation: Series Introduction

Beginning Audio with AVFoundation Part 1: Recording & Playback

Readers’ App Reviews – March 2016

$
0
0

POTUSPalooza

We just wrapped up RWDevCon, and it was a great opportunity to meet the community face to face. I saw some great developers learning some new stuff, and I can’t wait to see some apps come from those tutorials!

Luckily, we don’t have to wait. The community has been very busy and filled my inbox with more apps for yet another month. I’ve given them all a try and I want to share a few with you now.

I receive more than an app a day from readers like you, and although I don’t have time to write about every app that hits my inbox, hopefully the few I show inspires you to finish your app.

This month we have:

  • A more exciting way to show your political support
  • An app to keep up with the latest movies
  • A game about moral dilemmas
  • And of course, much more!

Keep reading to see the the latest apps released by raywenderlich.com readers like you!

AlertFilm

alertfilm
Have you ever wanted to see a movie but forgot by the time it came out? AlertFilm is here to help.

AlertFilm helps you manage a watchlist of movies you’d like to see. You can discover new movies in the app looking at the latest box office hits or upcoming movies. AlertFilm grabs ratings, trailers and more from IMDB.

AlertFilm will also alert you when the film hits theaters or when its available on iTunes – perhaps one of the coolest features ever. I’m definitely looking forward to Netflix and Amazon support coming soon.

POTUSpalooza Primaries

POTUSPalooza
POTUSpalooza Primaries is part game, part revolutionary voting system.

In POTUSpalooza Primaries the characters are made up of the politicians running for President of the United States. You can choose one to play as and then go bouncing on your way to the presidential bus avoiding your constituents and political challenges. Its a fun side scrolling arcade style game.

The cool part is your play counts as votes. As you survive your challenges and make it to the bus, you’re unlocking votes. Everyone around the world is. Its an all new form of voting: play to vote!

Time Storm

TimeStorm
Time Storm is a feature packed clock for your daily needs. It has all the features you’ll need like unlimited alarms, a timer, stop watch, and times.

Alarms are very customizable. Each alarm can have its own music and vibration settings. Alarms can be one off or scheduled to be repeated automatically. You can choose any days of the week if you’d like weekday only alarms for example. You can even choose your own snooze length.

The stopwatch works as you’d expect with support for basic lap times and its accurate to the hundredth of a second.

If you’re looking for a new clock app that looks great, check out Time Storm.

DISPATCH!

dispatch
Dispatch is a game of reflexes and coordination.

Colorful shapes fall from above and your job is to sort them as quickly as you can. There are three different colors you’ll have to sort. Your task is easy: simply swipe each shape to its corresponding color on the side. Sounds easy, but the receptacles change over time and the colors speed up as you get the hang of it.

Survive being a human router as long as you can to climb the leaderboards and each achievements. You can go head to head with GameCenter multiplayer. Gain the edge with powerups to slow down the flow or freeze the timer.

Miracle Timer

miracletimer
Miracle Timer is an app to help you follow the Pomodoro task management technique.

Miracle Timer lets you set a task and start your timer. The timer will go for 25 minutes then ring for a 4 minute break. The science behind the technique is all about maintaining a balanced focus. Don’t let yourself go too far down a rabbit hole without a break. Miracle Timer can also send you a daily reminder to make sure you don’t forget to start a timer first thing in the morning.

Miracle Timer also has several pro features you can unlock. Customize your timers so you can choose your own work and break lengths that work best for you. Check out some beautiful stats to see your progress by the day, week, or month. Update your data if you forgot to start a timer.

Stack the Color

StackTheColors
Stack the Color is a simple yet addictive game that takes just the right amount of patience and memory coordination.

Colors fall one at a time in order. You have to tap each color in the order they fall before the time runs out. Each round you complete you’ll get a little less time to match the colors.

Stack the Color is deceptively easy. Before you know it you’re frantically trying to keep up and tap just the right colors.

Scruples – The Game of Moral Dilemmas

scruples
Scruples is a great pass and play game for parties.

Scruples is a bit backwards as far as trivia games go. You start with an answer you’re trying to get and it gives you some moral dilemma questions to choose from. You have to choose the question you think will get the answer you want from your opponent. There are no right answers and you don’t even need to tell the truth! But you have to make it convincing, opponents can challenge you if you’re bluffing.

Scruples has 250+ questions with the first 30 for free. All 250 questions are sure to start conversations and laughter with friends.

Deckr – The Flashcards App

deckr
Deckr is a powerful flashcards app to help you memorize anything you’d like. Deckr is designed to be simple so you can practice anywhere anytime.

Deckr is a fully customizable BYOF (Bring your own Flashcards) app. You can setup multiple decks for different subjects. You can setup each flashcard with a question on the front and the answer on the back. Flashcards support images if you’d rather practice your visual memory.

While you practice you can let Deckr know if you were correct or not. Deckr will automatically show you the ones you need some extra practice with until you get them right.

Jump Legends

jumplegends
Jump Legends is an isometric endless runner set in the ever-changing landscape of the Great Fall.

Like most endless runners the controls are simple. You can tap to jump. The longer you hold down your tap the higher you’ll jump. Time your jumps to span great divides, dangerous spikes, and other obstacles standing in your way.

There are 15 fully animated, playable characters to unlock and choose from. As you run, the world will change and new obstacles will emerge. See how far you can make it and challenge your friends on GameCenter.

Honorable Mentions

Every month I get way more submissions than I have time to write about. I download every app to try them out, but only have time to review a select few. I love seeing our readers through the apps submitted to me every month.

It’s not a popularity contest or even a favorite picking contest — I just try to share a snapshot of the community through your submissions. Please take a moment and try these other fantastic apps from readers like you.

Carl Can Divide Full Version – A fun division game for learning times tables and improving mental math skills
Slime Sports
APODtv
crazykooz
Hurricane Blasters
Mxo Pulse
MMA Quotes
HEX’EM
Birthdays
Spacer – An Outline Maker for Timed Events
Simple Mind Games
Flappy Turtle: Aquarium Adventure
EigoRacer
Sasha Prokhorenko

Where To Go From Here?

Each month, I really enjoy seeing what our community of readers comes up with. The apps you build are the reason we keep writing tutorials. Make sure you tell me about your next one, submit here.

If you saw an app your liked, hop to the App Store and leave a review! A good review always makes a dev’s day. And make sure you tell them you’re from raywenderlich.com; this is a community of makers.

If you’ve never made an app, this is the month! Check out our free tutorials to become an iOS star. What are you waiting for – I want to see your app next month.

The post Readers’ App Reviews – March 2016 appeared first on Ray Wenderlich.

Collection Views in OS X Tutorial

$
0
0

CollectionViews_feature

A collection view is a powerful mechanism for laying out an ordered set of data items visually. It sounds boring when explained in technical terms, so think of apps that do this: Finder and Photos; these apps let you tab through files in a gallery (visual) layout.

When released with OS X 10.5, NSCollectionView offered a handy means of arranging a group of objects in a grid of identically sized items displayed in a scrollable view.

OS X 10.11, aka El Capitan, gave NSCollectionView a major overhaul inspired by UICollectionView from iOS.

Among other things, the new NSCollectionView API adds support for:

  • Sections with optional headers/footers
  • Variable-size items
  • Customizable layouts
  • Cell reuse

In this collection views in OS X tutorial, you’ll discover the joy of arranging things in beautiful, flowing interfaces for the desktop. You’ll close the gap on UX between mobile and desktop and enjoy greater control over your apps by building SlidesMagic — your own grid-based image browsing app.

This tutorial assumes that you know the basics of writing OS X apps. If you’re new to OS X you should take a look at the OS X tutorials available here, and then come back to learn about collection views.

The show is about to start, so have a seat and get ready for your own personal magic show by NSCollectionView.

Behind the Scenes of Collection Views

The NSCollectionView is the main view — the stage, if you will — where the magic show happens. It displays visual items and contains these key components:

Layouts

NSCollectionViewLayout – New to this version, this lets you specify a layout by setting the collection view’s collectionViewLayout. It’s an abstract class from which all concrete layout classes inherit.

NSCollectionViewFlowLayout – Provides a flexible grid-like layout, and you can achieve your desired results for most apps with it.

NSCollectionViewGridLayout – Matches NSCollectionView‘s simple grid layout behavior pre OS X 10.11 but doesn’t support sections and all the goodies that come with the new API.

Layouts

Sections and NSIndexPath – Allows for grouping of items into sections. The items form an ordered list of sections, each containing an ordered list of items. Each item is associated with an index that comprises of a pair of integers (section, item) encapsulated in an NSIndexPath instance. When grouping of items into sections isn’t required, you still have at least one section (by default).

NSIndexPath

The Collection View Items

Like many other Cocoa frameworks, items in the collection view follow the MVC design pattern.

The Model and the View – The items’ content comes from your model’s data objects. Each individual object that becomes visible gets its own view in the larger collection view. The structure of these individual views are defined in a separate nib (file extension “.xib”).

The Controller – The nib mentioned above is owned by an instance of NSCollectionViewItem, which is is a descendant of NSViewController, or a subclass. It mediates the flow of information between the items’ views and model objects. Generally, you subclass NSCollectionViewItem. When items are not of the same kind, you define a different subclass and nib for each variant.

Supplementary Views

To display extra information in the collection view that’s not part of an individual item, you’d use supplementary views; some common implementations of these are section headers and footers.

The Collection View Data Source and Delegates

  • NSCollectionViewDataSource – Introduced with the new API in OS X 10.11, the populates the collection view with items and supplementary views.
  • NSCollectionViewDelegate – Handles events related to drag-and-drop, selection and highlighting.
  • NSCollectionViewDelegateFlowLayout – Lets you customize a flow layout.
Note: You can populate a table view by using a data source or Cocoa Bindings. This collection views in OS X tutorial covers the data source.

Introducing SlidesMagic

SlidesMagic the app you’re going to build is a simple image browser. It’s pretty cool, but don’t get all excited and delete Photos from your Mac just yet.

It retrieves all image files from a folder on the file system and displays them and their names in an elegant collection view. It’s actually kind of magical when you think about it! The finished app will look like this:

SlidesMagicSections

Download the starter project here and open it in Xcode. Build and run:

empty-app

At this point, it appears to be an empty window, but it has hidden features that will become the foundation of an image browser.

When SlidesMagic launches, it automatically loads all the images from the system’s Desktop Pictures folder. From Xcode‘s console log, you can see the file names.

desktop photos

That list in the console is an indicator that the model-loading logic is in place. You can choose another folder by selecting the File \ Open Another Folder… menu.

Overview of the Starter Project code

The starter project provides functionality that is not directly related to collection views but specific to SlidesMagic.

CollectionProjectNav

Model

  • ImageFile.swift: Encapsulates a single image file
  • ImageDirectoryLoader.swift: Helper class that loads image files from the disk

Controllers

The application has two main controllers:

  • WindowController.swiftwindowDidLoad() is responsible for the initial sizing of the window on the left half of the screen. The openAnotherFolder method is invoked by File \ Open Another Folder… menu item, and it presents a standard open dialog to choose a different folder.
  • ViewController.swiftviewDidLoad() opens the Desktop Pictures folder as the initial folder to browse, and loadDataForNewFolderWithUrl() is used by openAnotherFolder from WindowController.

Creating the Collection View

Open Main.storyboard. Go to the Object Library, and drag a Collection View into the view of the View Controller Scene.

AddCollectionView

Note: You may have noticed Interface Builder added three views instead of just one. That’s because the Collection View is embedded inside a Scroll View (which also has another subview called Clip View). When you’re instructed to select the Collection View, make sure you’re not selecting the Scroll View or the Clip View.

If you build now you’ll see an error:

Main.storyboard: Unknown segue relationship: Prototype

Along with the collection view, Xcode also added an NSCollectionViewItem, connected with a Prototype segue.

Therein you have the cause of your build error — it’s this type of segue that’s causing the trouble. This is a vestige (or bug if you like…) of the OS X 10.10 and earlier API model that prevents you from using collection view items in storyboards.

The fix is to delete it and reincarnate it in a separate xib file.

Select the Collection View Item and press Delete to, well, delete it.

deleteItem

Now the build error is gone.

Resize the Bordered Scroll View so it takes up the whole area of the parent view. Then, select Editor \ Resolve Auto Layout Issues \ Add Missing Constraints to add the Auto Layout constraints.

CollectionZeroConstraints

You need to add an outlet in ViewController to access the collection view. Open ViewController.swift and add the following inside the ViewController class definition:

@IBOutlet weak var collectionView: NSCollectionView!

Open Main.storyboard, and select the View Controller inside the View Controller Scene.

Open the Connections Inspector and find the collectionView element within the Outlets section. Connect it to the collection view by dragging from the button next to it to the collection view control in the canvas.

ConnectCollectionView

Configure the Collection View Layout

You’ve got options: You can set the initial layout and some of its attributes in Interface Builder, or you can set them programmatically.

For SlidesMagic, you’ll take the programmatic approach.

Open ViewController.swift and add the following method to ViewController:

private func configureCollectionView() {
  // 1
  let flowLayout = NSCollectionViewFlowLayout()
  flowLayout.itemSize = NSSize(width: 160.0, height: 140.0)
  flowLayout.sectionInset = NSEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
  flowLayout.minimumInteritemSpacing = 20.0
  flowLayout.minimumLineSpacing = 20.0
  collectionView.collectionViewLayout = flowLayout
  // 2
  view.wantsLayer = true
  // 3
  collectionView.layer?.backgroundColor = NSColor.blackColor().CGColor
}

Here’s what you’re doing in this method:

  1. Creating an NSCollectionViewFlowLayout and setting its attributes and the collectionViewLayout property of the NSCollectionView.
  2. For optimal performance, NSCollectionView is designed to be layer-backed. So, you’re setting an ancestor’s wantsLayer property to true.
  3. Making an addition related to the layer that’s specific to SlidesMagic, setting the collection view’s background color to black.

You need to call this method when the view is created, so add this to the end of viewDidLoad():

configureCollectionView()

Build and run:

BlackView

At this point, you have a black background and a layout. You’ve set the stage for your magic show!

Loading Items in the Collection View

To load items, you need to call its reloadData() method, which causes the collection view to discard and redisplay any currently visible items.

You’d typically call this method when the model changes.

Open ViewController.swift and add this code at the end of loadDataForNewFolderWithUrl(_:):

collectionView.reloadData()

This makes it so that selecting File \ Open Another Folder… calls this method. it loads a new model then calls reloadData().

Creating a Collection View Item

Just because you removed NSCollectionViewItem from the storyboard doesn’t mean you don’t need it. :] Here’s how to bring it back the right way.

Go to File \ New \ File…, select OS X \ Source \ Cocoa Class and click Next.

Set the Class field to CollectionViewItem, the Subclass of field to NSCollectionViewItem, and check Also create XIB for user interface.

CreateColViewItems

Click Next, and in the save dialog, select Controllers from Group and click Create.

Open CollectionViewItem.swift and replace the whole class with this:

class CollectionViewItem: NSCollectionViewItem {
 
  // 1
  var imageFile: ImageFile? {
    didSet {
      guard viewLoaded else { return }
      if let imageFile = imageFile {
        imageView?.image = imageFile.thumbnail
        textField?.stringValue = imageFile.fileName
      } else {
        imageView?.image = nil
        textField?.stringValue = ""
      }
    }
  }
 
  // 2
  override func viewDidLoad() {
    super.viewDidLoad()
    view.wantsLayer = true
    view.layer?.backgroundColor = NSColor.lightGrayColor().CGColor
  }
}

In here, you:

  1. Define the imageFile property that holds the model object to be presented in this item. When set, its didSet property observer sets the content of the item’s image and label.
  2. Change the background color to the item’s view.

Add Controls to the View

The View in the nib is the root view for a subtree of controls to be displayed in the item. You’re going to add an image view and a label for the file name.

Open CollectionViewItem.xib.

Add an NSImageView:

  1. From the Object Library, add an Image View to View.
  2. Select and click Pin from the Auto Layout toolbar to set its constraints.
  3. Set the top, leading and trailing constraints to 0, the bottom to 30 and click Add 4 Constraints.

    ImageAL1

  4. To fix the Auto Layout issues, select Editor \ Resolve Auto Layout Issues \ Update Frames.

ImageAL2

Add a label:

  1. From the Object Library, add a Label below the Image View.
  2. LabelInPlace

  3. Click the Pin button. Set the top, bottom, trailing and leading constraints to 0, and then click Add 4 Constraints.
  4. Screen Shot 2015-12-09 at 20.11.30

  5. Select Editor \ Resolve Auto Layout Issues \ Update Frames to update its position.

Select the Label, and in the Attributes Inspector set the following attributes:

  1. Alignment to center
  2. Text Color to white
  3. Line Break to Truncate Tail

ConfigLabel

Now you need to connect the controls to the imageView and the textField outlets:

  1. Select File’s Owner and show the Connections Inspector.
  2. Next, drag from the button next imageView to the Image View control to connect them.
  3. In the same way, connect the textField outlet to Label.

OwnerOutlets2

Add a Top Level CollectionViewItem to the Nib

The File’s Owner in the nib — of type CollectionViewItem — is just a placeholder. You still need to instantiate it.

CollectionView's method makeItemWithIdentifier(_:forIndexPath:) instantiates the collection view item, and it requires the nib to contain a single top-level instance of either NSCollectionViewItem or a subclass thereof.

You need to make it appear.

Drag a Collection View Item from the Object Library and drop it into Document Outline. Select it, and in the Identity Inspector, set its Class to CollectionViewItem.

TopLevelObject

Populate the Collection View

You need to implement the data source methods so the view knows the answers to these questions:

  1. How many sections are in the collection?
  2. How many items are in each section?
  3. Which item is associated with a specified index path?

Meet your data source method: NSCollectionViewDataSource protocol.

Put it into action now — open ViewController.swift and add the following extension at the end of the file:

extension ViewController : NSCollectionViewDataSource {
 
  // 1
  func numberOfSectionsInCollectionView(collectionView: NSCollectionView) -> Int {
    return imageDirectoryLoader.numberOfSections
  }
 
  // 2
  func collectionView(collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
    return imageDirectoryLoader.numberOfItemsInSection(section)
  }
 
  // 3
  func collectionView(collectionView: NSCollectionView, itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem {
 
    // 4
    let item = collectionView.makeItemWithIdentifier("CollectionViewItem", forIndexPath: indexPath)
    guard let collectionViewItem = item as? CollectionViewItem else {return item}
 
    // 5
    let imageFile = imageDirectoryLoader.imageFileForIndexPath(indexPath)
    collectionViewItem.imageFile = imageFile
    return item
  }
 
}
  1. This method provides the number of sections. When your app doesn’t support sections, you can omit this method because a single section will be assumed. When SlidesMagic launches, the model imageDirectoryLoader is set to return the value 1.
  2. This is one of two required methods for NSCollectionViewDataSource. Here you return the number of items in the section specified by the section parameter. Upon launch, SlidesMagic has a single section, so you set the model to return the total number of images in the folder.
  3. This is the second required method. It returns a collection view item for a given indexPath.
  4. The collection view’s method makeItemWithIdentifier(_:forIndexPath:) instantiates an item from a nib where its name equals the value of the identifier parameter. In this case, it’s "CollectionViewItem". First, it attempts to reuse an unused item of the requested type, and if nothing is available it creates a new one.
  5. This code gets the model object for the given NSIndexPath and sets the content of the image and the label.
Note: The ability of the collection view to recycle unused collection view items provides a scalable solution for large collections. Items associated with model objects that aren’t visible are the objects that get recycled.

Set the Data Source

A collection view without data is like a magic act with no slight of hand — pointless and uninspiring. So, your next step is to define the data source; in this case it’s the view controller.

Open Main.storyboard and select the collection view.

Open the Connections Inspector and locate dataSource in the Outlets section. Drag from the adjacent button to the View Controller in Document Outline View.

SetAsDataSource

Build and run.
OneSectionFinal

Voila! It was worth all that work! Your collection view displays images from the Desktop Pictures folder!

Troubleshooting

If you don’t see images, then something went wrong. You worked through several steps, so you probably just missed something small.

  1. Are all the connections in the Connections Inspector set as instructed?
  2. Did you set the dataSource outlet?
  3. Did you use the right type for custom classes in the Identity Inspector.
  4. Did you add the top level NSCollectionViewItem object and change its type to CollectionViewItem?
  5. Is the value for the identifier parameter in makeItemWithIdentifier identical to the nib name?

Going Multi-Section

MagicSlides is doing some serious magic now. But you’re going to improve it by adding sections.

First, you need to add a check box at the bottom of the view so you can toggle between single and multi-section.

Open Main.storyboard, and in the Document Outline view, select the scroll view’s bottom constraint. Open the Size Inspector and change its Constant to 30.

This is how you move the collection view up to make room for the check box.

change-constraint

Now, drag a Check Box Button from the Object Library into the space below the collection view. Select it, and in the Attributes Inspector, set its Title to Show Sections, and its State to Off.

ShowSections

Then, set its Auto Layout constraints by selecting the Editor \ Resolve Auto Layout Issues \ Add Missing Constraints menu.

Build and run. It should look like this at the bottom:

ShowSectionsBottom

Now for a little UI. When you click the box, the application needs to change the collection view’s appearance.

Open ViewController.swift and add the following method at the end of the ViewController class:

// 1
@IBAction func showHideSections(sender: AnyObject) {
  // 2
  let show = (sender as! NSButton).state
  imageDirectoryLoader.singleSectionMode = (show == NSOffState)
  imageDirectoryLoader.setupDataForUrls(nil)
  // 3
  collectionView.reloadData()
}

Section by section, here’s what you’re doing:

  1. Calling this method by toggling the state of the checkbox.
  2. Accordingly, retrieving the state of the checkbox and setting data model mode singleSelectionMode, and then calling the model’s setupDataForUrls(_:) method to rearrange the sections structure. The nil value passed means you skip image loading — same images, different layout.

If you’re curious how images are distributed across sections, look up sectionLengthArray in ImageDirectoryLoader. The number of elements in this array sets the max number of sections, and the element values set the number of items in each section.

Now, open Main.storyboard. In the Document Outline, Control-Drag from the Show Sections control over the View Controller. In the black pop-up window click showHideSections: to connect it. You can check if the connection was set properly in the Connections Inspector.

ConnectShowSections

Build and run.

SectionsShowing

Check Show Sections and watch the layout change.

Because of the “black tail” in the second row, you see section 0 has seven images, but section 1 has five and section 2 has 10 (look at sectionLengthArray). It’s not clear because the sections are rather cozy.

To fix this, open ViewController.swift and modify the layout’s sectionInset property in the configureCollectionView() function.

Replace:

flowLayout.sectionInset = NSEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)

With this:

flowLayout.sectionInset = NSEdgeInsets(top: 30.0, left: 20.0, bottom: 30.0, right: 20.0)

Here you set the bottom and top section insets to 30 to provide better visual separation between sections.

Build and run.

SectionInsets

Check Show Sections, and note the additional spacing between sections.

Add Section Headers

The app is looking great so far, but more organization will make it even better.

Another way to see section boundaries is adding a header or footer view. To do this, you need a custom NSView class and will need to implement a data source method to provide the header views to the table view.

To create the header view, select File \ New \ File…. Select OS X \ User Interface \ View and click Next.

Enter HeaderView.xib as the file name and for Group select Resources.

Click Create.

HeaderView

Open HeaderView.xib and select the Custom View. Open the Size Inspector and change Width to 500 and Height to 40.

Drag a label from the Object Library to the left-hand side of Custom View. Open the Attributes Inspector and change Title to Section Number and Font Size to 16.

Drag a second label to the right-hand side of Custom View and change Title to Images Count and Text Alignment to Right.

Now, select the Editor \ Resolve Auto Layout Issues \ Add Missing Constraints menu to add its Auto Layout constraints.

The header view should look like this:

HeaderControls

With the interface ready for show time, the next task is to create a custom view subclass for the header view.

Select File \ New \ File… to create a new file.

Choose OS X \ Source \ Cocoa Class and name the class HeaderView, and then make it a subclass of NSView. Click next, and for Group select Views. Click Create.

Open HeaderView.swift and replace the contents of the class with the following:

// 1
@IBOutlet weak var sectionTitle: NSTextField!
@IBOutlet weak var imageCount: NSTextField!
 
// 2
override func drawRect(dirtyRect: NSRect) {
  super.drawRect(dirtyRect)
  NSColor(calibratedWhite: 0.8 , alpha: 0.8).set()
  NSRectFillUsingOperation(dirtyRect, NSCompositingOperation.CompositeSourceOver)
}

In here, you’re:

  1. Setting up outlets you’ll use to connect to the labels in the nib.
  2. Drawing a gray background.

With the framework in place, the next task is changing the nib file to use this new class and connecting the outlets to the labels.

Open HeaderView.xib and select the Custom View. Open the Identity Inspector. Change the Class to HeaderView.

Screen Shot 2015-12-09 at 22.50.57

In the Document Outline view, Control-Click on the Header View. In the black pop-up window, drag from imageCount to the Images Count label on the canvas to connect the outlet.

Repeat the operation for the second label, dragging from sectionTitle to the Section Number label in the canvas.

ConnectHeaderControls

Implement the Data Source and Delegate Methods

Your header view is in place and ready to go, and you need to pass the header views to the collection view to implement the collectionView(_:viewForSupplementaryElementOfKind:atIndexPath:) method.

Open ViewController.swift and add the following method to the NSCollectionViewDataSource extension:

func collectionView(collectionView: NSCollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> NSView {
  // 1
  let view = collectionView.makeSupplementaryViewOfKind(NSCollectionElementKindSectionHeader, withIdentifier: "HeaderView", forIndexPath: indexPath) as! HeaderView
  // 2
  view.sectionTitle.stringValue = "Section \(indexPath.section)"
  let numberOfItemsInSection = imageDirectoryLoader.numberOfItemsInSection(indexPath.section)
  view.imageCount.stringValue = "\(numberOfItemsInSection) image files"
  return view
}

The collection view calls this method when it needs the data source to provide a header for a section. The method:

  1. Calls makeSupplementaryViewOfKind(_:withIdentifier:forIndexPath:) to instantiate a HeaderView object using the nib with a name equal to withIdentifier.
  2. Sets the values for the labels.

At the end of ViewController.swift, add this NSCollectionViewDelegateFlowLayout extension.

extension ViewController : NSCollectionViewDelegateFlowLayout {
  func collectionView(collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> NSSize {
    return imageDirectoryLoader.singleSectionMode ? NSZeroSize : NSSize(width: 1000, height: 40)
  }
}

The above method, although technically optional, is a must when you use headers because the flow layout delegate needs to provide the size of the header for every section.

When not implemented, the header won’t show because zero size is assumed. Additionally, it ignores the specified width, effectively setting it to the collection view’s width.

In this case, the method returns a size of zero when the collection view is in single section mode, and it returns 40 when in multiple sections mode.

For the collection view to use NSCollectionViewDelegateFlowLayout, you must connect ViewController to the delegate outlet of NSCollectionView.

Open Main.storyboard and select the collection view. Open the Connections Inspector, and locate the delegate in the Outlets section. Drag from the button next to it to the view controller in the Document Outline.

ConnectTheDelegate

Build and run.

WithHeaders

Check Show Sections and watch your header neatly define sections.

Selection in Collection Views

Collection views support both single and multiple selections. To show an item as selected, you must highlight it.

Before you can do that, you need to make the collection view selectable. Open the Main.storyboard. Then, select the Collection View and in the Attributes Inspector, check Selectable.

SelectionAttributes

Checking Selectable enables single selection, meaning you can click an item to select it. And when you choose a different item, it deselects the previous item and selects item you just picked.

To show an item as selected, you’ll set a white border with borderWith set to 5.0. Non-selected items will get no special treatment.

Open CollectionViewItem.swift. Add the following at the end of viewDidLoad():

// 1
view.layer?.borderWidth = 0.0
// 2
view.layer?.borderColor = NSColor.whiteColor().CGColor
  1. Setting borderWidth to 0.0 initializes the item to show not selected
  2. Sets white for the color when selected

Add the following method at the end of CollectionViewItem class:

func setHighlight(selected: Bool) {
  view.layer?.borderWidth = selected ? 5.0 : 0.0
}

This method is called to add or remove highlighting.

When the user selects an item in the collection view, you find out via delegate methods. You’ll need to implement those methods, so open ViewController.swift and add this extension at the end of the file:

extension ViewController : NSCollectionViewDelegate {
  // 1
  func collectionView(collectionView: NSCollectionView, didSelectItemsAtIndexPaths indexPaths: Set<NSIndexPath>) {
    // 2
    guard let indexPath = indexPaths.first else {
      return
    }
    // 3
    guard let item = collectionView.itemAtIndexPath(indexPath) else {
      return
    }
    (item as! CollectionViewItem).setHighlight(true)
  }
 
  // 4
  func collectionView(collectionView: NSCollectionView, didDeselectItemsAtIndexPaths indexPaths: Set<NSIndexPath>) {
    guard let indexPath = indexPaths.first else {
      return
    }
    guard let item = collectionView.itemAtIndexPath(indexPath) else {
      return
    }
    (item as! CollectionViewItem).setHighlight(false)
  }
}

This implements the necessary NSCollectionViewDelegate methods. Further detail:

  1. When you select an item, NSCollectionView calls this method.
  2. Here you get the selected item — since multiple selection is disabled, it is always the first.
  3. This retrieves an item by its index and highlights it.
  4. The same as the previous method, but it’s called when an item is deselected.

What Happens During Selection Stays in Selection

When selected, an item is set in:

  1. The selectionIndexPaths property of NSCollectionView.
  2. The selected property of NSCollectionViewItem.

It’s critical to understand that when an NSCollectionViewItem instance is recycled, the data set must be refreshed with the data from the new object. Your selected property of NSCollectionViewItem is where you ensure this happens.

Accordingly, in the NSCollectionViewDataSource extension you need to add the following inside collectionView(_:itemForRepresentedObjectAtIndexPath:) method, just before the return statement:

if let selectedIndexPath = collectionView.selectionIndexPaths.first where selectedIndexPath == indexPath {
  collectionViewItem.setHighlight(true)
} else {
  collectionViewItem.setHighlight(false)
}

This guarantees that selection and highlighting are in sync.

Build and run.

ShowSelection

Click an item and you’ll see highlighting. Choose a different image and you’ll see fully functional highlighting. Poof! Magic!

Where to go From Here

Download the final version of SlidesMagic here.

In this collection views in OS X tutorial you went all the way from creating your first ever collection view, through discovering the intricacies of the data source API with sections, to handling selection with the delegate protocol. However, although you covered a lot of ground, you’ve barely explored the capabilities of collection views. For instance, you didn’t look into any of these:

  • “Data Source-less” collection views using Cocoa Bindings
  • Different kind of items
  • Adding and removing items
  • Custom layouts
  • Drag and drop
  • Animations
  • Tweaking NSCollectionViewFlowLayout (sticky headers, for example)

We will be covering some of these topics in upcoming OS X tutorials here on raywenderlich.com, so be sure to check back over the coming months.

Unfortunately, the documentation for collection views from Apple and other sources is limited, but here are my suggestions:

I wish you a pleasant journey with Collection View in your apps. I look forward to hearing your ideas, experiences and any questions you have in the forums below!

The post Collection Views in OS X Tutorial appeared first on Ray Wenderlich.


Announcing In-Person iOS Bootcamp: Alt-U!

$
0
0

Alt-U-Thumb

Over the past few years, I’ve noticed a lot of people interested in changing their career to iOS development. Maybe they are web developers, maybe they’re new to programming all-together – either way, it’s time for a change.

A lot of these folks have come to our site, and taught themselves via written or video tutorials. However, others have mentioned that they wish there was a way to get some help (and maybe a kick in the butt) via a live, in-person bootcamp – but at that time, we had nothing to offer them.

But now we do, thanks to our partnership with Five Pack Creative: Alt-U!

Alt-U offers live in-person bootcamps designed to take complete beginners to iOS development and teach you everything you know to excel at a real-world iOS development jobs, through a series of hands-on tutorials and exercises based on the materials you know and love at raywenderlich.com.

Keep reading to find out about Alt-U’s upcoming bootcamps, and how to get your raywenderlich.com reader’s discount.

First Bootcamp: The iOS Apprentice

Alt-U-Laptop

The first bootcamp Alt-U is on April 24-29 in Dallas, Texas and is for complete beginners to iOS development: the iOS Apprentice.

In the iOS Apprentice, you will learn the fundamentals of iOS development with the Swift programming language.

You will leverage Swift, the iOS SDK, and Apple developer tools to learn object-oriented programming, design patterns, type systems, functional language features, user interface design, best practices in programming, and problem analysis. At the end of the week you should feel ready and confident to explore intern level job opportunities.

In the intense week-long bootcamp, you’ll learn the following topics:

  • Build functioning programs in Swift
  • Function as a member of a real development team
  • Interface with web services to pull data from a remote server
  • Manage/share code with git
  • Work with debugging tools and methodologies
  • Work effectively within an Agile development environment
  • Build elegant user interfaces in Interface Builder and in Code
  • Submit an app to the Apple App Store
  • And much, much more!

Alt-U is taught by the team at Five Pack Creative, an award-winning mobile development shop that has created apps for American Airlines, match.com, and more. The co-owner of Five Pack Creative, Jerry Beers, is a video tutorial team member on our site – you may have seen his video tutorial series on Adaptive Layout.

That’s what makes this bootcamp unique – it’s taught by real developers down in the trenches, teaching you exactly what you need to know to succeed in the real world.

In fact, Five Pack Creative and other companies are looking to hire the best graduates from the bootcamp immediately – so if you’re looking for a job, this is a great opportunity!

Where To Go From Here?

I’m so excited about this, because I really believe this is a great alternative for people who want to get into a career in iOS development, without having to go broke paying for a $100,000+ computer science degree. In fact, that’s how it got its name. Alt-U is short for “Alternative University”.

To celebrate the launch, the Five Pack Creative team has been generous enough to offer a massive 50% off discount to raywenderlich.com readers. Just enter the following code at checkout: RAYWENDERLICH. Note that this offer expires in just a little over a week (April 8), so be sure to sign up soon!

Where to go next depends on you:

  • If you are looking to switch your career to iOS development, or know somebody who is, there’s never been a better time. Make the investment in yourself and sign up for this bootcamp, and the team at Five Pack Creative will guide you through the rest!
  • If you’re a seasoned iOS developer and like learning via intense bootcamps, you should sign-up to get notified when more advanced courses are offered on the Alt-U site.

The team at Five Pack Creative and I hope you enjoy the Alt-U bootcamps! :]

The post Announcing In-Person iOS Bootcamp: Alt-U! appeared first on Ray Wenderlich.

Beginning Audio with AVFoundation Part 2: Controlling Audio

In-App Purchase Tutorial: Getting Started

$
0
0
in-app purchase tutorial

Get started with in-app purchases to grow app revenue!

Update note: This in-app purchase tutorial was updated for iOS 9.3 and Swift 2.2 by Ed Sasena. The original tutorial was written by site editor-in-chief Ray Wenderlich.

One of the great things about being an iOS developer is the variety of methods available for making money from apps, namely: paid, free with ads, and in-app purchases.

An in-app purchase (or ‘IAP‘), the focus of this tutorial, allows developers to charge users for specific functionality or content while using an app. Implementing IAPs is particularly compelling for several reasons:

  • It’s an extra way to earn money, in addition to simply selling the app for a fee upfront. Some users are willing to spend a lot more on extra content.
  • An app can be offered for free, which makes it a no-brainer download for most people; free apps will typically get many more downloads than paid apps. If users enjoy the app, then they can purchase more content or functionality later.
  • You could also display advertisements to the user in a free app, with an option to remove them by purchasing an IAP.
  • Following the initial release of an app, new paid content can be added to the same app instead of having to develop a brand new app to earn more money.

In this in-app purchase tutorial you’ll leverage IAPs to unlock extra content embedded in an app. You’ll need to be familiar with basic Swift and iOS programming concepts. If these are unfamiliar topics, then check out our range of Swift tutorials before getting started. You’ll also need a paid developer account, with access to both the iOS Developer Center and iTunes Connect.

Getting Started

In this in-app purchase tutorial, you’ll be building a small app called “Rage”, which allows users to buy rage comics. Readers of this site will undoubtedly recognize the genre. Rage comics typically involve someone facing a common, frustrating situation and reacting wildly in a humorous manner.

in-app purchase tutorial

A typical rage comic.

Download the starter project and open it in Xcode. Build and run to see what it does so far. The answer is: not a lot! You’ll see an empty table view, with a single “Restore” button in the navigation bar (which will be hooked up later to restore purchases).

in-app purchase tutorial

Upon finishing this tutorial, there will be a list of rage comics listed in the table which you’ll be able to buy and then view. If you delete and reinstall the app, the “Restore” button will reinstate any previously purchased comics.

Head over to Xcode to take a quick look at the code. The main view controller is in MasterViewController.swift. This class displays the table view which will contain a list of available IAPs. Purchases are stored as an array of SKProduct objects.

Notice that MasterViewController is using an object called RageProducts.store of type IAPHelper to do the heavy lifting. Take a look at their respective code files, RageProducts.swift and IAPHelper.swift.

RageProducts is a simple struct that contains some information about the products in the app, and IAPHelper does all the important work of talking to StoreKit. The methods are all stubbed out at the moment, but you’ll fill them out in this tutorial to add IAP functionality to the app.

Before writing any code to incorporate IAP into an app, you’ll first need to do some setup in the iOS Developer Center and iTunes Connect. So let’s get busy.

Creating an App ID

First you’ll need to create an App ID. This will link together your app in Xcode, to iTunes Connect, to your in-app purchaseable products. Login to the iOS Developer Center, then select Certificates, Identifiers & Profiles.


in-app purchase tutorial

Next, under iOS Apps, select Identifiers. Then select App IDs in the left pane. Click + in the upper right corner to create a new App ID.

in-app purchase tutorial

In-App Purchase Tutorial

Fill out the information for the new App ID. Enter “Rage IAP Tutorial App” for the Name, and leave the App ID Prefix set to your Team ID. Choose Explicit App ID, and enter a unique Bundle ID. A common practice is to use your domain name in reverse (for example, com.razeware.rageapp). Make note of the Bundle ID as it will be needed in the steps that follow.

Scroll down to the App Services section. Notice that In-App Purchase and GameKit are enabled by default. Click Continue and then Submit.

Congratulations! You have a new App ID! Next, you’ll create a matching app in iTunes Connect.

Creating an App in iTunes Connect

Before you can add IAPs to an app in iTunes Connect, make sure you have a “paid applications contract” in effect. Log in to iTunes Connect for the same developer account you just used to set up the App ID. Click on Agreements, Tax, and Banking.

in-app purchase tutorial

If you see a section entitled Request Contracts containing a row for Paid Applications, then click the Request button. Fill out all the necessary information and submit it. It may take some time for your request to be approved. Sit tight!

Otherwise, if you see Paid Applications listed under Contracts In Effect, then it looks like you’ve already done this step! Nice job!

Now to create the app record itself, click iTunes Connect in the upper left corner of the page, and then click My Apps.

in-app purchase tutorial

Next, click + in the upper left corner of the page and select New App to add a new app record. Fill out the information as shown here:

in-app purchase tutorial

You won’t be able to use the exact same app Name that you see here, because app names need to be unique across the App Store. Perhaps add your own initials after the example title shown in the screenshot above.

Note: If you are quick in getting to this step, the Bundle ID might not be showing up in the dropdown list. This sometimes takes a while to propagate through Apple’s systems.

Click Create and you’re done!

Creating In-App Purchase Products

When offering IAP within an an app, you must first add an entry for each individual purchase within iTunes Connect. If you’ve ever listed an app for sale in the store, it’s a similar process and includes things like choosing a pricing tier for the purchase. When the user makes a purchase, the App Store handles the complex process of charging the user’s iTunes account.

There are a whole bunch of different types of IAP you can add:

  • Consumable: These can be bought more than once and can be used up. These are things such as extra lives, in-game currency, temporary power-ups, and the like.
  • Non-Consumable: Something that you buy once, and expect to have permanently such as extra levels and unlockable content.
  • Non-Renewing Subscription: Content that’s available for a fixed period of time.
  • Auto-Renewing Subscription: A repeating subscription such as a monthly Netflix subscription.

You can only offer In-App Purchases for digital items, and not for physical goods or services. For more information about all of this, check out Apple’s full documentation on Creating In-App Purchase Products.

Now, while viewing your app’s entry in iTunes Connect, click on the Features tab and then select In-App Purchases. To add a new IAP product, click the + to the right of In-App Purchases. When a user purchases a rage comic in your app, you’ll want them to always have access to it, so select Non-Consumable.

in-app purchase tutorial

in-app purchase tutorial

Next, fill out the details for the IAP as follows:

  • Reference Name: A nickname identifying the IAP within iTunes Connect. This name does not appear anywhere in the app. The title of the comic you’ll be unlocking with this purchase is “Girlfriend of Drummer“, so enter that here.
  • Product ID: This is a unique string identifying the IAP. Usually it’s best to start with the Bundle ID and then append a unique name specific to this purchasable item. For this tutorial, make sure you append “GirlfriendOfDrummerRage“, as this will be used later within the app to look up the comic to unlock. So, for example: com.theNameYouPickedEarlier.Rage.GirlFriendOfDrummerRage.
  • Cleared for Sale: Enables or disables the sale of the IAP. You want to enable it!
  • Price Tier: The cost of the IAP. Choose Tier 1.

Now scroll down to the In-App Purchase Details section and click Add Language. The language section allows you to provide localizations for the names of your products. Select your language of choice, and enter “Girlfriend of Drummer” again for both the Display Name and the Description. Click Save. Great! You’ve created your first IAP product.

in-app purchase tutorial

in-app purchase tutorial

There’s one more step required before you can delve into some code. When testing in-app purchases in a development build of an app, Apple provides a test environment which allows you to ‘purchase’ your IAP products without creating financial transactions.

These special test purchases can only be made by a special “Sandbox Tester” user account in iTunes Connect. So let’s create one. We’re almost at the code, I promise!

Creating a Sandbox User

In iTunes Connect, click iTunes Connect in the top left corner of the window to get back to the main menu. Select Users and Roles, then click the Sandbox Testers tab. Click + next to the “Tester” title.

in-app purchase tutorial

Fill out the information and click Save when you’re done. You can make up a first and last name for your test user, but the email address chosen must be a real email address as a verification will be sent to the address by Apple. Once you receive that email, be sure to click the link in it to verify your address.

The email address you enter should also NOT already be associated with an Apple ID account.

Note: Unfortunately, testing a new purchase of a non-consumable IAP requires a new sandbox tester (and email address) each time. Repeated purchases using the same sandbox tester will be treated as restoring an already purchased item, so any code specific to new purchases will not be exercised.If multiple test runs through new purchase code are necessary and your email provider does not support qualifiers, then consider setting up a consumable IAP just for testing purposes. Delete the app on your device after each test and the purchase of a consumable IAP will be considered a new purchase.

Great – you now have a test user. You can finally implement IAP in your app!

Project Configuration

For everything to work correctly, it’s really important that the bundle identifier and product identifiers in the app match the ones you just created in the Developer Center and in iTunes Connect.

Head over to the starter project in Xcode. Select the Rage project in the project navigator, then select it again under Targets. Select the General tab, and enter the bundle ID you used earlier.

in-app purchase tutorial

Next select the Capabilities tab. Scroll down to In-App Purchase and toggle the switch to ON.

in-app purchase tutorial

There’s one other place that you need to set the bundle ID. Open RageProducts.swift. Find the following line of code:

private static let Prefix = "com.razeware.Rage."

And change it to use the bundle ID you created earlier. Don’t forget to include the final period after "Rage.", since this is a prefix that will precede each IAP product name.

Notice that the lines below include a reference to the IAP product you created: GirlfriendOfDrummerRage. This is why it’s important that you set the product ID correctly in iTunes Connect:

public static let GirlfriendOfDrummerRage = Prefix + "GirlfriendOfDrummerRage"
 
private static let productIdentifiers: Set = [RageProducts.GirlfriendOfDrummerRage]
Note: The list of product identifiers can be pulled from a web server so new IAPs can be added dynamically rather than requiring an app update. This tutorial keeps things simple and uses hard-coded product identifiers.

Listing In-App Purchases

The store property of RageProduct is an instance of IAPHelper. As was briefly mentioned earlier, this object interacts with the StoreKit API to list and perform purchases. Your first task will be to update IAPHelper to retrieve a list of IAPs (although there is only one so far) from Apple’s servers.

Open IAPHelper.swift. At the top of the class, add the following private property:

private let productIdentifiers: Set

Next, add the following to init(productIds:) before the call to super.init():

self.productIdentifiers = productIds

An IAPHelper instance is created by passing in a set of product identifiers. This is how RageProducts creates its store instance.

Next, add these other private properties just under the one you added a moment ago:

private var purchasedProductIdentifiers = Set()
 
private var productsRequest: SKProductsRequest?
private var productsRequestCompletionHandler: ProductsRequestCompletionHandler?

purchasedProductIdentifiers will track which items have been purchased. The other two properties will be used by the SKProductsRequest delegate to perform requests from Apple.

Next, still in IAPHelper.swift replace the implementation of requestProducts(_:) with the following:

public func requestProducts(completionHandler: ProductsRequestCompletionHandler) {
  productsRequest?.cancel()
  productsRequestCompletionHandler = completionHandler
 
  productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
  productsRequest!.delegate = self
  productsRequest!.start()
}

This code saves the user’s completion handler for future execution. It then creates and initiates a request to Apple via an SKProductsRequest object. There’s one problem: the code declares IAPHelper as the request’s delegate, but it doesn’t yet conform to the SKProductsRequestDelegate protocol.

To fix this, add the following extension to the very end of IAPHelper.swift, after the last curly brace:

// MARK: - SKProductsRequestDelegate
 
extension IAPHelper: SKProductsRequestDelegate {
  public func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
    print("Loaded list of products...")
    let products = response.products
    productsRequestCompletionHandler?(success: true, products: products)
    clearRequestAndHandler()
 
    for p in products {
      print("Found product: \(p.productIdentifier) \(p.localizedTitle) \(p.price.floatValue)")
    }
  }
 
  public func request(request: SKRequest, didFailWithError error: NSError) {
    print("Failed to load list of products.")
    print("Error: \(error.localizedDescription)")
    productsRequestCompletionHandler?(success: false, products: nil)
    clearRequestAndHandler()
  }
 
  private func clearRequestAndHandler() {
    productsRequest = nil
    productsRequestCompletionHandler = nil
  }
}

This extension is used to get a list of products, their titles, descriptions and prices from Apple’s server by implementing the two methods required by the SKProductsRequestDelegate protocol.

productsRequest(_:didReceiveResponse:) is called when the list is succesfully retrieved. It receives an array of SKProduct objects and passes them to the previously saved completion handler. The handler reloads the table with new data. If a problem occurs, request(_:didFailWithError:) is called. In either case, when the request finishes, both the request and completion handler are cleared with clearRequestAndHandler().

Build and run. Hooray! A list of products (only one so far) is displayed in the table view! It took some work, but you got there in the end.

 

Rage Run 2 - 2 Buy

If the run was unsuccessful and you didn’t see any products, then there are a number of things to check. (This list is courtesy of itsme.manish and abgtan from the forums.)

  • Does the project’s Bundle ID match the App ID from the iOS Development Center?
  • Check Apple Developer System Status. Alternatively, try this link. If it doesn’t respond with a status value, then the iTunes sandbox may be down. The status codes are explained in Apple’s Validating Receipts With the App Store documentation.
  • Have IAPs been enabled for the App ID? (Did you select “Cleared for Sale” earlier?)
  • Is the full product ID being used when making an SKProductRequest? (Check the productIdentifiers property of RageProducts.)
  • Have you waited several hours since adding your product to iTunes Connect? Product additions may be active immediately or may take some time.
  • Is the Paid Applications Contract in effect on iTunes Connect?
  • Have you tried deleting the app from your device and reinstalling?

Still stuck? It’s time to make another rage comic and/or try this tutorial’s comments for a discussion with other readers.

Purchased Items

You want to be able to determine which items are already purchased. To do this you will use the  purchasedProductIdentifiers property you added earlier. If a product identifier is contained in this set, the user has purchased the item. The method for checking this is straightforward.

In IAPHelper.swift, replace the return statement in isProductPurchased(_:) with the following:

return purchasedProductIdentifiers.contains(productIdentifier)

Saving purchase status locally alleviates the need to request the information from Apple’s server every time the app starts. purchasedProductIdentifiers are saved using NSUserDefaults.

Still in IAPHelper.swift, add the following before the call to super.init() in init(productIds:):

for productIdentifier in productIds {
  let purchased = NSUserDefaults.standardUserDefaults().boolForKey(productIdentifier)
  if purchased {
    purchasedProductIdentifiers.insert(productIdentifier)
    print("Previously purchased: \(productIdentifier)")
  } else {
    print("Not purchased: \(productIdentifier)")
  }
}

For each product identifier, you check whether the value is stored in NSUserDefaults. If it is, then the identifier is inserted into the purchasedProductIdentifiers set. Later, you’ll add an identifier to the set following a purchase.

Note: User defaults may not be the best place to store information about purchased products in a real application. An owner of a jailbroken device could easily access your app’s NSUserDefaults plist, and modify it to ‘unlock’ purchases. If this sort of thing concerns you, then it’s worth checking out Apple’s documentation on Validating App Store Receipts – this allows you to verify that a user has made a particular purchase.

Making Purchases (Show Me The Money!)

Knowing what a user has purchased is great, but you still need to be able to make the purchases in the first place! Implementing purchase capability seems like a logical next step.

Still in IAPHelper.swift, replace buyProduct(_:) with the following:

public func buyProduct(product: SKProduct) {
  print("Buying \(product.productIdentifier)...")
  let payment = SKPayment(product: product)
  SKPaymentQueue.defaultQueue().addPayment(payment)
}

This creates a payment object using an SKProduct (retrieved from the Apple server) to add to a payment queue. The code utilizes a singleton SKPaymentQueue object called defaultQueue(). Boom! Money in the bank. Or is it? How do you know if the payment went through?

Payment verification is achieved by having IAPHelper observe transactions happening on the SKPaymentQueue. Before setting up IAPHelper as an SKPaymentQueue transactions observer, the class must conform to the SKPaymentTransactionObserver protocol.

Go to the very bottom (after the last curly brace) of IAPHelper.swift and add the following extension:

// MARK: - SKPaymentTransactionObserver
 
extension IAPHelper: SKPaymentTransactionObserver {
 
  public func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
      switch (transaction.transactionState) {
      case .Purchased:
        completeTransaction(transaction)
        break
      case .Failed:
        failedTransaction(transaction)
        break
      case .Restored:
        restoreTransaction(transaction)
        break
      case .Deferred:
        break
      case .Purchasing:
        break
      }
    }
  }
 
  private func completeTransaction(transaction: SKPaymentTransaction) {
    print("completeTransaction...")
    deliverPurchaseNotificatioForIdentifier(transaction.payment.productIdentifier)
    SKPaymentQueue.defaultQueue().finishTransaction(transaction)
  }
 
  private func restoreTransaction(transaction: SKPaymentTransaction) {
    guard let productIdentifier = transaction.originalTransaction?.payment.productIdentifier else { return }
 
    print("restoreTransaction... \(productIdentifier)")
    deliverPurchaseNotificatioForIdentifier(productIdentifier)
    SKPaymentQueue.defaultQueue().finishTransaction(transaction)
  }
 
  private func failedTransaction(transaction: SKPaymentTransaction) {
    print("failedTransaction...")
    if transaction.error!.code != SKErrorCode.PaymentCancelled.rawValue {
      print("Transaction Error: \(transaction.error?.localizedDescription)")
    }
 
    SKPaymentQueue.defaultQueue().finishTransaction(transaction)
  }
 
  private func deliverPurchaseNotificatioForIdentifier(identifier: String?) {
    guard let identifier = identifier else { return }
 
    purchasedProductIdentifiers.insert(identifier)
    NSUserDefaults.standardUserDefaults().setBool(true, forKey: identifier)
    NSUserDefaults.standardUserDefaults().synchronize()
    NSNotificationCenter.defaultCenter().postNotificationName(IAPHelper.IAPHelperPurchaseNotification, object: identifier)
  }
}

That’s a lot of code! A detailed review is in order. Fortunately, each method is quite short.

paymentQueue(_:updatedTransactions:) is the only method actually required by the protocol. It gets called when one or more transaction states change. This method evaluates the state of each transaction in an array of updated transactions and calls the relevant helper method: completeTransaction(_:), restoreTransaction(_:) or failedTransaction(_:).

If the transaction was completed or restored, it adds to the set of purchases and saves the identifier in NSUserDefaults. It also posts a notification with that transaction so that any interested object in the app can listen for it to do things like update the user interface. Finally, in both the case of success or failure, it marks the transaction as finished.

If the transaction was completed or restored, deliverPurchaseNotificatioForIdentifier gets called to add to the set of purchased items and save the identifier in NSUserDefaults. It also posts a notification with that product’s identifier so that any interested object in the app can listen and do things like update the user interface. Finally, in both the case of success or failure, it marks the transaction as finished by calling finishTransaction on the payment queue.

All that’s left is to hook up IAPHelper as a payment transaction observer. Still in IAPHelper.swift, go back to init(productIds:) and add the following line right after super.init().

SKPaymentQueue.defaultQueue().addTransactionObserver(self)

Making a Sandbox Purchase

Build and run the app – but to test out purchases, you’ll have to run it on a device. The sandbox tester created earlier can be used to perform the purchase without getting charged. If only I could have a sandbox tester to do my grocery shopping! Here’s how to use the tester account:

Go to your iPhone and make sure you’re logged out of your normal App Store account. To do this, go to the Settings app and tap iTunes & App Store.

in-app purchase tutorial

Tap your iCloud account name and then tap Sign Out.

Build and run! You’ll see your product listed in the app. To begin the purchase process, tap the Buy button.

An alert will appear prompting you to log in. Tap Use Existing Apple ID, and enter the login details for the sandbox tester account that you created earlier.

Confirm the purchase by tapping Buy. The alert view notes that the purchase is being made in the sandbox as a reminder that you won’t be charged for it.

in-app purchase tutorial

Finally, an alert view will appear confirming the purchase was successful. Once the purchase process has been completed, a checkmark appears next to the purchased item. Tap on the purchased item to enjoy your new comic.

Finally you get to see this “Girlfriend of Drummer” rage comic that you’ve been hearing so much about!

in-app purchase tutorial

Restoring Purchases

If the user deletes and re-installs the app or installs it on another device, then they need the ability to access previously purchased items. In fact, Apple may reject an app if it cannot restore non-consumable purchases.

As a purchase transaction observer, IAPHelper is already being notified when purchases have been restored. The next step is to react to this notification by restoring the purchases.

Open IAPHelper.swift. In the StoreKit API extension, replace restorePurchases() with the following:

public func restorePurchases() {
  SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}

That was almost too easy! You’ve already set the transaction observer and implemented the method to handle restoring transactions in the previous step.

To test this out, after you’ve made a purchase (which you should’ve done in the previous step), delete the app from your device. Build and run again, and then tap the Restore button. You should see a checkmark appear next to the previously purchased product.

Payment Permissions

Some devices and accounts may not permit an in-app purchase. This can happen, for example, if parental controls are set to disallow it. Apple requires this situation to be handled gracefully. Not doing so will likely result in an app rejection.

Open IAPHelper.swift again. In the StoreKit API extension, replace the return statement in canMakePayments() with this line:

return SKPaymentQueue.canMakePayments()

Product cells should behave differently depending on the value returned by canMakePayments(). For example, if canMakePayments() returns false, then the Buy button should not be shown and the price should be replaced by “Not Available”.

To accomplish this, open ProductCell.swift and replace the entire implementation of the product property’s didSet handler with the following:

didSet {
  guard let product = product else { return }
 
  textLabel?.text = product.localizedTitle
 
  if RageProducts.store.isProductPurchased(product.productIdentifier) {
    accessoryType = .Checkmark
    accessoryView = nil
    detailTextLabel?.text = ""
  } else if IAPHelper.canMakePayments() {
    ProductCell.priceFormatter.locale = product.priceLocale
    detailTextLabel?.text = ProductCell.priceFormatter.stringFromNumber(product.price)
 
    accessoryType = .None
    accessoryView = self.newBuyButton()
  } else {
    detailTextLabel?.text = "Not available"
  }
}

This implementation will display more appropriate information when payments cannot be made with the device. And there you have it – an app with in-app purchase!

Where To Go From Here?

You can download the final project with all of the code developed above. Feel free to re-use the IAP helper class in your own projects!

The In-App Purchase Video Tutorial Series by Sam Davies covers all of the topics introduced here, but goes to the next level in Part 3 where he talks about validating receipts.

One shortcoming of the sample app is that it doesn’t indicate to the user when it is communicating with Apple. A possible improvement would be to display a spinner or HUD control at appropriate times. This UI enhancement, however, is beyond the scope of this tutorial. For more information on HUD controls, check out The iOS Apprentice 3 tutorial.

Apple has a great landing page for in-app purchase: In-App Purchase for Developers. It collects together links to all the relevant documentation and WWDC videos.

IAPs can be an important part of your business model. Use them wisely and be sure to follow the guidelines about restoring purchases and failing gracefully, and you’ll be well on your way to success!

If you have any questions or comments about this in-app purchase tutorial, then please join the forum discussion below!

And to end things off with a laugh, here’s a great iOS app rage comic made by Jayant C Varma from the original Objective-C version of this tutorial! :]

Coming Up With An iOS App Idea Rage Comic by Jayant Varma

The post In-App Purchase Tutorial: Getting Started appeared first on Ray Wenderlich.

Beginning Audio with AVFoundation Part 3: Audio Effects

Looking for Sprite Kit & Scene Kit Team Lead

$
0
0

SpriteKitSceneKitTeamLead-feature

Are you passionate about making iOS games with Apple’s built in APIs: Sprite Kit and Scene Kit?

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

Do you like learning and teaching others, and are you interested in building leadership experience?

If so, we have a great opportunity for you – we are currently looking for a team lead for our Sprite Kit & Scene Kit team!

Keep reading to find out what’s involved and how to apply.

Being a Team Lead

If tech editors are pillars that hold up the site, and final pass editors are the masterminds, then the team leads are the architects.

As team lead, you directly influence the three main requirements to make a great tutorial:

  1. A great idea: As a team lead, you are responsible for making the wishlist of what tutorials we’d like on the site, and vetting ideas from team members.
  2. A great team: As a team lead, you can make a great team by recruiting great team members, training existing team members to be great, and by removing people from the team who are not great (and are not learning).
  3. Great communication: As a team lead, you can have great team communication by staying on top of your team’s status, keeping Trello up-to-date, and sending regular status emails.

Being a team lead is a great way to lead the direction our site takes on covering Sprite Kit and Scene Kit, and influence a generation of programmers. It’s also a great way to gain leadership and project management experience, work directly with the myself and the rest of the Razeware team, get access to special opportunities like working on our books or conference, and become a true master/expert on your subject.

This is a paid part-time position. Hours can vary but it’s something you can easily accomplish in your spare time along with a full-time job.

How To Apply

We are currently only looking for advanced developers who have shipped an app using Sprite Kit or Scene Kit.

If you meet this requirement, then email me the answers to the following questions:

  • Why do you want to be the Sprite Kit & Scene Kit team lead?
  • Please tell me a little bit about yourself and your experience.
  • Have you read 2D iOS & tvOS Games by Tutorials and/or 3D iOS Games by Tutorials? If so, which ones, and what did you think?
  • What kind of tutorials would you like to see about Sprite Kit & Scene Kit in the next year?
  • What is the best app/game you’ve made or worked on, and why are you proud of the work you did on this app/game? [Please include link]
  • Please link to any examples of technical writing you have done in the past.
  • Please include links to: your GitHub account, your StackOverflow account, your Twitter account.

We already have a strong team with tons of Sprite Kit & Scene Kit development experience, and two published books. With your help and ideas, just imagine where we could take coverage of iOS games in the year to come.

Thanks – I look forward to hearing from you! :]

The post Looking for Sprite Kit & Scene Kit Team Lead appeared first on Ray Wenderlich.

Viewing all 4370 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>