'In swift for spritekit, how would I change the textures of nodes when they are placed?

I’m currently working on a matching game and when the user touches the nodes (Fruit match cards) I want them to display different images when a user clicks the nodes (Fruit match cards).

This is my current code:

import Foundation import SpriteKit

class EasyScreen: SKScene {

override func didMove(to view: SKView) {
    var background = SKSpriteNode(imageNamed: "Easy Screen Background")
    
    let timerText = SKLabelNode(fontNamed: "Arial")
    timerText.fontSize = 40
    timerText.fontColor = SKColor.white
    timerText.position = CGPoint(x: 20, y: 400)
    timerText.zPosition = 1
    
    var counter:Int = 120
    timerText.run(
        SKAction.repeatForever(
            SKAction.sequence(
                [
                    SKAction.run {
                        counter -= 1
                        timerText.text = " Time: \(counter)"
                        
                        print("\(counter)")

                        if counter <= 0 {
                            let newScene = TryAgainScreen(fileNamed: "Try Again Screen")
                            newScene?.scaleMode = .aspectFill
                            self.view?.presentScene(newScene)
                            }
                        },
                    SKAction.wait(forDuration: 1)
                ]
            )
        )
    )
    
    background.position = CGPoint(x: 0, y: 0)
    background.size.width = self.size.width
    background.size.height = self.size.height
    background.anchorPoint = CGPoint(x: 0.5,y: 0.5)
    
    let matchCardOne = SKSpriteNode(imageNamed: "Fruit Match Card")
    let matchCardTwo = SKSpriteNode(imageNamed: "Fruit Match Card")
    let matchCardThree = SKSpriteNode(imageNamed: "Fruit Match Card")
    let matchCardFour = SKSpriteNode(imageNamed: "Fruit Match Card")
    
    matchCardOne.name = "FruitMatchCard1"
    matchCardTwo.name = "FruitMatchCard2"
    matchCardThree.name = "FruitMatchCard3"
    matchCardFour.name = "FruitMatchCard4"
    
    matchCardOne.size = CGSize(width: 150, height: 300)
    matchCardTwo.size = CGSize(width: 150, height: 300)
    matchCardThree.size = CGSize(width: 150, height: 300)
    matchCardFour.size = CGSize(width: 150, height: 300)
    
    matchCardOne.zPosition = 1
    matchCardTwo.zPosition = 1
    matchCardThree.zPosition = 1
    matchCardFour.zPosition = 1
    
    matchCardOne.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    matchCardTwo.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    matchCardThree.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    matchCardFour.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    
    matchCardOne.position = CGPoint(x: -125, y: 60)
    matchCardTwo.position = CGPoint(x: -125, y: -260)
    matchCardThree.position = CGPoint(x: 70, y: 60)
    matchCardFour.position = CGPoint(x: 70 , y: -260)
    
    addChild(background)
    addChild(matchCardOne)
    addChild(matchCardTwo)
    addChild(matchCardThree)
    addChild(matchCardFour)
    addChild(timerText)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view?.isMultipleTouchEnabled = false
    let touch = touches.first
    let positionInScene = touch!.location(in: self)
    let touchedCardOneNode = self.atPoint(positionInScene)
    
    if let name = touchedCardOneNode.name {
        if name == "FruitMatchCard1" {
            let newTexture = SKTexture(imageNamed: "Apple")
            FruitMatchCard1.init(texture: newTexture)
        }
    }

    let touchTwo = touches.first
    let positionInSceneTwo = touch!.location(in: self)
    let touchedCardTwoNode = self.atPoint(positionInScene)
    
    if let name = touchedCardTwoNode.name {
        if name == "FruitMatchCard2" {
            FruitMatchCard2.init(imageNamed: "Banana")
        }
    }
        
    let touchThree = touches.first
    let positionInSceneThree = touch!.location(in: self)
    let touchedCardThreeNode = self.atPoint(positionInScene)
    if let name = touchedCardThreeNode.name {
        if name == "FruitMatchCard3" {
            FruitMatchCard3.init(imageNamed: "Apple")
        }
    }
          
    let touchFour = touches.first
    let positionInSceneFour = touch!.location(in: self)
    let touchedCardFourNode = self.atPoint(positionInScene)
    if let name = touchedCardFourNode.name {
        if name == "FruitMatchCard4" {
            FruitMatchCard4.init(imageNamed: "Banana")
        }
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    }

I’m trying to change the textures of the nodes in this part of the code. Inside the “if name == “FruitMatchCard” { } “ part of the code. However, when I launch the Xcode simulator the node’s textures aren't changing.

Any advice on how I can do this? Thanks!



Solution 1:[1]

Your fundamental problem is that when someone taps a card, you are creating a new card with the new texture and not doing anything with it. Take the following code you have:

FruitMatchCard2.init(imageNamed: "Banana")

This code creates a match card, but you don't do anything with the card.

To change the texture of the card, you must get the sprite node of the tapped card and change its texture. I see in your code you have the following variable:

let touchedCardTwoNode = self.atPoint(positionInScene)

This variable has the card that was touched. Set its texture to the texture you want to use.

touchedCardTwoNode.texture = SKTexture(imageNamed: "Banana")

My SpriteKit is a bit rusty so I can't guarantee that example will compile, but it gives you an idea of what you need to do to change the texture when tapping a card.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Swift Dev Journal