Swift App Tutorial: Swing Copters Part II

wift Copters Swing Copters

In the first part of the tutorial “Swing Copters – Swift Copters” we establish the base of the game. In this chapter, we are going to finish the job implementing:

  1. Move our hero with taps
  2. Center the camera on him
  3. Create the enemies
  4. Detect collisions
  5. Transition to another scene

At the end of the post you will have a game like this:

1. Move a SKNode. Handle touches in SpriteKit with Swift

Lets give to our Swift Copter hero some rock & roll! We want to implement the same behaviour of the Swing Copter game: When you tap the screen, the hero change his direction and acceleration direction 180 degrees. If you tap again and again your hero will go up in a little zig-zag.

In order to handle touches in SpriteKit, we should override “touchesBegan” in our GameScene.swift:

Here you have some explanations:

  • The first “if” of the method is used in order to start the game. When we created our hero in startCopter(), we put it with dynamic = false. Until we change it to true, gravity and impulses don’t affect him. Also, we add to the sprite of the copter some funny animation of movement with 4 SKTextures
  • And now we are going to perform a second “if”. This time, what we are evaluating is the direction of the gravity before the touch. If the gravity (and our hero’s direction) was positive, we are going to change it and to apply a negative impulse to our hero. And vice versa. Again, we animate a little bit our hero, this time with some ration changes (to make the direction change more polite)
  • At the end of the method we have an important code. Remember when we init the world, and we put some physic border to delimit the screen? We used for that the frame of the view (320×568). Now we are moving our hero up, and we want him to reach the sky limit. So while our hero is moving up, we are going to change the frame of our screen limits to make it higher, so the copter will never touch the sky without limits (Ey, the width will be constant -…a deadly constant for him-)

Build and Run! Play a little bit. Have you notice? There are some invisible walls at each side of the screen. However, our hero flies away at the top.

But there is a problem, right? We need the camera to follow him!

2. The camera: Follow that dog with a flying hat!

SpriteKit doesn’t have a “camera” method to center the scene on a node. They recommend us a trick. We are going to move the nodeWorld (remember, where the rest of the nodes are) in the other way of the hero when the hero moves.

How are we going to perform this? We are going to move our hero and to apply impulses to him. But, at the end of each frame, we are going  move the rest of the scene the same length in the other way. SpriteKit has a method that executes every frame (in fact there are more than one) where we can do this job. (you can check Apple doc here for details)

Copy this:

As the name of the method says: didSimulatePhysics() is the method that is fired every frame when all the physics calculations and effects have finished.

Here we are going to do some more work, but at this time, we are only calling to our method centerOnNode. Build and Launch. See the effect?

3. It is time for the bad guys: The enemies

We are going to generate some enemies to stop our hero. This is an infinite scroll game…so if the player is good, there could be infinite enemies! But we want to take care of the memory of the iPhone so we will need some trick to maintain it low.

We can generate 5/10 enemies (the next ones the hero is going to meet)…and when those enemies disappear at the bottom of the screen, we could move them up again to the next position. In this way, we only generate 5/10 objects and reuse them forever.

Our enemies will have different sprites: They are composed by a bar and a hammer head at the end. One of this packs in each side of the screen. Let’s create 10 (pairs) of them.

So we have to create 10 enemies (let’s use a “for” loop), composed each one by 2×2 spriteNodes (2bar+2hammerHead), which they have their own physicalBodies to detect collisions, and that are going to be reused later.

Copy the following method, and call it at didMoveToView func.

  1.  We are going to spread each enemy in a random X position as in the original game. So we generate it there (//1)
  2. Our enemies will have a node tree with this node as the parent. In this way, when we want to reposition the enemy to reuse it, we have to move only this node (the father).
  3. Here we are creating the Bars. Notice how we use the randomX coordinate generated in point 1. Moreover we use a parameter to specify the distance between both sides on the enemy (you can play with it to make the game easier or harder).
  4. We create and attach two hammer heads to both bars. See how we set up an initial rotation, because we are going to animate them!
  5. We create the swing animation here. In order to do it right, the anchor point of the nodes should be (0,0). The rotateByAngle action rotates the node with the anchor point as the origin. You can play with it to see the different effects.
  6. Now we add every sprite to the enemy and position it in some Y coordinate. We save this coordinate in order to keep track of it. We are going to change it for the next enemy in every step of the loop (point 7)
  7. Add some distance for the next enemy.

If you build this, you will notice some errors. We need to add these vars on the top of our scene:

  • lastYposition: Y-axis coordinate of the last enemy
  • ditanceBetweenBars: The horizontal gap between bars where our hero has to pass through
  • ditanceFromBarToBar: The vertical distance between two enemies.
  • Node where we are going to add every enemy.

Lets add nodeEnemies to our nodeWorld and call startEnemies in our didMoveToView. The method should look like this:

Now build and run it again. There should be enemies around you. But after 10 of them…nothing!...we still need to reuse those that are offscreen when the hero has passed through them.

Which place could execute code in every frame and allow us to move any node as soon as possible when it is not needed anymore? We have used it yet…didSimulatePhysiscs! Add this call and this new method:

See what shouldRepositeNodes does? We get all the children nodes of nodeEnemies (every single enemy was added to this node). With go through that array an for every node, we check if it is under our hero more than 300px (out of screen at the bottom). When that happens, we are moving that enemy to the next lastYPosition+distanceFromBarToBar. An we have a “new” enemy ready to rock our hero!

Build & Run…now you should see an infinite game!

 4. Stopppp no no stop! Ouch… How to detect collisions with Swift

Have you trained a little bit? Okey! Now it is time for our hero to demonstrate real skills. We are going to detect the collisions.

We have set up physicalBodies everywhere: our hero, the invisible walls of the screen and the enemies (Bar and hammer head). We even specify which collisions should be detected with our hero before:

So now, it is time to handle those collisions. Add these two new methods to our scene:

As you imagine, didBeginContact got called when a contact between two physical bodies happen. Then, we check the categoryBitMasks. When one body has categoryCopter (the hero) and the other is an Enemy or the Screen borders…our hero should die!

In our game, we are going to transit to another scene, where we will show the user a “game over” text. But remember…our viewController is in charge of the transitions between scenes, so we call him first!

5. The Game is Over. SKTransitions between SKScenes

We need to do some changes in our GameViewController, but I let you check them in the final project. It is easy to make a transition between scenes, for example:

 

Here you have the full code of the tutorial:

I have added there two more things: a score node with the points and some animated clouds. But that is your homework! Check them and if you have any questions, let me know in the comments :).

 

I am preparing a video-course with full step by step explanations in video, and much more features for this game template. You could use it to have your own game in the Appstore in 2 days! Do you want to hear about it? Write me!

About @marioeguiluz

iOS Freelancer, Entrepreneur and Mobile App Expert

Categories: All, Apps, Development, Tutorial

6 comments

  • fishdawgza

    If anyone is attempting this tutorial and finding problems its because the spelling in the code is atrocious among other irritating things such as calling .addChild twice for the same SKSpriteNode – which causes it to crash.

    Do not copy the code as is. Code through every line meticulously and looked out for those buggy repetitions

    • @marioeguiluz

      Hi fishdawgza!
      Thanks for your warning about “atrocious and irritating” things 😀 ! (could you point them? I will fix them asap!)
      Anyway, you can download the github project, it is working as I write this!

  • Teboul Jonathan

    Hi,

    thank you so much, I have been a iOS developer for a long time and I am developing my first sprite kit game in swift. Thanks to you I have learnt many things. But I am stuck with a very very simple project: 4 nodes in the game scene and 0 nodes in the menu scene. I have simplified a lot my sample to find out a solution. I have a ball in the game scene and its move is very smooth. When i change the scene to the menu scene then I get back to the game scene the move is laggy. Could you please look at my tiny project or just the gamescene.swift. I am willing to pay if you could help me, I have been working on it for many days and I am desperate, that would be very kind of you. Thank you so much in advance!

    John

Leave a Reply

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