Use the Sprite Kit to make games like Cut the Rope (Part 2)

Tram Ho

Translated from: https://www.raywenderlich.com/5347797-how-to-make-a-game-like-cut-the-rope-with-spritekit

In this tutorial, we will learn how to build a game similar to Cut the Rope using SpriteKit in Swift, the game will have animations, sound, effects, and physics! See part 1 here: https://viblo.asia/p/su-dung-sprite-kit-de-lam-game-giong-nhu-cut-the-rope-part-1-naQZRxYX5vx

Adding Joints to the Vines

The problem is that you still haven’t joined the rope components yet. To fix it, you need to add the following code at the end of addToScene(_:):

This code will set up the physical connection between components, connecting them together. Use SKPhysicsJointPin to join components. This type of join processing will allow when you impact the junction between the two nodes, allowing them to oscillate around the junction without moving too close or too far.

Build and relaunch the app. You will see the rope hanging from the tree in real life.

The final step is to attach the string to the pineapple. Still in VineNode.swift , navigate to attachToPrize(_:) . Add the following code:

This code will take the last segment of the rope, position it a little above the center of the prize (pineapple). You will need to leave it in this position to be able to follow the same award as reality. If it is the middle point of the prize, because of the pineapple’s weight, it can rotate around the connecting point. It will also create another junction to joint the string and the pineapple.

Build and run. If your code joint and nodes are set up correctly, you will see the results as shown below:

Snipping the Vines

Surely you have noticed that it is still not possible to cut the rope segment! You will solve that problem now.

In the next section, you will work with the touch method, which will allow the player to cut the strings that are hanging on it. Back to GameScene.swift , navigate to touchesMoved(_:with:) add the following code:

This code works as follows: First, it takes the current and previous position of each touch (touch). Next, loop through all the bodies in the scene that are located between the SKScene using SKScene ‘s handy method enumerateBodies(alongRayStart:end:using:) . For each body found, call checkIfVineCut(withBody:) is the function you will write in a few minutes.

Finally, the code will call the method to create a SKEmitterNode by loading it from Particle.sks , and adding it to the scene where the user touches. This will create a nice blue line of smoke where your fingers touch.

Now, navigate to checkIfVineCut(withBody:) and add the following code:

The code above will first check if the node that is connected to the physics body has a name yet. Remember, there are many guest nodes next to the parts of the rope, and you definitely don’t want to cut the wrong pineapple or crocodile! But you only name the nodes of the rope, so if the node has a name, you can be sure it is part of the rope.

Next, delete the node from the scene. Deleting a code also deletes its physicsBody, and expels any joint that is connected to it. You will now officially cut the string!

Finally, list all the nodes in the scene whose names match the names of the nodes you’ve just cut, enumerateChildNodes(withName:using:) scene’s enumerateChildNodes(withName:using:) . The nodes that will match consist only of nodes that are other segments of the same string, so you only need to loop through the segments of the string you have cut.

For each node, you create a SKAction , first obscuring the node and then removing it from the scene. The effect will run after being cut, each string will be blurred.

Buid and run the app. Try cutting the string – you can now cut all 3 segments and see the prize falling.

Handling Contact Between Bodies

When you write setUpPhysics() , you specify that GameScene will act as contactDelegate for physicsWorld . You will also configure contactTestBitMask of crocodiles to SpriteKit will notice when it touches the award. It is outstanding foresight!

Now, in GameScene.swift you need approval to deploy didBegin(_:) of SKPhysicsContactDelegate , which will activate each time confirmed the interaction between two masked bodies. There are a few things needed for this function – navigate to it and add the following code:

This code will check if the two interactive objects are crocodiles and prizes. You don’t know the order of the nodes, so you will check both directions. If you pass the test, you will activate a simple animation to shrink the prize and make it disappear.

Animate the Crocodile’s Chomp

You will also want to make the crocodile chew when you catch a pineapple. In the if statement where you performed the pineapple retraction, add the following line:

Now navigate to runNomNomAnimation(withDelay:) and add the following code:

The extra code removes any running animation with the crocodile using removeAllActions() . Then create a series of animations with, open and close and run sequentially.

This new animation will be activated when the prize falls into the mouth of the crocodile, creating a feeling of chewing.

Add the following code below enumerateChildNodes at checkIfVineCut(withBody:) :

It will make sure that the mouth of the crocodile opens when you cut the cord, so it is likely that the prize will fall into the mouth of the crocodile.

Build and run. The happy crocodile will now chew the pineapple when it falls into its mouth. But once again happening, the game just stopped there. You will solve that problem next.

Resetting the Game

Next, you will reset the game when the pineapple falls, or the crocodile eats it.

In GameScene.swift , navigate to switchToNewGame(withTransition:) , and add the following code:

The above code uses SKView's presentScene(_:transition:) to display the next scene.

In this case, the scene you move to will be a new instance of GameScene . You will also move using the effect of the SKTransition class. You define transitions as a method variable, so you can use different transition effects depending on what happens in the game.

Return to didBegin(_:) , and inside the if statement, after Prize Shrink and NomNom animations, add the following:

This snippet calls the switchToNewGame(withTransition:) using .doorway(withDuration:) to create the opening effect. It will show the next level with the opening effect. Build and run to see the effect. Pretty good, huh?

Ending the Game

You might think that you need to add some other physical body to the water to be able to confirm when the prize hits it, but that won’t help identify the pineapple falling off the screen.

Simply put, the next direction is better than just recognizing that the pineapple has moved away from the bottom edge of the screen, and the game is over.

SKScene provides update(_:) this function is called every frame. Find that method in GameScene.swift and add the following logic:

The if segment will check if the pineapple’s y coordinate is less than zero (negative value) – that’s it, the bottom of the screen. If so, call switchToNewGame(withTransition:) to start the level again, this time use .fade(withDuration:) .

Build and run. You will see the screen dims and switches to a new screen whether the player wins or loses.

Adding Sound and Music Now you will add a nice song about the forest from incompetech.com and some sound effects from freesound.org .

SpriteKit will process sound effects for you. But you will use AVAudioPlayer to play background music every time you switch levels.

Adding the Background Music

To add music, add the following attribute to GameScene.swift :

This command initializes a property, so that all GameScene instances will be able to access the same backgroundMusicPlayer . Navigate to setUpAudio () and add the following code:

The above code checks if backgroundMusicPlayer already exists. If not, create a new AVAudioPlayer with BackgroundMusic that you added to Constants.swift earlier. It will then convert it to a URL and assign it to the property. The number of iterations numberOfLoops to be -1, this will make the song repeat forever.

Next add the following code at the end of the setUpAudio() function:

First it will start the music so when the scene is loaded the first time. Then loop infinitely until you exit the app or another mehtod called stop() .

You can call play() without checking if the player is knitting play, but this way the music won’t rewind or restart if it played at the start of the level.

Adding the Sound Effects

When you’re here, you can set up all of the sound effects you want to use later. Unlike music, you won’t want to play sound effects right away. Instead you will create one into SKActions when playing the audio later.

Return to the beginning of the GameScene class, and add the following property:

Return to setUpAudio() and add the following code to the end of the method:

This code initializes the sound using SKAction ‘s playSoundFileNamed(_:waitForCompletion:) . Now it’s time to play the sound effects:

Find update(_:) av adding the following code in the if statement above the call to switchToNewGame(withTransition:) :

It will play a splash sound when the pineapple touches the water. Next, find didBegin(_:) and add the code below below the line runNomNomAnimation(withDelay:) :

It will add chewing sound when the crocodile catches the prize. Finally, navigate to checkIfVineCut(withBody:) and add the following code to the end of the if statement:

This segment will play a sound when the player cuts the strings.

Build and run to enjoy the sound of the crocodile eating pineapple!

Getting Rid of an Awkward Sound Effect

Do you see any bugs? If the prize falls without winning the crocodile, the sound of the water will play several times. This is because the “level complete” processing is repeated until the game switches screen. To fix it add a new attribute to the top of the class:

Now update(_:) the update(_:) and didBegin(_:) by adding the following code to the beginning of each function:

Finally, inside the if section of the same method, add the line of code to set the status isLevelOver to true:

Now every time the game senses isLevelOver is set, whether because of the pineapple touching the ground, or the crocodile, it will stop checking the game win / lose. It will not repeat sound effects anymore.

Build and run. No more weird sound effects!

Adding Some Difficulty

After playing a few rounds, playing it will become quite easy. You will easily feed the crocodile with just 1 time through all 3 strings.

Make it more complicated by using the values ​​in Constants.swift , CanCutMultipleVinesAtOnce .

In GameScene.swift , add the attribute to the top of the GameScene class:

Find checkIfVineCut(withBody:) and add an if to the beginning of the function:

Add the code at the end of the above function, inside the if statement:

Just to keep everything together, navigate to touchesBegan(_:with:) and add the following line:

By doing this, you will reset didCutVine every time the user touches the screen:

Build and tremble. You will see that you can only cut one string at a time. To cut another string, you need to lift your hand and slide it back.

Share the news now

Source : Viblo