Search code examples
swiftsprite-kitskspritenode

How to create a function that will add blocks to a grid?


I have this code that creates a 15x12 grid of blocks, but I am trying to access the index of each block and be able to remove or add blocks at that given index. I think I need to use a 2d array, but I am not sure how to add the blocks to an array that will make it easy for me to get each block at their index. Please comment any tips or advice you have, thanks!

         for i in 0...12{
            for j in 0...16{

            let block = SKSpriteNode(texture: blockImage, size: blockSize)
                block.position.x = block.frame.width/2 + CGFloat((64*j))
                block.position.y = frame.height - block.frame.height/2 - CGFloat((64*i))
                block.zPosition = 1
                
                addChild(block)
        }
        }

enter image description here


Solution

  • Let's follow the idea you proposed.

    Step 1

    We can create a Dictionary were we map the index of a node (in the key) with the node (in the value).

    struct Index: Hashable {
        let i: Int
        let j: Int
    }
    private var grid:[Index: SKNode] = [:]
    

    Step 2

    Now when you are adding the nodes to the parent, you just need to save the Index-Node relationship into the dictionary.

    func addSprites() {
        let blockImage = SKTexture(imageNamed: "TODO")
        let blockSize = blockImage.size()
    
        for i in 0...12{
           for j in 0...16{
               let block = SKSpriteNode(texture: blockImage, size: blockSize)
               assert(grid[Index(i: i, j: j)] == nil)
               grid[Index(i: i, j: j)] = block // <------------
               block.position.x = block.frame.width/2 + CGFloat((64*j))
               block.position.y = block.frame.height - block.frame.height/2 - CGFloat((64*i))
               block.zPosition = 1
               addChild(block)
           }
        }
    }
    

    Step 3

    And finally you can easily remove a node for a given index

    func removeSprite(at index: Index) {
        guard let node = grid[index] else {
            debugPrint("No node found at index: \(index)")
            return
        }
        node.removeFromParent()
        grid[index] = nil
    }
    

    Full code

    class GameScene: SKScene {
    
        struct Index: Hashable {
            let i: Int
            let j: Int
        }
        private var grid:[Index: SKNode] = [:]
    
        func addSprites() {
            let blockImage = SKTexture(imageNamed: "TODO")
            let blockSize = blockImage.size()
    
            for i in 0...4{
               for j in 0...4{
                   let block = SKSpriteNode(texture: blockImage, size: blockSize)
                   assert(grid[Index(i: i, j: j)] == nil)
                   grid[Index(i: i, j: j)] = block // <---
                   block.position.x = block.frame.width/2 + CGFloat((64*j))
                   block.position.y = block.frame.height - block.frame.height/2 - CGFloat((64*i))
                   block.zPosition = 1
                   addChild(block)
               }
            }
        }
        
        func removeSprite(at index: Index) {
            guard let node = grid[index] else {
                debugPrint("No node found at index: \(index)")
                return
            }
            node.removeFromParent()
            grid[index] = nil
        }
    
    }
    

    Quick Playground Test

    enter image description here