SpriteKit Game From Scratch, Swift 2.0, part 2

Swift 2.0, Xcode 7.1.1
Part 2 of the SpriteKit Game tutorial





We’ll continue with our tutorial on creating a SpriteKit Game from scratch. Last we took off where we were able to create an instance of our hero on every tap on the screen. However we won’t really be creating our hero or the enemy with a tap on the screen, we rather want for the game logic to control that. We also don’t really want our hero or the enemy to be rotating for our example, but you could leave that function in for something else later on if you wish.


We’ll add a couple of things we’ll need later in the global.swift file:


What we are doing is – saying that we’ll have an SKScene, called gameScene, we are getting the scene’s Width and Height and we are setting the positions of our Hero and Enemy.
The only thing now is that we need to make sure there is a gameScene and it’s not nil.
In order to do that we’ll add this at the beginning of our didMoveToView:

This basically says that the our ‘gameScene‘ is in fact the current loaded GameScene, thus we are getting the Width and Height of the loaded scene.

Next we’ll place 2 functions in the GameScene.swift:

First one we’ll spawn our hero at a position that we could pass along when calling the function and the second one will spawn an enemy at a position, where we could also pass the level of the enemy ( we’ll have to figure that out 🙂 )
Let’s comment everything inside the ‘touchesBegan‘ method, in order to disable tap hero creation.
Now let’s call our hero creating method in the didMoveToView like this:

Run your project and you should now see this:

Next we need to create the enemy class.
In order to do that created a new Swift file and copy everything from the hero.swift, then change the class name from ‘hero’ to ‘enemy’ and change the texture declaration to this:

Add another line in the ‘didMoveToView‘ method in order to create the enemy:

We said we are going to pass an integer to define the enemy’s level, but we never actually implemented this. So let’s make a little change to our enemy spawn method:

The only thing different here is that we are increasing the health of the enemy based on the level we pass. Obviously you could have other thing change as well, but in order to keep things simple here we’ll just change the Health property.

Run the project and you’ll see this:

To make things a bit more interesting we’ll want our enemy to be moving up and down.
Let’s add this function to the bottom of the enemy.swift file:

Then at the bottom of the init of the enemy call the moving function and we’ll just do speed of 50 for now( right below adding the top texture ):



Shooting and Projectiles

Now we need to figure out how the shooting will work. Originally we set up the shooting and weapon protocols, but we set it up in way where the gun will always hit the target. We can create an example like that later, but for now I want to create a flying projectile, that can either Hit or Miss it’s target. To do that we’ll use a similar method as with the Hero and Enemy creation – we’ll create a new class , called ‘Projectile‘ , subclass of SKNode. We could then either create separate subclasses for each bullet – like bulletEnemy and bulletHero or use the same one. We’ll add one more zLayer in our Global file, as we want our projectiles to be on top of everything else:

Also, until now we’ve been adding objects to the GameScene directly, which is not a very good practice for a variety of reasons. One of them is related to later removing them. It’s best to create an extra layer, that will serve as the parent to the object we need to interact with.
If you have many different groups of objects it’s wise to create different parent layers ( SKNodes ), so that later you can easily conduct operations on them. Let’s say you have a ton of enemies – you will add them to a separate layer called(for example) enemyLayer( of type SKNode).
Later you could iterate through all the children of that layer in order to search, count, pause or other operation that might be available. It is also worth said that the best practice for removing Nodes from the game is to create an Array of Nodes. If you have noticed there is a built-in function inside the GameScene , called ‘update’ – this function is called every frame, 60 time per second if we are running at 60 fps. Inside this function Update we’ll just create another function that will remove everything inside the Array from the game.
Let’s add these 2 functions to the global.swift:

We’ll add a function to the GameScene to create the Layer:

, and then call it in the didMoveToView:

Then we need to change our functions where we are creating our Hero and Enemy, adding them not directly to the Scene, but rather to the newly created objectsLayer:

Now, let’s create a new swift file and call it projectile.swift – we’ll put all our projectile stuff in there – the main class ( subclass of SKNode ) and the 2 subclasses of it, one for each different bullet ( hero’s and enemy’s ):

Analyze the code and the notes/comments within it. We are basically creating one main projectile and inside we are creating a function to create a SKSpriteNode on top of it, based on the texture we pass it. Then inside each of the subclasses we just call that function, passing it the desired bullet texture.

Next we need to create the shooting action inside the Hero and Enemy classes.
The only difference, besides that the textures will be different will be the fact that the Hero’s bullets will fly out to the right and the Enemy’s ones will fly to the left.
Here is the Hero’s shooting function we’ll add to the bottom of the class:

Then the one for our Enemy:

Then, in order to test the shooting, let’s call the function as soon as the Hero and Enemy are initialized. Put this inside the override init() { .. } at the bottom:

Run the project and you should see the 2 projectiles shoot out.
That’s good, except we will want the Enemy to be shooting repeatedly.
In order to do that we’ll need to create an action for the shooting and call it to be repeated.
Also, in most games to make things a bit more interesting you need to add a random element.
It would be better if we can have the Enemy shoot at random intervals.
In order to do that we’ll first add 2 more functions to our global file:

These, when called, will generate a random number, first one a CGFloat, second one – an Integer.
However we won’t need them for the shooting random timing, as we can use another method, but you will find these useful on many other occasions.
First we’ll need to move everything from our shoot() action to a new func that we’ll call shootingRepeater:

When called, this function will return our Shooting action, as a SKAction – a general class in swift, that can be utilized for various operations, allowing to attach actions onto objects, have them repeat and more.
Then we’ll change our shoot func to this:

This will also return a SKAction when called. Inside we have a Delay, a sequence – calling the shooting SKAction, then the delay – and a Repeat Forever action that just keeps repeating that sequence, until stopped or until the object it’s ran on is removed from the Scene.

Let’s change the shooting call at the bottom of the Enemy’s initializer to this:

It’s a good practice to assign a Key to Actions, as this allows you to later stop them, by calling them.
Now we’ll add one more texture to the global.swift file:

You need to add the background to your project – this is just something free I found on OpenGameArt.org again(feel free to use any large enough image you want ):

Just make sure that the name in the SKTexture call matches the name of the file.

It’s a good practice to put everything in it’s own function.
So we’ll create one more at the bottom of the GameScene:

Than call it in the didMoveToView method right after setupLayers():

Now hit run and you should see something like this:


We’ll see that things don’t look quite right. The bullets are moving up and down along with the enemy’s movements. The reason why is that inside our shooting action we are adding them as children of the Enemy itself. Instead we need to add them to the objectsLayer.
However if we add them to the objectsLayer we need some way to be able to position their starting point to be the Enemy. In order to do that we need to expose the Enemy and the Hero class ( for later ) outside the gameScene.
Let’s declare 2 variables in our global.swift file again:

We’ll slightly modify our spawning functions in order to actually return a Hero and an Enemy:

And then instead of just calling the functions in the didMoveToView, we’ll use them in order to initialize our characters like this:

Very slight change, but this will now allow us to change our shooting action inside the enemy class to this:

Notice the difference – we are adding the bullets as a chid to the objectsLayer and we are using our newly created instance of an enemy ( spawnedEnemy ) to set the bullet’s starting position.
Finally, run the project and you should see that the bullets are behaving more appropriately:

We’ll end with Part 2 here. In the next part we’ll look into ways of detecting collision, scores, removing objects and much more.

Ready with this part? Go to Part 3
Please feel free to ask any questions in the comments below or just join our Slack group.

Please find the full files at my repo here:
SpriteKit Game From Scratch – Part 2

Cheers !



Missed something from the previous part ? – Go to Part 1


8 thoughts on “SpriteKit Game From Scratch, Swift 2.0, part 2

  1. Your gameScene variable still returns nil. I’ve added it to the top of my didMoveToView and I still get frameH found nil when unwrapping an optional variable. I’m a complete noob, so I may have pasted something wrong, but I think the global files are getting called before the didMoveToView is and so it get a value of nil.

    When I added the line “gameScene = scene” to the viewDidLoad method in the GameSceneController page it worked like a champ.

    • Razvigor Andreev says:

      It’s a bit tricky, as these are really not initialized at the point, however I’ve run the code and it compiled fine on my machine. Did you compare your code to the one from the link on GitHub ? I’ve copied that from the one I had running. If you want to be super safe you would want to get the frame values after the View loads, you could also get the UIScreen size instead, but there are some other problems there, since the scene gets stretched across the screen. Basically, I prefer using global files, however you have to be careful 🙂 Also, if you are creating global functions ( public func ) that are outside a class, but you want the func to be using something from within a game scene you can have the functions take a parameter like : public func myFunc( someScene: GameScene ) { do something with someScene here } …
      Anyway … let me know what happens 🙂

    • Razvigor Andreev says:

      Also what is ‘scene’ in your didMoveToView method ?

  2. i tried to run the project and this error came up. HELP ME PLEZ

    • Razvigor Andreev says:

      You need to call setupLayers() first.
      When you call spawnHero() you are trying to add it to a layer that doesn’t exist yet.
      You just have the functions around.

  3. thank you it worked!

Leave a Reply

Your email address will not be published. Required fields are marked *