kodeco.com Forums

How to Make a Game Like Candy Crush with Swift Tutorial: Part 1

Learn how to make a game like Candy Crush for your iPhone in this 2-part tutorial series - and get a great Swift tutorial along the way!


This is a companion discussion topic for the original entry at http://www.raywenderlich.com/75270/make-game-like-candy-crush-with-swift-tutorial-part-1

I’m making a match game using some of the ideas from this tutorial. The Cookies.swift file uses ‘static func random() → CookieType’ to create random numbers for positioning the sprites.

This method for random numbers allows repeats and doesn’t guarantee utilization of all members of the array. Does anyone know a way to use arc4random_uniform in this way to assure no repeats until all are used?

The line of code is ‘return CookieType(rawValue: Int(arc4random_uniform())+1)!’

Any guidance will be appreciated.

I follow tutorial until “Build and run, and you should finally see some cookies:”
I build and run project but sometime cookies appeared on screen but sometime not, it just blank screen (without changing code).
Can anyone explane what do i do wrong ?

Latest versions of Xcode can be a bit buggy, and possible problems as follow:

  1. The texture aren’t fully copied to the device/simulator
  2. The size of the sprite/tile is different from the texture of the node (cookie)

Possible solutions:

  1. Clean, delete derived, rebuild
  2. If you aren’t copy/pasting the tutorial (aka if you’re using your own textures/images), be sure to resize each SKTextureNode … One solution is to use the convenience method SKSpriteNode(texture: SKTextureAtlas(named:).textureNamed(name:), size:)

khanh_pham, had similar issue, in GameScene.swift changed order of addChild so cookies and tiles show in front of background instead of behind:

override init(size: CGSize) {
super.init(size: size)
anchorPoint = CGPoint(x: 0.5, y: 0.5)
let background = SKSpriteNode(imageNamed: “Background”)
addChild(background)
addChild(gameLayer)
let layerPosition = CGPoint(
x: -TileWidth * CGFloat(NumColumns) / 2,
y: -TileHeight * CGFloat(NumRows) / 2)
tilesLayer.position = layerPosition
cookiesLayer.position = layerPosition
gameLayer.addChild(tilesLayer)
gameLayer.addChild(cookiesLayer)
swipeFromColumn = nil
swipeFromRow = nil
}

I just find out that you just need to stop and clean project then build run again will fix the problem. The reason may be swift do not build complete.

@hollance
One question thought, preparing for Swift 3 where C-style for loops are deprecated, any idea on the best way to “swiftify” these kind of loops?

for var i = column - 1; i >= 0 && cookies[i, row]?.cookieType == cookieType; --i, ++horzLength { }

I was thinking of something like
for i in (0 ..< column).reverse() where (monsters[i, row]?.monsterType == monsterType)

then increment the variable, but it obviously fails, as the “where” statement doesn’t apply simultaneously on the initial parameter.

Any clue?

I did the following which seems to work. Not sure if it is the accepted solution.

private func hasChainAtColumn(column: Int, row: Int) -> Bool {
    let cookieType = cookies[column, row]!.cookieType
    
    var horzLength = 1
    for index in (column - 1).stride(through: 0, by: -1) {
        if cookies[index, row]?.cookieType == cookieType {
            horzLength += 1
        }
        else {
            break
        }
    }
    for index in (column + 1).stride(to: NumColumns, by: 1) {
        if cookies[index, row]?.cookieType == cookieType {
            horzLength += 1
        }
        else {
            break
        }
    }
    if horzLength >= 3 {
        return true
    }
    
    var vertLength = 1
    for index in (row - 1).stride(through: 0, by: -1) {
        if cookies[column, index]?.cookieType == cookieType {
            vertLength += 1
        }
        else {
            break
        }
    }
    for index in (row + 1).stride(to: NumRows, by: 1) {
        if cookies[column, index]?.cookieType == cookieType {
            vertLength += 1
        }
        else {
            break
        }
    }
    return vertLength >= 3
}

I’m trying to build this game in xCode 7.3.1 and I’m getting the following errors:

Use of unresolved identifier ‘rawValue’ in the following code block:

var spriteName: String {
let spriteNames = [
“Croissant”,
“Cupcake”,
“Danish”,
“Donut”,
“Macaroon”,
“SugarCookie”]

return spriteNames[rawValue - 1]

}

Type ‘Cookie.CookieType’ does not conform to protocol ‘CustonStringConvertible’ in the following code block:

enum CookieType: Int, CustomStringConvertible {
case Unknown = 0, Croissant, Cupcake, Danish, Donut, Macaroon, SugarCookie

}

Note that CustomStringConvertible was recommended to replace Printable.

Here is the entire class code for context:

import SpriteKit

class Cookie: CustomStringConvertible {
    var column: Int
    var row: Int
    let cookieType: CookieType
    var sprite: SKSpriteNode?
    
    init(column: Int, row: Int, cookieType: CookieType) {
        self.column = column
        self.row = row
        self.cookieType = cookieType
    }
    
    enum CookieType: Int, CustomStringConvertible {
        case Unknown = 0, Croissant, Cupcake, Danish, Donut, Macaroon, SugarCookie
        
    }
    
    var spriteName: String {
        let spriteNames = [
            "Croissant",
            "Cupcake",
            "Danish",
            "Donut",
            "Macaroon",
            "SugarCookie"]
        
        return spriteNames[rawValue - 1]
        //return spriteNames.rawValue - 1
    }
    
    var description: String {
        return "type:\(cookieType) square: (\(column),\(row))"
    }
    
    var highlightedSpriteName: String {
        return spriteName + "-Highlighted"
    }
    
    static func random() -> CookieType {
        return CookieType(rawValue: Int(arc4random_uniform(6)) + 1)!
    }

}

Any help is greatly appreciated.

Thanks!indent preformatted text by 4 spaces

That’s because you closed out your CookieType enum. Those variables need to be inside.

Duh!!!

@jj_tagy Much appreciated!!! That, and a little closer inspection of my code vs the descriptions cured my errors to this point…

Thanks!!!

You really need to update this tutorial if you’re going to leave it on the website. A lot of the code is outdated and no longer works.

Also, you really need to write the functions (in the tutorial) BEFORE you reference them because beginners will get stuck trying to figure out why there is an error when your code references a function that doesn’t yet exist. They will not KNOW it’s a function and not some built in swift code. Clarity is best. Just sayin’.

As it stands now, this tutorial is useless to most people since about half way through your code creates an error that prevents moving further in the tutorial. Specifically when you state to add the following to the viewDidLoad method:

scene.handleSwipe = swipeHandler

this isn’t properly linking to the GameScene.swift file’s reference of swipeHandler. I’m certain it’s a difference in updated swift code (which again, sort of begs the question on why this tutorial isn’t updated if it’s still visible on the website).

Please fix this.

Actually, I found that working through this tutorial and identifying the things that have changed in the newer Swift helped to understand the code much more than just copying what is there.

As for the swipeHandler piece, you need to do all pieces before it “connects”.

of course. but that’s not the point. the tutorial is written very disjointedly. not a HUGE deal to those of us that already understand programming and can work our way through the errors but for beginners it pretty much guarantees they give up. that benefits no one.

i figured out the issue with the swipeHandler but again, a better written tutorial and that “error” would never have happened.

oh well.