SpriteKit Basics: Sprites

SpriteKit Basics: Sprites

In this series, we're learning how to use SpriteKit to build 2D games for iOS. In this post, we'll continue our exploration of SpriteKit nodes, and learn about a special kind of node called a "sprite"—an SKSpriteNode.

To follow along with this tutorial, just download the accompanying GitHub repo. It has a folder called ExampleProject Starter. Open the project in that folder in Xcode, and you're ready to go!

Sprite Nodes

An SKSpriteNode is drawn either as a rectangle with a texture mapped onto it, or as a colored untextured rectangle. Creating a SKSpriteNode with a texture mapped onto it is the most common, as this is how you bring your game's artwork to life.

Add the following to the didMove(to:) method within GameScene.swift.

Here we are using the convenience intiailizer init(color:size:) which will draw a rectangular sprite with the color and size you pass in as parameters. If you test the project now, you will see half of the red square showing.

red sprite

You might be wondering why only half of the sprite is showing since we already determined that SKNode's origins are at (0,0). This because the SKSpriteNode's frame and therefore its texture is centered on its position. To change this behaviour, you can change the sprite's anchorPoint property, which determines the point at which the frame is positioned. The diagram below shows how the anchorPoint works.

Diagram showing the anchorPoint property within a coordinate system

The anchorPoint is specified in the unit coordinate system, which places (0,0) at the bottom left and (1,1) at the top right corner of the frame. The default for SKSpriteNodes is (0.5,0.5).

Go ahead and change the anchorPoint property to (0,0) and notice the difference it makes.

Now, if you test, you will see that the sprite is lined up perfectly with the bottom left of the scene.

red sprite aligned bottom left

Now let's move it to the top center of the scene by changing its position property. Replace your didMove(to:) function with the following:

Notice how we had to subtract from both the x and y values to center the sprite. If we had left the anchorPoint at its default then it would already have been centered on the x axis. It is important to remember that when you change the anchor point, you may have to make some adjustments in your positioning.

red sprite centered top

Textured Sprites

That red box is good for practice with positioning, but you'll usually want to texture your sprite with artwork for your game. 

Let's create a textured SKSpriteNode. Add the following code at the bottom of the didMove(to:) method.

Here we use the convenience initializer init(imageNamed:), which takes as a parameter the name of an image without the extension. This is the easiest way to create a textured sprite as it creates the texture for you from the image you pass in. 

The other way to create a textured SKSpriteNode is to create an SKTexture beforehand, and use one of the intializers that take a texture as a parameter.

textured sprite

Let's create a couple more SKSpriteNodes and change some of their properties. Again, add these to the bottom of your didMove(to:) function.

Here we create two SKSpriteNodes, enemy1 and enemy2. We set the xScale on enemy1 to 2 and change the zRotation on enemy2 to rotate it by 90 degrees. (The zRotation property takes it values in radians, and a positive value indicates a counterclockwise rotation.) 

We've experimented with changing a few properties on a sprite. Take a look at the documentation for SKNodes and SKSpriteNodes and try changing a few of the other properties to see the effects they have.

textured sprite properties changed

Sprite nodes are good for basic rectangles and textures, but sometimes a more complex shape will be needed. The SKShapeNode has you covered in those cases. We'll take a look at shape nodes next.

Shape Nodes

Another useful node is the SKShapeNode. This node renders a shape defined by a Core Graphics path. SKShapeNodes are useful for content that cannot be easily realized with an SKSpriteNode. This class is more memory intensive and has lower performance than using an SKSpriteNode, so you should try to use it sparingly.

To assign a shape to SKShapeNode, you can set a CGPath to the node's path property. However, there are a few initializers that offer predefined shapes such as rectangles, circles, and ellipses. Let's create a circle using the convenience initializer init(circleOfRadius:).

Then, add the following to the bottom of the didMove(to:) method.

We change a few properties on the shape node, position it, and add it to the scene. It is very easy to use the predefined shape initializers. However, creating a complex CGPath manually takes a considerable amount of time and is not for the faint of heart as it usually involves some complex math. 

Thankfully, there is a tool that lets you draw shapes visually and export their CGPath as Swift code. Check out PaintCode if you want to learn more.

shape node

Sprite Nodes and Shape Nodes will cover most cases, but sometimes you may wish to display video in your apps. The SKVideoNode, which we'll take a look at next, has you covered.

Video Nodes

The last node we will be taking a look at is the SKVideoNode. As the name implies, this node allows you to play video within your games.

There are a few different ways to create an SKVideoNode. One uses an instance of an AVPlayer, another just uses the name of a video file that is stored in the app bundle, and the third way is to use a URL.

One thing to keep in mind is that the video's size property will initially be the same as the size of the target video. You can change this size property, though, and the video will be stretched to the new size.

Another thing to be aware of is that the SKVideoNode offers play() and pause() methods only. If you wanted more control over your videos, you would initialize an SKVideoNode with an existing AVPlayer and use that to control your videos.

Let's use the simplest method to create an SKVideoNode. Add the following to the bottom of the didMove(to:) method.

Here we used the intiailizer init(fileNamed:) to create a video. You pass in the video's name along with the extension. I have not included a video along with the project's source code, but if you want to see this work, you can add a video named "video.mov" to your project.

Conclusion

This completes our study on nodes. After reading this post and the previous one, you should have a good understanding of SKNodes and their subclasses. In the next part of this series, we will take a look at SKActions and using physics within our games. Thanks for reading, and I will see you there!

In the meantime, check out some of our other great courses and tutorials on creating iOS apps with Swift and SpriteKit.

Also, check out our SpriteKit courses! These will take you through all the steps of building your first SpriteKit game for iOS, even if you've never coded with SpriteKit before.

 

Source: Tuts Plus

About the Author